Merge "Do not initiate clip classification again when copying to profile."
diff --git a/Android.bp b/Android.bp
index 457752c..60ec7e2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -50,12 +50,8 @@
"SPDX-license-identifier-Apache-2.0",
"SPDX-license-identifier-BSD",
"SPDX-license-identifier-CC-BY",
- "SPDX-license-identifier-CPL-1.0",
- "SPDX-license-identifier-GPL",
- "SPDX-license-identifier-GPL-2.0",
"SPDX-license-identifier-MIT",
"SPDX-license-identifier-Unicode-DFS",
- "SPDX-license-identifier-W3C",
"legacy_unencumbered",
],
license_text: [
@@ -148,6 +144,7 @@
"framework-minus-apex",
"framework-appsearch.impl",
"framework-connectivity.impl",
+ "framework-connectivity-tiramisu.impl",
"framework-graphics.impl",
"framework-mediaprovider.impl",
"framework-permission.impl",
@@ -275,6 +272,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",
],
@@ -505,7 +503,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"],
@@ -513,17 +513,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)
@@ -545,15 +542,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
@@ -565,6 +553,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/METADATA b/METADATA
index 95577d8..5c3f89c 100644
--- a/METADATA
+++ b/METADATA
@@ -1,4 +1,3 @@
third_party {
- # would be NOTICE save for libs/usb/tests/accessorytest/f_accessory.h
- license_type: RESTRICTED
+ license_type: RECIPROCAL
}
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/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/api.go b/api/api.go
index 4b6ebc1..aa9e399e 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 modules_with_only_public_scope = []string{i18n, conscrypt}
// 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
@@ -183,6 +184,27 @@
ctx.CreateModule(genrule.GenRuleFactory, &props)
}
+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{}
+ modules_with_system_stubs := removeAll(modules, modules_with_only_public_scope)
+ props.Name = proptools.StringPtr("all-modules-system-stubs")
+ props.Static_libs = append(
+ transformArray(modules_with_only_public_scope, "", ".stubs"),
+ transformArray(modules_with_system_stubs, "", ".stubs.system")...)
+ props.Sdk_version = proptools.StringPtr("module_current")
+ props.Visibility = []string{"//frameworks/base"}
+ ctx.CreateModule(java.LibraryFactory, &props)
+}
+
func createMergedModuleLibStubs(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})
@@ -205,7 +227,7 @@
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})
+ bcpWithSystemApi := removeAll(bootclasspath, modules_with_only_public_scope)
tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
for i, f := range []string{"current.txt", "removed.txt"} {
@@ -253,6 +275,8 @@
createMergedStubsSrcjar(ctx, bootclasspath)
+ createMergedPublicStubs(ctx, bootclasspath)
+ createMergedSystemStubs(ctx, bootclasspath)
createMergedModuleLibStubs(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/core/api/current.txt b/core/api/current.txt
index d696bc7..a32a3a9 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,12 +25216,14 @@
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);
@@ -26634,6 +25369,7 @@
}
public abstract class PlatformVpnProfile {
+ method public final boolean getExcludeLocalRoutes();
method public final int getType();
method @NonNull public final String getTypeString();
field public static final int TYPE_IKEV2_IPSEC_PSK = 7; // 0x7
@@ -26984,65 +25720,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 {
@@ -41349,6 +40026,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 {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index b380e6d..32c711b 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);
}
}
@@ -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();
@@ -344,6 +433,7 @@
}
public class Process {
+ field public static final int NFC_UID = 1027; // 0x403
field public static final int VPN_UID = 1016; // 0x3f8
}
@@ -375,6 +465,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..61b4ada 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -316,6 +316,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 +1851,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 +1916,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 {
@@ -7523,11 +7109,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;
@@ -12325,6 +11912,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
@@ -13691,6 +13279,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
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..18ceb25 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 {
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/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/bluetooth/Attributable.java b/core/java/android/bluetooth/Attributable.java
deleted file mode 100644
index d9acbe3..0000000
--- a/core/java/android/bluetooth/Attributable.java
+++ /dev/null
@@ -1,55 +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.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.AttributionSource;
-
-import java.util.List;
-
-/**
- * Marker interface for a class which can have an {@link AttributionSource}
- * assigned to it; these are typically {@link android.os.Parcelable} classes
- * which need to be updated after crossing Binder transaction boundaries.
- *
- * @hide
- */
-public interface Attributable {
- void setAttributionSource(@NonNull AttributionSource attributionSource);
-
- static @Nullable <T extends Attributable> T setAttributionSource(
- @Nullable T attributable,
- @NonNull AttributionSource attributionSource) {
- if (attributable != null) {
- attributable.setAttributionSource(attributionSource);
- }
- return attributable;
- }
-
- static @Nullable <T extends Attributable> List<T> setAttributionSource(
- @Nullable List<T> attributableList,
- @NonNull AttributionSource attributionSource) {
- if (attributableList != null) {
- final int size = attributableList.size();
- for (int i = 0; i < size; i++) {
- setAttributionSource(attributableList.get(i), attributionSource);
- }
- }
- return attributableList;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
deleted file mode 100644
index 8b9cec1..0000000
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ /dev/null
@@ -1,1149 +0,0 @@
-/*
- * Copyright (C) 2008 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.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-
-/**
- * This class provides the public APIs to control the Bluetooth A2DP
- * profile.
- *
- * <p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothA2dp proxy object.
- *
- * <p> Android only supports one connected Bluetooth A2dp device at a time.
- * Each method is protected with its appropriate permission.
- */
-public final class BluetoothA2dp implements BluetoothProfile {
- private static final String TAG = "BluetoothA2dp";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Intent used to broadcast the change in connection state of the A2DP
- * profile.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
-
- /**
- * Intent used to broadcast the change in the Playing state of the A2DP
- * profile.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING},
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PLAYING_STATE_CHANGED =
- "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
-
- /** @hide */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED =
- "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
-
- /**
- * Intent used to broadcast the selection of a connected device as active.
- *
- * <p>This intent will have one extra:
- * <ul>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
- * be null if no device is active. </li>
- * </ul>
- *
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @UnsupportedAppUsage(trackingBug = 171933273)
- public static final String ACTION_ACTIVE_DEVICE_CHANGED =
- "android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED";
-
- /**
- * Intent used to broadcast the change in the Audio Codec state of the
- * A2DP Source profile.
- *
- * <p>This intent will have 2 extras:
- * <ul>
- * <li> {@link BluetoothCodecStatus#EXTRA_CODEC_STATUS} - The codec status. </li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently
- * connected, otherwise it is not included.</li>
- * </ul>
- *
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @UnsupportedAppUsage(trackingBug = 181103983)
- public static final String ACTION_CODEC_CONFIG_CHANGED =
- "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED";
-
- /**
- * A2DP sink device is streaming music. This state can be one of
- * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
- * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
- */
- public static final int STATE_PLAYING = 10;
-
- /**
- * A2DP sink device is NOT streaming music. This state can be one of
- * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
- * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
- */
- public static final int STATE_NOT_PLAYING = 11;
-
- /** @hide */
- @IntDef(prefix = "OPTIONAL_CODECS_", value = {
- OPTIONAL_CODECS_SUPPORT_UNKNOWN,
- OPTIONAL_CODECS_NOT_SUPPORTED,
- OPTIONAL_CODECS_SUPPORTED
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface OptionalCodecsSupportStatus {}
-
- /**
- * We don't have a stored preference for whether or not the given A2DP sink device supports
- * optional codecs.
- *
- * @hide
- */
- @SystemApi
- public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1;
-
- /**
- * The given A2DP sink device does not support optional codecs.
- *
- * @hide
- */
- @SystemApi
- public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0;
-
- /**
- * The given A2DP sink device does support optional codecs.
- *
- * @hide
- */
- @SystemApi
- public static final int OPTIONAL_CODECS_SUPPORTED = 1;
-
- /** @hide */
- @IntDef(prefix = "OPTIONAL_CODECS_PREF_", value = {
- OPTIONAL_CODECS_PREF_UNKNOWN,
- OPTIONAL_CODECS_PREF_DISABLED,
- OPTIONAL_CODECS_PREF_ENABLED
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface OptionalCodecsPreferenceStatus {}
-
- /**
- * We don't have a stored preference for whether optional codecs should be enabled or
- * disabled for the given A2DP device.
- *
- * @hide
- */
- @SystemApi
- public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1;
-
- /**
- * Optional codecs should be disabled for the given A2DP device.
- *
- * @hide
- */
- @SystemApi
- public static final int OPTIONAL_CODECS_PREF_DISABLED = 0;
-
- /**
- * Optional codecs should be enabled for the given A2DP device.
- *
- * @hide
- */
- @SystemApi
- public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
-
- /** @hide */
- @IntDef(prefix = "DYNAMIC_BUFFER_SUPPORT_", value = {
- DYNAMIC_BUFFER_SUPPORT_NONE,
- DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD,
- DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- /**
- * Indicates the supported type of Dynamic Audio Buffer is not supported.
- *
- * @hide
- */
- @SystemApi
- public static final int DYNAMIC_BUFFER_SUPPORT_NONE = 0;
-
- /**
- * Indicates the supported type of Dynamic Audio Buffer is A2DP offload.
- *
- * @hide
- */
- @SystemApi
- public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD = 1;
-
- /**
- * Indicates the supported type of Dynamic Audio Buffer is A2DP software encoding.
- *
- * @hide
- */
- @SystemApi
- public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING = 2;
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothA2dp> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.A2DP, "BluetoothA2dp",
- IBluetoothA2dp.class.getName()) {
- @Override
- public IBluetoothA2dp getServiceInterface(IBinder service) {
- return IBluetoothA2dp.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothA2dp proxy object for interacting with the local
- * Bluetooth A2DP service.
- */
- /* package */ BluetoothA2dp(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- @UnsupportedAppUsage
- /*package*/ void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothA2dp getService() {
- return mProfileConnector.getService();
- }
-
- @Override
- public void finalize() {
- // The empty finalize needs to be kept or the
- // cts signature tests would fail.
- }
-
- /**
- * Initiate connection to a profile of the remote Bluetooth device.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is already connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that
- * connection state intent for the profile will be broadcasted with
- * the state. Users can get the connection state of the profile
- * from this intent.
- *
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @UnsupportedAppUsage
- public boolean connect(BluetoothDevice device) {
- if (DBG) log("connect(" + device + ")");
- final IBluetoothA2dp service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connectWithAttribution(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate disconnection from a profile
- *
- * <p> This API will return false in scenarios like the profile on the
- * Bluetooth device is not in connected state etc. When this API returns,
- * true, it is guaranteed that the connection state change
- * intent will be broadcasted with the state. Users can get the
- * disconnection state of the profile from this intent.
- *
- * <p> If the disconnection is initiated by a remote device, the state
- * will transition from {@link #STATE_CONNECTED} to
- * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
- * host (local) device the state will transition from
- * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
- * state {@link #STATE_DISCONNECTED}. The transition to
- * {@link #STATE_DISCONNECTING} can be used to distinguish between the
- * two scenarios.
- *
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @UnsupportedAppUsage
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) log("disconnect(" + device + ")");
- final IBluetoothA2dp service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnectWithAttribution(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
- if (VDBG) log("getConnectedDevices()");
- final IBluetoothA2dp service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevicesWithAttribution(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothA2dp service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStatesWithAttribution(states,
- mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @BtProfileState int getConnectionState(BluetoothDevice device) {
- if (VDBG) log("getState(" + device + ")");
- final IBluetoothA2dp service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionStateWithAttribution(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Select a connected device as active.
- *
- * The active device selection is per profile. An active device's
- * purpose is profile-specific. For example, A2DP audio streaming
- * is to the active A2DP Sink device. If a remote device is not
- * connected, it cannot be selected as active.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is not connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that the
- * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
- * with the active device.
- *
- * @param device the remote Bluetooth device. Could be null to clear
- * the active device and stop streaming audio to a Bluetooth device.
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @UnsupportedAppUsage(trackingBug = 171933273)
- public boolean setActiveDevice(@Nullable BluetoothDevice device) {
- if (DBG) log("setActiveDevice(" + device + ")");
- final IBluetoothA2dp service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && ((device == null) || isValidDevice(device))) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setActiveDevice(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the connected device that is active.
- *
- * @return the connected device that is active or null if no device
- * is active
- * @hide
- */
- @UnsupportedAppUsage(trackingBug = 171933273)
- @Nullable
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothDevice getActiveDevice() {
- if (VDBG) log("getActiveDevice()");
- final IBluetoothA2dp service = getService();
- final BluetoothDevice defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<BluetoothDevice> recv =
- new SynchronousResultReceiver();
- service.getActiveDevice(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set priority of the profile
- *
- * <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
- *
- * @param device Paired bluetooth device
- * @param priority
- * @return true if priority is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setPriority(BluetoothDevice device, int priority) {
- if (DBG) log("setPriority(" + device + ", " + priority + ")");
- return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothA2dp service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the priority of the profile.
- *
- * <p> The priority can be any of:
- * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * @param device Bluetooth device
- * @return priority of the device
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
- public int getPriority(BluetoothDevice device) {
- if (VDBG) log("getPriority(" + device + ")");
- return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- final IBluetoothA2dp service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Checks if Avrcp device supports the absolute volume feature.
- *
- * @return true if device supports absolute volume
- * @hide
- */
- @RequiresNoPermission
- public boolean isAvrcpAbsoluteVolumeSupported() {
- if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
- final IBluetoothA2dp service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isAvrcpAbsoluteVolumeSupported(recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Tells remote device to set an absolute volume. Only if absolute volume is supported
- *
- * @param volume Absolute volume to be set on AVRCP side
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void setAvrcpAbsoluteVolume(int volume) {
- if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
- final IBluetoothA2dp service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- service.setAvrcpAbsoluteVolume(volume, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Check if A2DP profile is streaming music.
- *
- * @param device BluetoothDevice device
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isA2dpPlaying(BluetoothDevice device) {
- if (DBG) log("isA2dpPlaying(" + device + ")");
- final IBluetoothA2dp service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isA2dpPlaying(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * This function checks if the remote device is an AVCRP
- * target and thus whether we should send volume keys
- * changes or not.
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean shouldSendVolumeKeys(BluetoothDevice device) {
- if (isEnabled() && isValidDevice(device)) {
- ParcelUuid[] uuids = device.getUuids();
- if (uuids == null) return false;
-
- for (ParcelUuid uuid : uuids) {
- if (uuid.equals(BluetoothUuid.AVRCP_TARGET)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Gets the current codec status (configuration and capability).
- *
- * @param device the remote Bluetooth device.
- * @return the current codec status
- * @hide
- */
- @UnsupportedAppUsage(trackingBug = 181103983)
- @Nullable
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothCodecStatus getCodecStatus(@NonNull BluetoothDevice device) {
- if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
- verifyDeviceNotNull(device, "getCodecStatus");
- final IBluetoothA2dp service = getService();
- final BluetoothCodecStatus defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<BluetoothCodecStatus> recv =
- new SynchronousResultReceiver();
- service.getCodecStatus(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Sets the codec configuration preference.
- *
- * @param device the remote Bluetooth device.
- * @param codecConfig the codec configuration preference
- * @hide
- */
- @UnsupportedAppUsage(trackingBug = 181103983)
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void setCodecConfigPreference(@NonNull BluetoothDevice device,
- @NonNull BluetoothCodecConfig codecConfig) {
- if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
- verifyDeviceNotNull(device, "setCodecConfigPreference");
- if (codecConfig == null) {
- Log.e(TAG, "setCodecConfigPreference: Codec config can't be null");
- throw new IllegalArgumentException("codecConfig cannot be null");
- }
- final IBluetoothA2dp service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- service.setCodecConfigPreference(device, codecConfig, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Enables the optional codecs.
- *
- * @param device the remote Bluetooth device.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void enableOptionalCodecs(@NonNull BluetoothDevice device) {
- if (DBG) Log.d(TAG, "enableOptionalCodecs(" + device + ")");
- verifyDeviceNotNull(device, "enableOptionalCodecs");
- enableDisableOptionalCodecs(device, true);
- }
-
- /**
- * Disables the optional codecs.
- *
- * @param device the remote Bluetooth device.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void disableOptionalCodecs(@NonNull BluetoothDevice device) {
- if (DBG) Log.d(TAG, "disableOptionalCodecs(" + device + ")");
- verifyDeviceNotNull(device, "disableOptionalCodecs");
- enableDisableOptionalCodecs(device, false);
- }
-
- /**
- * Enables or disables the optional codecs.
- *
- * @param device the remote Bluetooth device.
- * @param enable if true, enable the optional codecs, other disable them
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private void enableDisableOptionalCodecs(BluetoothDevice device, boolean enable) {
- final IBluetoothA2dp service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- if (enable) {
- service.enableOptionalCodecs(device, mAttributionSource);
- } else {
- service.disableOptionalCodecs(device, mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Returns whether this device supports optional codecs.
- *
- * @param device The device to check
- * @return one of OPTIONAL_CODECS_SUPPORT_UNKNOWN, OPTIONAL_CODECS_NOT_SUPPORTED, or
- * OPTIONAL_CODECS_SUPPORTED.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @OptionalCodecsSupportStatus
- public int isOptionalCodecsSupported(@NonNull BluetoothDevice device) {
- if (DBG) log("isOptionalCodecsSupported(" + device + ")");
- verifyDeviceNotNull(device, "isOptionalCodecsSupported");
- final IBluetoothA2dp service = getService();
- final int defaultValue = OPTIONAL_CODECS_SUPPORT_UNKNOWN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.supportsOptionalCodecs(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns whether this device should have optional codecs enabled.
- *
- * @param device The device in question.
- * @return one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or
- * OPTIONAL_CODECS_PREF_DISABLED.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @OptionalCodecsPreferenceStatus
- public int isOptionalCodecsEnabled(@NonNull BluetoothDevice device) {
- if (DBG) log("isOptionalCodecsEnabled(" + device + ")");
- verifyDeviceNotNull(device, "isOptionalCodecsEnabled");
- final IBluetoothA2dp service = getService();
- final int defaultValue = OPTIONAL_CODECS_PREF_UNKNOWN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getOptionalCodecsEnabled(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Sets a persistent preference for whether a given device should have optional codecs enabled.
- *
- * @param device The device to set this preference for.
- * @param value Whether the optional codecs should be enabled for this device. This should be
- * one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or
- * OPTIONAL_CODECS_PREF_DISABLED.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void setOptionalCodecsEnabled(@NonNull BluetoothDevice device,
- @OptionalCodecsPreferenceStatus int value) {
- if (DBG) log("setOptionalCodecsEnabled(" + device + ")");
- verifyDeviceNotNull(device, "setOptionalCodecsEnabled");
- if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN
- && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED
- && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) {
- Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);
- return;
- }
- final IBluetoothA2dp service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- service.setOptionalCodecsEnabled(device, value, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Get the supported type of the Dynamic Audio Buffer.
- * <p>Possible return values are
- * {@link #DYNAMIC_BUFFER_SUPPORT_NONE},
- * {@link #DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD},
- * {@link #DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING}.
- *
- * @return supported type of Dynamic Audio Buffer feature
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @Type int getDynamicBufferSupport() {
- if (VDBG) log("getDynamicBufferSupport()");
- final IBluetoothA2dp service = getService();
- final int defaultValue = DYNAMIC_BUFFER_SUPPORT_NONE;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getDynamicBufferSupport(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Return the record of {@link BufferConstraints} object that
- * has the default/maximum/minimum audio buffer. This can be used to inform what the controller
- * has support for the audio buffer.
- *
- * @return a record with {@link BufferConstraints} or null if report is unavailable
- * or unsupported
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @Nullable BufferConstraints getBufferConstraints() {
- if (VDBG) log("getBufferConstraints()");
- final IBluetoothA2dp service = getService();
- final BufferConstraints defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<BufferConstraints> recv =
- new SynchronousResultReceiver();
- service.getBufferConstraints(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set Dynamic Audio Buffer Size.
- *
- * @param codec audio codec
- * @param value buffer millis
- * @return true to indicate success, or false on immediate error
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setBufferLengthMillis(@BluetoothCodecConfig.SourceCodecType int codec,
- int value) {
- if (VDBG) log("setBufferLengthMillis(" + codec + ", " + value + ")");
- if (value < 0) {
- Log.e(TAG, "Trying to set audio buffer length to a negative value: " + value);
- return false;
- }
- final IBluetoothA2dp service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setBufferLengthMillis(codec, value, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Helper for converting a state to a string.
- *
- * For debug use only - strings are not internationalized.
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
- public static String stateToString(int state) {
- switch (state) {
- case STATE_DISCONNECTED:
- return "disconnected";
- case STATE_CONNECTING:
- return "connecting";
- case STATE_CONNECTED:
- return "connected";
- case STATE_DISCONNECTING:
- return "disconnecting";
- case STATE_PLAYING:
- return "playing";
- case STATE_NOT_PLAYING:
- return "not playing";
- default:
- return "<unknown state " + state + ">";
- }
- }
-
- private boolean isEnabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
- return false;
- }
-
- private void verifyDeviceNotNull(BluetoothDevice device, String methodName) {
- if (device == null) {
- Log.e(TAG, methodName + ": device param is null");
- throw new IllegalArgumentException("Device cannot be null");
- }
- }
-
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
deleted file mode 100755
index 5941681..0000000
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the Bluetooth A2DP Sink
- * profile.
- *
- * <p>BluetoothA2dpSink is a proxy object for controlling the Bluetooth A2DP Sink
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothA2dpSink proxy object.
- *
- * @hide
- */
-@SystemApi
-public final class BluetoothA2dpSink implements BluetoothProfile {
- private static final String TAG = "BluetoothA2dpSink";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Intent used to broadcast the change in connection state of the A2DP Sink
- * profile.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- *
- * @hide
- */
- @SystemApi
- @SuppressLint("ActionValue")
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothA2dpSink> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.A2DP_SINK,
- "BluetoothA2dpSink", IBluetoothA2dpSink.class.getName()) {
- @Override
- public IBluetoothA2dpSink getServiceInterface(IBinder service) {
- return IBluetoothA2dpSink.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothA2dp proxy object for interacting with the local
- * Bluetooth A2DP service.
- */
- /* package */ BluetoothA2dpSink(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- /*package*/ void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothA2dpSink getService() {
- return mProfileConnector.getService();
- }
-
- @Override
- public void finalize() {
- close();
- }
-
- /**
- * Initiate connection to a profile of the remote bluetooth device.
- *
- * <p> Currently, the system supports only 1 connection to the
- * A2DP profile. The API will automatically disconnect connected
- * devices before connecting.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is already connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that
- * connection state intent for the profile will be broadcasted with
- * the state. Users can get the connection state of the profile
- * from this intent.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean connect(BluetoothDevice device) {
- if (DBG) log("connect(" + device + ")");
- final IBluetoothA2dpSink service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate disconnection from a profile
- *
- * <p> This API will return false in scenarios like the profile on the
- * Bluetooth device is not in connected state etc. When this API returns,
- * true, it is guaranteed that the connection state change
- * intent will be broadcasted with the state. Users can get the
- * disconnection state of the profile from this intent.
- *
- * <p> If the disconnection is initiated by a remote device, the state
- * will transition from {@link #STATE_CONNECTED} to
- * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
- * host (local) device the state will transition from
- * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
- * state {@link #STATE_DISCONNECTED}. The transition to
- * {@link #STATE_DISCONNECTING} can be used to distinguish between the
- * two scenarios.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) log("disconnect(" + device + ")");
- final IBluetoothA2dpSink service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
- if (VDBG) log("getConnectedDevices()");
- final IBluetoothA2dpSink service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothA2dpSink service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
- if (VDBG) log("getConnectionState(" + device + ")");
- final IBluetoothA2dpSink service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the current audio configuration for the A2DP source device,
- * or null if the device has no audio configuration
- *
- * @param device Remote bluetooth device.
- * @return audio configuration for the device, or null
- *
- * {@see BluetoothAudioConfig}
- *
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
- if (VDBG) log("getAudioConfig(" + device + ")");
- final IBluetoothA2dpSink service = getService();
- final BluetoothAudioConfig defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<BluetoothAudioConfig> recv =
- new SynchronousResultReceiver();
- service.getAudioConfig(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set priority of the profile
- *
- * <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
- *
- * @param device Paired bluetooth device
- * @param priority
- * @return true if priority is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setPriority(BluetoothDevice device, int priority) {
- if (DBG) log("setPriority(" + device + ", " + priority + ")");
- return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothA2dpSink service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the priority of the profile.
- *
- * <p> The priority can be any of:
- * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * @param device Bluetooth device
- * @return priority of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public int getPriority(BluetoothDevice device) {
- if (VDBG) log("getPriority(" + device + ")");
- return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- final IBluetoothA2dpSink service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Check if audio is playing on the bluetooth device (A2DP profile is streaming music).
- *
- * @param device BluetoothDevice device
- * @return true if audio is playing (A2dp is streaming music), false otherwise
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean isAudioPlaying(@NonNull BluetoothDevice device) {
- if (VDBG) log("isAudioPlaying(" + device + ")");
- final IBluetoothA2dpSink service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isA2dpPlaying(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Helper for converting a state to a string.
- *
- * For debug use only - strings are not internationalized.
- *
- * @hide
- */
- public static String stateToString(int state) {
- switch (state) {
- case STATE_DISCONNECTED:
- return "disconnected";
- case STATE_CONNECTING:
- return "connecting";
- case STATE_CONNECTED:
- return "connected";
- case STATE_DISCONNECTING:
- return "disconnecting";
- case BluetoothA2dp.STATE_PLAYING:
- return "playing";
- case BluetoothA2dp.STATE_NOT_PLAYING:
- return "not playing";
- default:
- return "<unknown state " + state + ">";
- }
- }
-
- private boolean isEnabled() {
- return mAdapter.getState() == BluetoothAdapter.STATE_ON;
- }
-
- private static boolean isValidDevice(BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
deleted file mode 100644
index c17a7b4..0000000
--- a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.ElapsedRealtimeLong;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Record of energy and activity information from controller and
- * underlying bt stack state.Timestamp the record with system
- * time.
- *
- * @hide
- */
-@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
-public final class BluetoothActivityEnergyInfo implements Parcelable {
- private final long mTimestamp;
- private int mBluetoothStackState;
- private long mControllerTxTimeMs;
- private long mControllerRxTimeMs;
- private long mControllerIdleTimeMs;
- private long mControllerEnergyUsed;
- private List<UidTraffic> mUidTraffic;
-
- /** @hide */
- @IntDef(prefix = { "BT_STACK_STATE_" }, value = {
- BT_STACK_STATE_INVALID,
- BT_STACK_STATE_STATE_ACTIVE,
- BT_STACK_STATE_STATE_SCANNING,
- BT_STACK_STATE_STATE_IDLE
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface BluetoothStackState {}
-
- public static final int BT_STACK_STATE_INVALID = 0;
- public static final int BT_STACK_STATE_STATE_ACTIVE = 1;
- public static final int BT_STACK_STATE_STATE_SCANNING = 2;
- public static final int BT_STACK_STATE_STATE_IDLE = 3;
-
- /** @hide */
- public BluetoothActivityEnergyInfo(long timestamp, int stackState,
- long txTime, long rxTime, long idleTime, long energyUsed) {
- mTimestamp = timestamp;
- mBluetoothStackState = stackState;
- mControllerTxTimeMs = txTime;
- mControllerRxTimeMs = rxTime;
- mControllerIdleTimeMs = idleTime;
- mControllerEnergyUsed = energyUsed;
- }
-
- /** @hide */
- private BluetoothActivityEnergyInfo(Parcel in) {
- mTimestamp = in.readLong();
- mBluetoothStackState = in.readInt();
- mControllerTxTimeMs = in.readLong();
- mControllerRxTimeMs = in.readLong();
- mControllerIdleTimeMs = in.readLong();
- mControllerEnergyUsed = in.readLong();
- mUidTraffic = in.createTypedArrayList(UidTraffic.CREATOR);
- }
-
- /** @hide */
- @Override
- public String toString() {
- return "BluetoothActivityEnergyInfo{"
- + " mTimestamp=" + mTimestamp
- + " mBluetoothStackState=" + mBluetoothStackState
- + " mControllerTxTimeMs=" + mControllerTxTimeMs
- + " mControllerRxTimeMs=" + mControllerRxTimeMs
- + " mControllerIdleTimeMs=" + mControllerIdleTimeMs
- + " mControllerEnergyUsed=" + mControllerEnergyUsed
- + " mUidTraffic=" + mUidTraffic
- + " }";
- }
-
- public static final @NonNull Parcelable.Creator<BluetoothActivityEnergyInfo> CREATOR =
- new Parcelable.Creator<BluetoothActivityEnergyInfo>() {
- public BluetoothActivityEnergyInfo createFromParcel(Parcel in) {
- return new BluetoothActivityEnergyInfo(in);
- }
-
- public BluetoothActivityEnergyInfo[] newArray(int size) {
- return new BluetoothActivityEnergyInfo[size];
- }
- };
-
- /** @hide */
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeLong(mTimestamp);
- out.writeInt(mBluetoothStackState);
- out.writeLong(mControllerTxTimeMs);
- out.writeLong(mControllerRxTimeMs);
- out.writeLong(mControllerIdleTimeMs);
- out.writeLong(mControllerEnergyUsed);
- out.writeTypedList(mUidTraffic);
- }
-
- /** @hide */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /**
- * Get the Bluetooth stack state associated with the energy info.
- *
- * @return one of {@link #BluetoothStackState} states
- */
- @BluetoothStackState
- public int getBluetoothStackState() {
- return mBluetoothStackState;
- }
-
- /**
- * @return tx time in ms
- */
- public long getControllerTxTimeMillis() {
- return mControllerTxTimeMs;
- }
-
- /**
- * @return rx time in ms
- */
- public long getControllerRxTimeMillis() {
- return mControllerRxTimeMs;
- }
-
- /**
- * @return idle time in ms
- */
- public long getControllerIdleTimeMillis() {
- return mControllerIdleTimeMs;
- }
-
- /**
- * Get the product of current (mA), voltage (V), and time (ms).
- *
- * @return energy used
- */
- public long getControllerEnergyUsed() {
- return mControllerEnergyUsed;
- }
-
- /**
- * @return timestamp (real time elapsed in milliseconds since boot) of record creation
- */
- public @ElapsedRealtimeLong long getTimestampMillis() {
- return mTimestamp;
- }
-
- /**
- * Get the {@link List} of each application {@link android.bluetooth.UidTraffic}.
- *
- * @return current {@link List} of {@link android.bluetooth.UidTraffic}
- */
- public @NonNull List<UidTraffic> getUidTraffic() {
- if (mUidTraffic == null) {
- return Collections.emptyList();
- }
- return mUidTraffic;
- }
-
- /** @hide */
- public void setUidTraffic(List<UidTraffic> traffic) {
- mUidTraffic = traffic;
- }
-
- /**
- * @return true if the record Tx time, Rx time, and Idle time are more than 0.
- */
- public boolean isValid() {
- return ((mControllerTxTimeMs >= 0) && (mControllerRxTimeMs >= 0)
- && (mControllerIdleTimeMs >= 0));
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
deleted file mode 100644
index f94ee85..0000000
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ /dev/null
@@ -1,4434 +0,0 @@
-/*
- * Copyright 2009-2016 The Android Open Source Project
- * Copyright 2015 Samsung LSI
- *
- * 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.bluetooth;
-
-import static java.util.Objects.requireNonNull;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi; //import android.app.PropertyInvalidatedCache;
-import android.bluetooth.BluetoothDevice.Transport;
-import android.bluetooth.BluetoothProfile.ConnectionPolicy;
-import android.bluetooth.annotations.RequiresBluetoothAdvertisePermission;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
-import android.bluetooth.annotations.RequiresBluetoothScanPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.bluetooth.le.BluetoothLeAdvertiser;
-import android.bluetooth.le.BluetoothLeScanner;
-import android.bluetooth.le.PeriodicAdvertisingManager;
-import android.bluetooth.le.ScanCallback;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanRecord;
-import android.bluetooth.le.ScanResult;
-import android.bluetooth.le.ScanSettings;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Binder;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.ServiceManager;
-import android.sysprop.BluetoothProperties;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-import java.util.WeakHashMap;
-import java.util.concurrent.Executor;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-/**
- * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
- * lets you perform fundamental Bluetooth tasks, such as initiate
- * device discovery, query a list of bonded (paired) devices,
- * instantiate a {@link BluetoothDevice} using a known MAC address, and create
- * a {@link BluetoothServerSocket} to listen for connection requests from other
- * devices, and start a scan for Bluetooth LE devices.
- *
- * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
- * adapter, call the {@link BluetoothManager#getAdapter} function on {@link BluetoothManager}.
- * On JELLY_BEAN_MR1 and below you will need to use the static {@link #getDefaultAdapter}
- * method instead.
- * </p><p>
- * Fundamentally, this is your starting point for all
- * Bluetooth actions. Once you have the local adapter, you can get a set of
- * {@link BluetoothDevice} objects representing all paired devices with
- * {@link #getBondedDevices()}; start device discovery with
- * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
- * listen for incoming RFComm connection requests with {@link
- * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
- * Channels (CoC) connection requests with {@link #listenUsingL2capChannel()}; or start a scan for
- * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
- * </p>
- * <p>This class is thread safe.</p>
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>
- * For more information about using Bluetooth, read the <a href=
- * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
- * guide.
- * </p>
- * </div>
- *
- * {@see BluetoothDevice}
- * {@see BluetoothServerSocket}
- */
-public final class BluetoothAdapter {
- private static final String TAG = "BluetoothAdapter";
- private static final String DESCRIPTOR = "android.bluetooth.BluetoothAdapter";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Default MAC address reported to a client that does not have the
- * android.permission.LOCAL_MAC_ADDRESS permission.
- *
- * @hide
- */
- public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
-
- /**
- * Sentinel error value for this class. Guaranteed to not equal any other
- * integer constant in this class. Provided as a convenience for functions
- * that require a sentinel error value, for example:
- * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
- * BluetoothAdapter.ERROR)</code>
- */
- public static final int ERROR = Integer.MIN_VALUE;
-
- /**
- * Broadcast Action: The state of the local Bluetooth adapter has been
- * changed.
- * <p>For example, Bluetooth has been turned on or off.
- * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
- * #EXTRA_PREVIOUS_STATE} containing the new and old states
- * respectively.
- */
- @RequiresLegacyBluetoothPermission
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
- ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
-
- /**
- * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
- * intents to request the current power state. Possible values are:
- * {@link #STATE_OFF},
- * {@link #STATE_TURNING_ON},
- * {@link #STATE_ON},
- * {@link #STATE_TURNING_OFF},
- */
- public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
- /**
- * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
- * intents to request the previous power state. Possible values are:
- * {@link #STATE_OFF},
- * {@link #STATE_TURNING_ON},
- * {@link #STATE_ON},
- * {@link #STATE_TURNING_OFF}
- */
- public static final String EXTRA_PREVIOUS_STATE =
- "android.bluetooth.adapter.extra.PREVIOUS_STATE";
-
- /** @hide */
- @IntDef(prefix = { "STATE_" }, value = {
- STATE_OFF,
- STATE_TURNING_ON,
- STATE_ON,
- STATE_TURNING_OFF,
- STATE_BLE_TURNING_ON,
- STATE_BLE_ON,
- STATE_BLE_TURNING_OFF
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface AdapterState {}
-
- /**
- * Indicates the local Bluetooth adapter is off.
- */
- public static final int STATE_OFF = 10;
- /**
- * Indicates the local Bluetooth adapter is turning on. However local
- * clients should wait for {@link #STATE_ON} before attempting to
- * use the adapter.
- */
- public static final int STATE_TURNING_ON = 11;
- /**
- * Indicates the local Bluetooth adapter is on, and ready for use.
- */
- public static final int STATE_ON = 12;
- /**
- * Indicates the local Bluetooth adapter is turning off. Local clients
- * should immediately attempt graceful disconnection of any remote links.
- */
- public static final int STATE_TURNING_OFF = 13;
-
- /**
- * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
- *
- * @hide
- */
- public static final int STATE_BLE_TURNING_ON = 14;
-
- /**
- * Indicates the local Bluetooth adapter is in LE only mode.
- *
- * @hide
- */
- public static final int STATE_BLE_ON = 15;
-
- /**
- * Indicates the local Bluetooth adapter is turning off LE only mode.
- *
- * @hide
- */
- public static final int STATE_BLE_TURNING_OFF = 16;
-
- /**
- * UUID of the GATT Read Characteristics for LE_PSM value.
- *
- * @hide
- */
- public static final UUID LE_PSM_CHARACTERISTIC_UUID =
- UUID.fromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
-
- /**
- * Human-readable string helper for AdapterState
- *
- * @hide
- */
- public static String nameForState(@AdapterState int state) {
- switch (state) {
- case STATE_OFF:
- return "OFF";
- case STATE_TURNING_ON:
- return "TURNING_ON";
- case STATE_ON:
- return "ON";
- case STATE_TURNING_OFF:
- return "TURNING_OFF";
- case STATE_BLE_TURNING_ON:
- return "BLE_TURNING_ON";
- case STATE_BLE_ON:
- return "BLE_ON";
- case STATE_BLE_TURNING_OFF:
- return "BLE_TURNING_OFF";
- default:
- return "?!?!? (" + state + ")";
- }
- }
-
- /**
- * Activity Action: Show a system activity that requests discoverable mode.
- * This activity will also request the user to turn on Bluetooth if it
- * is not currently enabled.
- * <p>Discoverable mode is equivalent to {@link
- * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
- * this Bluetooth adapter when they perform a discovery.
- * <p>For privacy, Android is not discoverable by default.
- * <p>The sender of this Intent can optionally use extra field {@link
- * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
- * discoverability. Currently the default duration is 120 seconds, and
- * maximum duration is capped at 300 seconds for each request.
- * <p>Notification of the result of this activity is posted using the
- * {@link android.app.Activity#onActivityResult} callback. The
- * <code>resultCode</code>
- * will be the duration (in seconds) of discoverability or
- * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
- * discoverability or an error has occurred.
- * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
- * for global notification whenever the scan mode changes. For example, an
- * application can be notified when the device has ended discoverability.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
- ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
-
- /**
- * Used as an optional int extra field in {@link
- * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
- * for discoverability in seconds. The current default is 120 seconds, and
- * requests over 300 seconds will be capped. These values could change.
- */
- public static final String EXTRA_DISCOVERABLE_DURATION =
- "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
-
- /**
- * Activity Action: Show a system activity that allows the user to turn on
- * Bluetooth.
- * <p>This system activity will return once Bluetooth has completed turning
- * on, or the user has decided not to turn Bluetooth on.
- * <p>Notification of the result of this activity is posted using the
- * {@link android.app.Activity#onActivityResult} callback. The
- * <code>resultCode</code>
- * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
- * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
- * has rejected the request or an error has occurred.
- * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
- * for global notification whenever Bluetooth is turned on or off.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
- ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
-
- /**
- * Activity Action: Show a system activity that allows the user to turn off
- * Bluetooth. This is used only if permission review is enabled which is for
- * apps targeting API less than 23 require a permission review before any of
- * the app's components can run.
- * <p>This system activity will return once Bluetooth has completed turning
- * off, or the user has decided not to turn Bluetooth off.
- * <p>Notification of the result of this activity is posted using the
- * {@link android.app.Activity#onActivityResult} callback. The
- * <code>resultCode</code>
- * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
- * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
- * has rejected the request or an error has occurred.
- * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
- * for global notification whenever Bluetooth is turned on or off.
- *
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
- ACTION_REQUEST_DISABLE = "android.bluetooth.adapter.action.REQUEST_DISABLE";
-
- /**
- * Activity Action: Show a system activity that allows user to enable BLE scans even when
- * Bluetooth is turned off.<p>
- *
- * Notification of result of this activity is posted using
- * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
- * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
- * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
- * error occurred.
- *
- * @hide
- */
- @SystemApi
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
- "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
-
- /**
- * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
- * has changed.
- * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
- * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
- * respectively.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
- ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
-
- /**
- * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
- * intents to request the current scan mode. Possible values are:
- * {@link #SCAN_MODE_NONE},
- * {@link #SCAN_MODE_CONNECTABLE},
- * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
- */
- public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
- /**
- * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
- * intents to request the previous scan mode. Possible values are:
- * {@link #SCAN_MODE_NONE},
- * {@link #SCAN_MODE_CONNECTABLE},
- * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
- */
- public static final String EXTRA_PREVIOUS_SCAN_MODE =
- "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
-
- /** @hide */
- @IntDef(prefix = { "SCAN_" }, value = {
- SCAN_MODE_NONE,
- SCAN_MODE_CONNECTABLE,
- SCAN_MODE_CONNECTABLE_DISCOVERABLE
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ScanMode {}
-
- /**
- * Indicates that both inquiry scan and page scan are disabled on the local
- * Bluetooth adapter. Therefore this device is neither discoverable
- * nor connectable from remote Bluetooth devices.
- */
- public static final int SCAN_MODE_NONE = 20;
- /**
- * Indicates that inquiry scan is disabled, but page scan is enabled on the
- * local Bluetooth adapter. Therefore this device is not discoverable from
- * remote Bluetooth devices, but is connectable from remote devices that
- * have previously discovered this device.
- */
- public static final int SCAN_MODE_CONNECTABLE = 21;
- /**
- * Indicates that both inquiry scan and page scan are enabled on the local
- * Bluetooth adapter. Therefore this device is both discoverable and
- * connectable from remote Bluetooth devices.
- */
- public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
-
- /**
- * Device only has a display.
- *
- * @hide
- */
- public static final int IO_CAPABILITY_OUT = 0;
-
- /**
- * Device has a display and the ability to input Yes/No.
- *
- * @hide
- */
- public static final int IO_CAPABILITY_IO = 1;
-
- /**
- * Device only has a keyboard for entry but no display.
- *
- * @hide
- */
- public static final int IO_CAPABILITY_IN = 2;
-
- /**
- * Device has no Input or Output capability.
- *
- * @hide
- */
- public static final int IO_CAPABILITY_NONE = 3;
-
- /**
- * Device has a display and a full keyboard.
- *
- * @hide
- */
- public static final int IO_CAPABILITY_KBDISP = 4;
-
- /**
- * Maximum range value for Input/Output capabilities.
- *
- * <p>This should be updated when adding a new Input/Output capability. Other code
- * like validation depends on this being accurate.
- *
- * @hide
- */
- public static final int IO_CAPABILITY_MAX = 5;
-
- /**
- * The Input/Output capability of the device is unknown.
- *
- * @hide
- */
- public static final int IO_CAPABILITY_UNKNOWN = 255;
-
- /** @hide */
- @IntDef({IO_CAPABILITY_OUT, IO_CAPABILITY_IO, IO_CAPABILITY_IN, IO_CAPABILITY_NONE,
- IO_CAPABILITY_KBDISP})
- @Retention(RetentionPolicy.SOURCE)
- public @interface IoCapability {}
-
- /** @hide */
- @IntDef(prefix = "ACTIVE_DEVICE_", value = {ACTIVE_DEVICE_AUDIO,
- ACTIVE_DEVICE_PHONE_CALL, ACTIVE_DEVICE_ALL})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ActiveDeviceUse {}
-
- /**
- * Use the specified device for audio (a2dp and hearing aid profile)
- *
- * @hide
- */
- @SystemApi
- public static final int ACTIVE_DEVICE_AUDIO = 0;
-
- /**
- * Use the specified device for phone calls (headset profile and hearing
- * aid profile)
- *
- * @hide
- */
- @SystemApi
- public static final int ACTIVE_DEVICE_PHONE_CALL = 1;
-
- /**
- * Use the specified device for a2dp, hearing aid profile, and headset profile
- *
- * @hide
- */
- @SystemApi
- public static final int ACTIVE_DEVICE_ALL = 2;
-
- /** @hide */
- @IntDef({BluetoothProfile.HEADSET, BluetoothProfile.A2DP,
- BluetoothProfile.HEARING_AID})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ActiveDeviceProfile {}
-
- /**
- * Broadcast Action: The local Bluetooth adapter has started the remote
- * device discovery process.
- * <p>This usually involves an inquiry scan of about 12 seconds, followed
- * by a page scan of each new device to retrieve its Bluetooth name.
- * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
- * remote Bluetooth devices are found.
- * <p>Device discovery is a heavyweight procedure. New connections to
- * remote Bluetooth devices should not be attempted while discovery is in
- * progress, and existing connections will experience limited bandwidth
- * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
- * discovery.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
- ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
- /**
- * Broadcast Action: The local Bluetooth adapter has finished the device
- * discovery process.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
- ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
-
- /**
- * Broadcast Action: The local Bluetooth adapter has changed its friendly
- * Bluetooth name.
- * <p>This name is visible to remote Bluetooth devices.
- * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
- * the name.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
- ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
- /**
- * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
- * intents to request the local Bluetooth name.
- */
- public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
-
- /**
- * Intent used to broadcast the change in connection state of the local
- * Bluetooth adapter to a profile of the remote device. When the adapter is
- * not connected to any profiles of any remote devices and it attempts a
- * connection to a profile this intent will be sent. Once connected, this intent
- * will not be sent for any more connection attempts to any profiles of any
- * remote device. When the adapter disconnects from the last profile its
- * connected to of any remote device, this intent will be sent.
- *
- * <p> This intent is useful for applications that are only concerned about
- * whether the local adapter is connected to any profile of any device and
- * are not really concerned about which profile. For example, an application
- * which displays an icon to display whether Bluetooth is connected or not
- * can use this intent.
- *
- * <p>This intent will have 3 extras:
- * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
- * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
- * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
- *
- * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
- * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
- ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
-
- /**
- * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
- *
- * This extra represents the current connection state.
- */
- public static final String EXTRA_CONNECTION_STATE =
- "android.bluetooth.adapter.extra.CONNECTION_STATE";
-
- /**
- * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
- *
- * This extra represents the previous connection state.
- */
- public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
- "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
-
- /**
- * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
- *
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @SystemApi public static final String ACTION_BLE_STATE_CHANGED =
- "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
-
- /**
- * Intent used to broadcast the change in the Bluetooth address
- * of the local Bluetooth adapter.
- * <p>Always contains the extra field {@link
- * #EXTRA_BLUETOOTH_ADDRESS} containing the Bluetooth address.
- *
- * Note: only system level processes are allowed to send this
- * defined broadcast.
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED =
- "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED";
-
- /**
- * Used as a String extra field in {@link
- * #ACTION_BLUETOOTH_ADDRESS_CHANGED} intent to store the local
- * Bluetooth address.
- *
- * @hide
- */
- public static final String EXTRA_BLUETOOTH_ADDRESS =
- "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS";
-
- /**
- * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
- * by BLE Always on enabled application to know the ACL_CONNECTED event
- * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
- * as Bluetooth LE is the only feature available in STATE_BLE_ON
- *
- * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
- * works in Bluetooth state STATE_ON
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BLE_ACL_CONNECTED =
- "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
-
- /**
- * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
- * by BLE Always on enabled application to know the ACL_DISCONNECTED event
- * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
- * LE is the only feature available in STATE_BLE_ON
- *
- * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
- * works in Bluetooth state STATE_ON
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BLE_ACL_DISCONNECTED =
- "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
-
- /** The profile is in disconnected state */
- public static final int STATE_DISCONNECTED =
- 0; //BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
- /** The profile is in connecting state */
- public static final int STATE_CONNECTING = 1; //BluetoothProtoEnums.CONNECTION_STATE_CONNECTING;
- /** The profile is in connected state */
- public static final int STATE_CONNECTED = 2; //BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
- /** The profile is in disconnecting state */
- public static final int STATE_DISCONNECTING =
- 3; //BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING;
-
- /** @hide */
- public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
- private final IBinder mToken;
-
-
- /**
- * When creating a ServerSocket using listenUsingRfcommOn() or
- * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
- * a ServerSocket that auto assigns a channel number to the first
- * bluetooth socket.
- * The channel number assigned to this first Bluetooth Socket will
- * be stored in the ServerSocket, and reused for subsequent Bluetooth
- * sockets.
- *
- * @hide
- */
- public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
-
-
- private static final int ADDRESS_LENGTH = 17;
-
- /**
- * Lazily initialized singleton. Guaranteed final after first object
- * constructed.
- */
- private static BluetoothAdapter sAdapter;
-
- private BluetoothLeScanner mBluetoothLeScanner;
- private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
- private PeriodicAdvertisingManager mPeriodicAdvertisingManager;
-
- private final IBluetoothManager mManagerService;
- private final AttributionSource mAttributionSource;
-
- // Yeah, keeping both mService and sService isn't pretty, but it's too late
- // in the current release for a major refactoring, so we leave them both
- // intact until this can be cleaned up in a future release
-
- @UnsupportedAppUsage
- @GuardedBy("mServiceLock")
- private IBluetooth mService;
- private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
-
- @GuardedBy("sServiceLock")
- private static boolean sServiceRegistered;
- @GuardedBy("sServiceLock")
- private static IBluetooth sService;
- private static final Object sServiceLock = new Object();
-
- private final Object mLock = new Object();
- private final Map<LeScanCallback, ScanCallback> mLeScanClients;
- private final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
- mMetadataListeners = new HashMap<>();
- private final Map<BluetoothConnectionCallback, Executor>
- mBluetoothConnectionCallbackExecutorMap = new HashMap<>();
-
- /**
- * Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
- * implementation.
- */
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private final IBluetoothMetadataListener mBluetoothMetadataListener =
- new IBluetoothMetadataListener.Stub() {
- @Override
- public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) {
- Attributable.setAttributionSource(device, mAttributionSource);
- synchronized (mMetadataListeners) {
- if (mMetadataListeners.containsKey(device)) {
- List<Pair<OnMetadataChangedListener, Executor>> list =
- mMetadataListeners.get(device);
- for (Pair<OnMetadataChangedListener, Executor> pair : list) {
- OnMetadataChangedListener listener = pair.first;
- Executor executor = pair.second;
- executor.execute(() -> {
- listener.onMetadataChanged(device, key, value);
- });
- }
- }
- }
- return;
- }
- };
-
- /**
- * Get a handle to the default local Bluetooth adapter.
- * <p>
- * Currently Android only supports one Bluetooth adapter, but the API could
- * be extended to support more. This will always return the default adapter.
- * </p>
- *
- * @return the default local adapter, or null if Bluetooth is not supported
- * on this hardware platform
- * @deprecated this method will continue to work, but developers are
- * strongly encouraged to migrate to using
- * {@link BluetoothManager#getAdapter()}, since that approach
- * enables support for {@link Context#createAttributionContext}.
- */
- @Deprecated
- @RequiresNoPermission
- public static synchronized BluetoothAdapter getDefaultAdapter() {
- if (sAdapter == null) {
- sAdapter = createAdapter(AttributionSource.myAttributionSource());
- }
- return sAdapter;
- }
-
- /** {@hide} */
- public static BluetoothAdapter createAdapter(AttributionSource attributionSource) {
- IBinder binder = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
- if (binder != null) {
- return new BluetoothAdapter(IBluetoothManager.Stub.asInterface(binder),
- attributionSource);
- } else {
- Log.e(TAG, "Bluetooth binder is null");
- return null;
- }
- }
-
- /**
- * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
- */
- BluetoothAdapter(IBluetoothManager managerService, AttributionSource attributionSource) {
- mManagerService = Objects.requireNonNull(managerService);
- mAttributionSource = Objects.requireNonNull(attributionSource);
- synchronized (mServiceLock.writeLock()) {
- mService = getBluetoothService(mManagerCallback);
- }
- mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
- mToken = new Binder(DESCRIPTOR);
- }
-
- /**
- * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
- * address.
- * <p>Valid Bluetooth hardware addresses must be upper case, in a format
- * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
- * available to validate a Bluetooth address.
- * <p>A {@link BluetoothDevice} will always be returned for a valid
- * hardware address, even if this adapter has never seen that device.
- *
- * @param address valid Bluetooth MAC address
- * @throws IllegalArgumentException if address is invalid
- */
- @RequiresNoPermission
- public BluetoothDevice getRemoteDevice(String address) {
- final BluetoothDevice res = new BluetoothDevice(address);
- res.setAttributionSource(mAttributionSource);
- return res;
- }
-
- /**
- * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
- * address.
- * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
- * expects the address in network byte order (MSB first).
- * <p>A {@link BluetoothDevice} will always be returned for a valid
- * hardware address, even if this adapter has never seen that device.
- *
- * @param address Bluetooth MAC address (6 bytes)
- * @throws IllegalArgumentException if address is invalid
- */
- @RequiresNoPermission
- public BluetoothDevice getRemoteDevice(byte[] address) {
- if (address == null || address.length != 6) {
- throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
- }
- final BluetoothDevice res = new BluetoothDevice(
- String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1],
- address[2], address[3], address[4], address[5]));
- res.setAttributionSource(mAttributionSource);
- return res;
- }
-
- /**
- * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
- * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
- * supported on this device.
- * <p>
- * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
- * on this device before calling this method.
- */
- @RequiresNoPermission
- public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
- if (!getLeAccess()) {
- return null;
- }
- synchronized (mLock) {
- if (mBluetoothLeAdvertiser == null) {
- mBluetoothLeAdvertiser = new BluetoothLeAdvertiser(this);
- }
- return mBluetoothLeAdvertiser;
- }
- }
-
- /**
- * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
- * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
- * Advertising is not supported on this device.
- * <p>
- * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
- * supported on this device before calling this method.
- *
- * @hide
- */
- @RequiresNoPermission
- public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
- if (!getLeAccess()) {
- return null;
- }
-
- if (!isLePeriodicAdvertisingSupported()) {
- return null;
- }
-
- synchronized (mLock) {
- if (mPeriodicAdvertisingManager == null) {
- mPeriodicAdvertisingManager = new PeriodicAdvertisingManager(this);
- }
- return mPeriodicAdvertisingManager;
- }
- }
-
- /**
- * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
- */
- @RequiresNoPermission
- public BluetoothLeScanner getBluetoothLeScanner() {
- if (!getLeAccess()) {
- return null;
- }
- synchronized (mLock) {
- if (mBluetoothLeScanner == null) {
- mBluetoothLeScanner = new BluetoothLeScanner(this);
- }
- return mBluetoothLeScanner;
- }
- }
-
- /**
- * Return true if Bluetooth is currently enabled and ready for use.
- * <p>Equivalent to:
- * <code>getBluetoothState() == STATE_ON</code>
- *
- * @return true if the local adapter is turned on
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public boolean isEnabled() {
- return getState() == BluetoothAdapter.STATE_ON;
- }
-
- /**
- * Return true if Bluetooth LE(Always BLE On feature) is currently
- * enabled and ready for use
- * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
- *
- * @return true if the local Bluetooth LE adapter is turned on
- * @hide
- */
- @SystemApi
- @RequiresNoPermission
- public boolean isLeEnabled() {
- final int state = getLeState();
- if (DBG) {
- Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
- }
- return (state == BluetoothAdapter.STATE_ON
- || state == BluetoothAdapter.STATE_BLE_ON
- || state == BluetoothAdapter.STATE_TURNING_ON
- || state == BluetoothAdapter.STATE_TURNING_OFF);
- }
-
- /**
- * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
- *
- * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
- * to STATE_OFF and completely shut-down Bluetooth
- *
- * <p> If the Adapter state is STATE_ON, This would unregister the existance of
- * special Bluetooth LE application and hence the further turning off of Bluetooth
- * from UI would ensure the complete turn-off of Bluetooth rather than staying back
- * BLE only state
- *
- * <p>This is an asynchronous call: it will return immediately, and
- * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
- * to be notified of subsequent adapter state changes If this call returns
- * true, then the adapter state will immediately transition from {@link
- * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
- * later transition to either {@link #STATE_BLE_ON} or {@link
- * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
- * If this call returns false then there was an
- * immediate problem that will prevent the QAdapter from being turned off -
- * such as the QAadapter already being turned off.
- *
- * @return true to indicate success, or false on immediate error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disableBLE() {
- if (!isBleScanAlwaysAvailable()) {
- return false;
- }
- try {
- return mManagerService.disableBle(mAttributionSource, mToken);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
- *
- * enableBLE registers the existence of an app using only LE functions.
- *
- * enableBLE may enable Bluetooth to an LE only mode so that an app can use
- * LE related features (BluetoothGatt or BluetoothGattServer classes)
- *
- * If the user disables Bluetooth while an app is registered to use LE only features,
- * Bluetooth will remain on in LE only mode for the app.
- *
- * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
- *
- * <p>This is an asynchronous call: it returns immediately, and
- * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
- * to be notified of adapter state changes.
- *
- * If this call returns * true, then the adapter state is either in a mode where
- * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
- * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
- *
- * If this call returns false then there was an immediate problem that prevents the
- * adapter from being turned on - such as Airplane mode.
- *
- * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
- * states, It includes all the classic Bluetooth Adapter states along with
- * internal BLE only states
- *
- * @return true to indicate Bluetooth LE will be available, or false on immediate error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean enableBLE() {
- if (!isBleScanAlwaysAvailable()) {
- return false;
- }
- try {
- return mManagerService.enableBle(mAttributionSource, mToken);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
-
- return false;
- }
-
- /*
- private static final String BLUETOOTH_GET_STATE_CACHE_PROPERTY = "cache_key.bluetooth.get_state";
-
- private final PropertyInvalidatedCache<Void, Integer> mBluetoothGetStateCache =
- new PropertyInvalidatedCache<Void, Integer>(
- 8, BLUETOOTH_GET_STATE_CACHE_PROPERTY) {
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- protected Integer recompute(Void query) {
- try {
- return mService.getState();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- };
- */
-
- /** @hide */
- /*
- @RequiresNoPermission
- public void disableBluetoothGetStateCache() {
- mBluetoothGetStateCache.disableLocal();
- }
- */
-
- /** @hide */
- /*
- public static void invalidateBluetoothGetStateCache() {
- PropertyInvalidatedCache.invalidateCache(BLUETOOTH_GET_STATE_CACHE_PROPERTY);
- }
- */
-
- /**
- * Fetch the current bluetooth state. If the service is down, return
- * OFF.
- */
- @AdapterState
- private int getStateInternal() {
- int state = BluetoothAdapter.STATE_OFF;
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- //state = mBluetoothGetStateCache.query(null);
- state = mService.getState();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- e.rethrowFromSystemServer();
- } finally {
- mServiceLock.readLock().unlock();
- }
- return state;
- }
-
- /**
- * Get the current state of the local Bluetooth adapter.
- * <p>Possible return values are
- * {@link #STATE_OFF},
- * {@link #STATE_TURNING_ON},
- * {@link #STATE_ON},
- * {@link #STATE_TURNING_OFF}.
- *
- * @return current state of Bluetooth adapter
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- @AdapterState
- public int getState() {
- int state = getStateInternal();
-
- // Consider all internal states as OFF
- if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON
- || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
- if (VDBG) {
- Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
- }
- state = BluetoothAdapter.STATE_OFF;
- }
- if (VDBG) {
- Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(
- state));
- }
- return state;
- }
-
- /**
- * Get the current state of the local Bluetooth adapter
- * <p>This returns current internal state of Adapter including LE ON/OFF
- *
- * <p>Possible return values are
- * {@link #STATE_OFF},
- * {@link #STATE_BLE_TURNING_ON},
- * {@link #STATE_BLE_ON},
- * {@link #STATE_TURNING_ON},
- * {@link #STATE_ON},
- * {@link #STATE_TURNING_OFF},
- * {@link #STATE_BLE_TURNING_OFF}.
- *
- * @return current state of Bluetooth adapter
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- @AdapterState
- @UnsupportedAppUsage(publicAlternatives = "Use {@link #getState()} instead to determine "
- + "whether you can use BLE & BT classic.")
- public int getLeState() {
- int state = getStateInternal();
-
- if (VDBG) {
- Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state));
- }
- return state;
- }
-
- boolean getLeAccess() {
- if (getLeState() == STATE_ON) {
- return true;
- } else if (getLeState() == STATE_BLE_ON) {
- return true; // TODO: FILTER SYSTEM APPS HERE <--
- }
-
- return false;
- }
-
- /**
- * Turn on the local Bluetooth adapter—do not use without explicit
- * user action to turn on Bluetooth.
- * <p>This powers on the underlying Bluetooth hardware, and starts all
- * Bluetooth system services.
- * <p class="caution"><strong>Bluetooth should never be enabled without
- * direct user consent</strong>. If you want to turn on Bluetooth in order
- * to create a wireless connection, you should use the {@link
- * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
- * user permission to turn on Bluetooth. The {@link #enable()} method is
- * provided only for applications that include a user interface for changing
- * system settings, such as a "power manager" app.</p>
- * <p>This is an asynchronous call: it will return immediately, and
- * clients should listen for {@link #ACTION_STATE_CHANGED}
- * to be notified of subsequent adapter state changes. If this call returns
- * true, then the adapter state will immediately transition from {@link
- * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
- * later transition to either {@link #STATE_OFF} or {@link
- * #STATE_ON}. If this call returns false then there was an
- * immediate problem that will prevent the adapter from being turned on -
- * such as Airplane mode, or the adapter is already turned on.
- *
- * @return true to indicate adapter startup has begun, or false on immediate error
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean enable() {
- if (isEnabled()) {
- if (DBG) {
- Log.d(TAG, "enable(): BT already enabled!");
- }
- return true;
- }
- try {
- return mManagerService.enable(mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Turn off the local Bluetooth adapter—do not use without explicit
- * user action to turn off Bluetooth.
- * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
- * system services, and powers down the underlying Bluetooth hardware.
- * <p class="caution"><strong>Bluetooth should never be disabled without
- * direct user consent</strong>. The {@link #disable()} method is
- * provided only for applications that include a user interface for changing
- * system settings, such as a "power manager" app.</p>
- * <p>This is an asynchronous call: it will return immediately, and
- * clients should listen for {@link #ACTION_STATE_CHANGED}
- * to be notified of subsequent adapter state changes. If this call returns
- * true, then the adapter state will immediately transition from {@link
- * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
- * later transition to either {@link #STATE_OFF} or {@link
- * #STATE_ON}. If this call returns false then there was an
- * immediate problem that will prevent the adapter from being turned off -
- * such as the adapter already being turned off.
- *
- * @return true to indicate adapter shutdown has begun, or false on immediate error
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disable() {
- try {
- return mManagerService.disable(mAttributionSource, true);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Turn off the local Bluetooth adapter and don't persist the setting.
- *
- * @param persist Indicate whether the off state should be persisted following the next reboot
- * @return true to indicate adapter shutdown has begun, or false on immediate error
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean disable(boolean persist) {
-
- try {
- return mManagerService.disable(mAttributionSource, persist);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Returns the hardware address of the local Bluetooth adapter.
- * <p>For example, "00:11:22:AA:BB:CC".
- *
- * @return Bluetooth hardware address as string
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.LOCAL_MAC_ADDRESS,
- })
- public String getAddress() {
- try {
- return mManagerService.getAddress(mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return null;
- }
-
- /**
- * Get the friendly Bluetooth name of the local Bluetooth adapter.
- * <p>This name is visible to remote Bluetooth devices.
- *
- * @return the Bluetooth name, or null on error
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public String getName() {
- try {
- return mManagerService.getName(mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return null;
- }
-
- /** {@hide} */
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public int getNameLengthForAdvertise() {
- try {
- return mService.getNameLengthForAdvertise(mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return -1;
- }
-
- /**
- * Factory reset bluetooth settings.
- *
- * @return true to indicate that the config file was successfully cleared
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean factoryReset() {
- try {
- mServiceLock.readLock().lock();
- if (mService != null && mService.factoryReset(mAttributionSource)
- && mManagerService != null
- && mManagerService.onFactoryReset(mAttributionSource)) {
- return true;
- }
- Log.e(TAG, "factoryReset(): Setting persist.bluetooth.factoryreset to retry later");
- BluetoothProperties.factory_reset(true);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Get the UUIDs supported by the local Bluetooth adapter.
- *
- * @return the UUIDs supported by the local Bluetooth Adapter.
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @Nullable ParcelUuid[] getUuids() {
- if (getState() != STATE_ON) {
- return null;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.getUuids(mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return null;
- }
-
- /**
- * Set the friendly Bluetooth name of the local Bluetooth adapter.
- * <p>This name is visible to remote Bluetooth devices.
- * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
- * encoding, although many remote devices can only display the first
- * 40 characters, and some may be limited to just 20.
- * <p>If Bluetooth state is not {@link #STATE_ON}, this API
- * will return false. After turning on Bluetooth,
- * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
- * to get the updated value.
- *
- * @param name a valid Bluetooth name
- * @return true if the name was set, false otherwise
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setName(String name) {
- if (getState() != STATE_ON) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.setName(name, mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Returns the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
- * adapter.
- *
- * @return {@link BluetoothClass} Bluetooth CoD of local Bluetooth device.
- *
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothClass getBluetoothClass() {
- if (getState() != STATE_ON) {
- return null;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.getBluetoothClass(mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return null;
- }
-
- /**
- * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
- * adapter.
- *
- * <p>Note: This value persists across system reboot.
- *
- * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to.
- * @return true if successful, false if unsuccessful.
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
- if (getState() != STATE_ON) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.setBluetoothClass(bluetoothClass, mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Returns the Input/Output capability of the device for classic Bluetooth.
- *
- * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
- * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
- * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
- *
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @IoCapability
- public int getIoCapability() {
- if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
- try {
- mServiceLock.readLock().lock();
- if (mService != null) return mService.getIoCapability(mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, e.getMessage(), e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
- }
-
- /**
- * Sets the Input/Output capability of the device for classic Bluetooth.
- *
- * <p>Changing the Input/Output capability of a device only takes effect on restarting the
- * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
- * and {@link BluetoothAdapter#enable()} to see the changes.
- *
- * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
- * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
- * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setIoCapability(@IoCapability int capability) {
- if (getState() != STATE_ON) return false;
- try {
- mServiceLock.readLock().lock();
- if (mService != null) return mService.setIoCapability(capability, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, e.getMessage(), e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Returns the Input/Output capability of the device for BLE operations.
- *
- * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
- * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
- * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
- *
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @IoCapability
- public int getLeIoCapability() {
- if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
- try {
- mServiceLock.readLock().lock();
- if (mService != null) return mService.getLeIoCapability(mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, e.getMessage(), e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
- }
-
- /**
- * Sets the Input/Output capability of the device for BLE operations.
- *
- * <p>Changing the Input/Output capability of a device only takes effect on restarting the
- * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
- * and {@link BluetoothAdapter#enable()} to see the changes.
- *
- * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
- * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
- * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setLeIoCapability(@IoCapability int capability) {
- if (getState() != STATE_ON) return false;
- try {
- mServiceLock.readLock().lock();
- if (mService != null) return mService.setLeIoCapability(capability, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, e.getMessage(), e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Get the current Bluetooth scan mode of the local Bluetooth adapter.
- * <p>The Bluetooth scan mode determines if the local adapter is
- * connectable and/or discoverable from remote Bluetooth devices.
- * <p>Possible values are:
- * {@link #SCAN_MODE_NONE},
- * {@link #SCAN_MODE_CONNECTABLE},
- * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
- * <p>If Bluetooth state is not {@link #STATE_ON}, this API
- * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
- * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
- * to get the updated value.
- *
- * @return scan mode
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- @ScanMode
- public int getScanMode() {
- if (getState() != STATE_ON) {
- return SCAN_MODE_NONE;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.getScanMode(mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return SCAN_MODE_NONE;
- }
-
- /**
- * Set the Bluetooth scan mode of the local Bluetooth adapter.
- * <p>The Bluetooth scan mode determines if the local adapter is
- * connectable and/or discoverable from remote Bluetooth devices.
- * <p>For privacy reasons, discoverable mode is automatically turned off
- * after <code>durationMillis</code> milliseconds. For example, 120000 milliseconds should be
- * enough for a remote device to initiate and complete its discovery process.
- * <p>Valid scan mode values are:
- * {@link #SCAN_MODE_NONE},
- * {@link #SCAN_MODE_CONNECTABLE},
- * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
- * <p>If Bluetooth state is not {@link #STATE_ON}, this API
- * will return false. After turning on Bluetooth,
- * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
- * to get the updated value.
- * <p>Applications cannot set the scan mode. They should use
- * <code>startActivityForResult(
- * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
- * </code>instead.
- *
- * @param mode valid scan mode
- * @param durationMillis time in milliseconds to apply scan mode, only used for {@link
- * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
- * @return true if the scan mode was set, false otherwise
- * @hide
- */
- @UnsupportedAppUsage(publicAlternatives = "Use {@link #ACTION_REQUEST_DISCOVERABLE}, which "
- + "shows UI that confirms the user wants to go into discoverable mode.")
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public boolean setScanMode(@ScanMode int mode, long durationMillis) {
- if (getState() != STATE_ON) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- int durationSeconds = Math.toIntExact(durationMillis / 1000);
- return mService.setScanMode(mode, durationSeconds, mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } catch (ArithmeticException ex) {
- Log.e(TAG, "setScanMode: Duration in seconds outside of the bounds of an int");
- throw new IllegalArgumentException("Duration not in bounds. In seconds, the "
- + "durationMillis must be in the range of an int");
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Set the Bluetooth scan mode of the local Bluetooth adapter.
- * <p>The Bluetooth scan mode determines if the local adapter is
- * connectable and/or discoverable from remote Bluetooth devices.
- * <p>For privacy reasons, discoverable mode is automatically turned off
- * after <code>duration</code> seconds. For example, 120 seconds should be
- * enough for a remote device to initiate and complete its discovery
- * process.
- * <p>Valid scan mode values are:
- * {@link #SCAN_MODE_NONE},
- * {@link #SCAN_MODE_CONNECTABLE},
- * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
- * <p>If Bluetooth state is not {@link #STATE_ON}, this API
- * will return false. After turning on Bluetooth,
- * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
- * to get the updated value.
- * <p>Applications cannot set the scan mode. They should use
- * <code>startActivityForResult(
- * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
- * </code>instead.
- *
- * @param mode valid scan mode
- * @return true if the scan mode was set, false otherwise
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public boolean setScanMode(@ScanMode int mode) {
- if (getState() != STATE_ON) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.setScanMode(mode, getDiscoverableTimeout(), mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /** @hide */
- @UnsupportedAppUsage
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public int getDiscoverableTimeout() {
- if (getState() != STATE_ON) {
- return -1;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.getDiscoverableTimeout(mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return -1;
- }
-
- /** @hide */
- @UnsupportedAppUsage
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void setDiscoverableTimeout(int timeout) {
- if (getState() != STATE_ON) {
- return;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- mService.setDiscoverableTimeout(timeout, mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- }
-
- /**
- * Get the end time of the latest remote device discovery process.
- *
- * @return the latest time that the bluetooth adapter was/will be in discovery mode, in
- * milliseconds since the epoch. This time can be in the future if {@link #startDiscovery()} has
- * been called recently.
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public long getDiscoveryEndMillis() {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.getDiscoveryEndMillis(mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return -1;
- }
-
- /**
- * Start the remote device discovery process.
- * <p>The discovery process usually involves an inquiry scan of about 12
- * seconds, followed by a page scan of each new device to retrieve its
- * Bluetooth name.
- * <p>This is an asynchronous call, it will return immediately. Register
- * for {@link #ACTION_DISCOVERY_STARTED} and {@link
- * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
- * discovery starts and completes. Register for {@link
- * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
- * are found.
- * <p>Device discovery is a heavyweight procedure. New connections to
- * remote Bluetooth devices should not be attempted while discovery is in
- * progress, and existing connections will experience limited bandwidth
- * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
- * discovery. Discovery is not managed by the Activity,
- * but is run as a system service, so an application should always call
- * {@link BluetoothAdapter#cancelDiscovery()} even if it
- * did not directly request a discovery, just to be sure.
- * <p>Device discovery will only find remote devices that are currently
- * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
- * not discoverable by default, and need to be entered into a special mode.
- * <p>If Bluetooth state is not {@link #STATE_ON}, this API
- * will return false. After turning on Bluetooth, wait for {@link #ACTION_STATE_CHANGED}
- * with {@link #STATE_ON} to get the updated value.
- * <p>If a device is currently bonding, this request will be queued and executed once that
- * device has finished bonding. If a request is already queued, this request will be ignored.
- *
- * @return true on success, false on error
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public boolean startDiscovery() {
- if (getState() != STATE_ON) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.startDiscovery(mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Cancel the current device discovery process.
- * <p>Because discovery is a heavyweight procedure for the Bluetooth
- * adapter, this method should always be called before attempting to connect
- * to a remote device with {@link
- * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
- * the Activity, but is run as a system service, so an application should
- * always call cancel discovery even if it did not directly request a
- * discovery, just to be sure.
- * <p>If Bluetooth state is not {@link #STATE_ON}, this API
- * will return false. After turning on Bluetooth,
- * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
- * to get the updated value.
- *
- * @return true on success, false on error
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public boolean cancelDiscovery() {
- if (getState() != STATE_ON) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.cancelDiscovery(mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Return true if the local Bluetooth adapter is currently in the device
- * discovery process.
- * <p>Device discovery is a heavyweight procedure. New connections to
- * remote Bluetooth devices should not be attempted while discovery is in
- * progress, and existing connections will experience limited bandwidth
- * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
- * discovery.
- * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
- * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
- * starts or completes.
- * <p>If Bluetooth state is not {@link #STATE_ON}, this API
- * will return false. After turning on Bluetooth,
- * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
- * to get the updated value.
- *
- * @return true if discovering
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public boolean isDiscovering() {
- if (getState() != STATE_ON) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isDiscovering(mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Removes the active device for the grouping of @ActiveDeviceUse specified
- *
- * @param profiles represents the purpose for which we are setting this as the active device.
- * Possible values are:
- * {@link BluetoothAdapter#ACTIVE_DEVICE_AUDIO},
- * {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL},
- * {@link BluetoothAdapter#ACTIVE_DEVICE_ALL}
- * @return false on immediate error, true otherwise
- * @throws IllegalArgumentException if device is null or profiles is not one of
- * {@link ActiveDeviceUse}
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public boolean removeActiveDevice(@ActiveDeviceUse int profiles) {
- if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
- && profiles != ACTIVE_DEVICE_ALL) {
- Log.e(TAG, "Invalid profiles param value in removeActiveDevice");
- throw new IllegalArgumentException("Profiles must be one of "
- + "BluetoothAdapter.ACTIVE_DEVICE_AUDIO, "
- + "BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL, or "
- + "BluetoothAdapter.ACTIVE_DEVICE_ALL");
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- if (DBG) Log.d(TAG, "removeActiveDevice, profiles: " + profiles);
- return mService.removeActiveDevice(profiles, mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
-
- return false;
- }
-
- /**
- * Sets device as the active devices for the profiles passed into the function
- *
- * @param device is the remote bluetooth device
- * @param profiles represents the purpose for which we are setting this as the active device.
- * Possible values are:
- * {@link BluetoothAdapter#ACTIVE_DEVICE_AUDIO},
- * {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL},
- * {@link BluetoothAdapter#ACTIVE_DEVICE_ALL}
- * @return false on immediate error, true otherwise
- * @throws IllegalArgumentException if device is null or profiles is not one of
- * {@link ActiveDeviceUse}
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public boolean setActiveDevice(@NonNull BluetoothDevice device,
- @ActiveDeviceUse int profiles) {
- if (device == null) {
- Log.e(TAG, "setActiveDevice: Null device passed as parameter");
- throw new IllegalArgumentException("device cannot be null");
- }
- if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
- && profiles != ACTIVE_DEVICE_ALL) {
- Log.e(TAG, "Invalid profiles param value in setActiveDevice");
- throw new IllegalArgumentException("Profiles must be one of "
- + "BluetoothAdapter.ACTIVE_DEVICE_AUDIO, "
- + "BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL, or "
- + "BluetoothAdapter.ACTIVE_DEVICE_ALL");
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- if (DBG) {
- Log.d(TAG, "setActiveDevice, device: " + device + ", profiles: " + profiles);
- }
- return mService.setActiveDevice(device, profiles, mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
-
- return false;
- }
-
- /**
- * Get the active devices for the BluetoothProfile specified
- *
- * @param profile is the profile from which we want the active devices.
- * Possible values are:
- * {@link BluetoothProfile#HEADSET},
- * {@link BluetoothProfile#A2DP},
- * {@link BluetoothProfile#HEARING_AID}
- * {@link BluetoothProfile#LE_AUDIO}
- * @return A list of active bluetooth devices
- * @throws IllegalArgumentException If profile is not one of {@link ActiveDeviceProfile}
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @NonNull List<BluetoothDevice> getActiveDevices(@ActiveDeviceProfile int profile) {
- if (profile != BluetoothProfile.HEADSET
- && profile != BluetoothProfile.A2DP
- && profile != BluetoothProfile.HEARING_AID
- && profile != BluetoothProfile.LE_AUDIO) {
- Log.e(TAG, "Invalid profile param value in getActiveDevices");
- throw new IllegalArgumentException("Profiles must be one of "
- + "BluetoothProfile.A2DP, "
- + "BluetoothProfile.HEARING_AID, or"
- + "BluetoothProfile.HEARING_AID"
- + "BluetoothProfile.LE_AUDIO");
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- if (DBG) {
- Log.d(TAG, "getActiveDevices(profile= "
- + BluetoothProfile.getProfileName(profile) + ")");
- }
- return mService.getActiveDevices(profile, mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
-
- return new ArrayList<>();
- }
-
- /**
- * Return true if the multi advertisement is supported by the chipset
- *
- * @return true if Multiple Advertisement feature is supported
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public boolean isMultipleAdvertisementSupported() {
- if (getState() != STATE_ON) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isMultiAdvertisementSupported();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
- *
- * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
- * fetch scan results even when Bluetooth is turned off.<p>
- *
- * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
- *
- * @hide
- */
- @SystemApi
- @RequiresNoPermission
- public boolean isBleScanAlwaysAvailable() {
- try {
- return mManagerService.isBleScanAlwaysAvailable();
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception when calling isBleScanAlwaysAvailable", e);
- return false;
- }
- }
-
- /*
- private static final String BLUETOOTH_FILTERING_CACHE_PROPERTY =
- "cache_key.bluetooth.is_offloaded_filtering_supported";
- private final PropertyInvalidatedCache<Void, Boolean> mBluetoothFilteringCache =
- new PropertyInvalidatedCache<Void, Boolean>(
- 8, BLUETOOTH_FILTERING_CACHE_PROPERTY) {
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- protected Boolean recompute(Void query) {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isOffloadedFilteringSupported();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
-
- }
- };
- */
-
- /** @hide */
- /*
- @RequiresNoPermission
- public void disableIsOffloadedFilteringSupportedCache() {
- mBluetoothFilteringCache.disableLocal();
- }
- */
-
- /** @hide */
- /*
- public static void invalidateIsOffloadedFilteringSupportedCache() {
- PropertyInvalidatedCache.invalidateCache(BLUETOOTH_FILTERING_CACHE_PROPERTY);
- }
- */
-
- /**
- * Return true if offloaded filters are supported
- *
- * @return true if chipset supports on-chip filtering
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public boolean isOffloadedFilteringSupported() {
- if (!getLeAccess()) {
- return false;
- }
- //return mBluetoothFilteringCache.query(null);
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isOffloadedFilteringSupported();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Return true if offloaded scan batching is supported
- *
- * @return true if chipset supports on-chip scan batching
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public boolean isOffloadedScanBatchingSupported() {
- if (!getLeAccess()) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isOffloadedScanBatchingSupported();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Return true if LE 2M PHY feature is supported.
- *
- * @return true if chipset supports LE 2M PHY feature
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public boolean isLe2MPhySupported() {
- if (!getLeAccess()) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isLe2MPhySupported();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Return true if LE Coded PHY feature is supported.
- *
- * @return true if chipset supports LE Coded PHY feature
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public boolean isLeCodedPhySupported() {
- if (!getLeAccess()) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isLeCodedPhySupported();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Return true if LE Extended Advertising feature is supported.
- *
- * @return true if chipset supports LE Extended Advertising feature
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public boolean isLeExtendedAdvertisingSupported() {
- if (!getLeAccess()) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isLeExtendedAdvertisingSupported();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /**
- * Return true if LE Periodic Advertising feature is supported.
- *
- * @return true if chipset supports LE Periodic Advertising feature
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public boolean isLePeriodicAdvertisingSupported() {
- if (!getLeAccess()) {
- return false;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isLePeriodicAdvertisingSupported();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
- }
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- BluetoothStatusCodes.SUCCESS,
- BluetoothStatusCodes.ERROR_UNKNOWN,
- BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
- BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED,
- })
- public @interface LeFeatureReturnValues {}
-
- /**
- * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio feature is
- * supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if
- * the feature is not supported or an error code.
- *
- * @return whether the LE audio is supported
- */
- @RequiresNoPermission
- public @LeFeatureReturnValues int isLeAudioSupported() {
- if (!getLeAccess()) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isLeAudioSupported();
- }
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- } finally {
- mServiceLock.readLock().unlock();
- }
- return BluetoothStatusCodes.ERROR_UNKNOWN;
- }
-
- /**
- * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Periodic Advertising Sync Transfer Sender
- * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the
- * feature is not supported or an error code
- *
- * @return whether the chipset supports the LE Periodic Advertising Sync Transfer Sender feature
- */
- @RequiresNoPermission
- public @LeFeatureReturnValues int isLePeriodicAdvertisingSyncTransferSenderSupported() {
- if (!getLeAccess()) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.isLePeriodicAdvertisingSyncTransferSenderSupported();
- }
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- } finally {
- mServiceLock.readLock().unlock();
- }
- return BluetoothStatusCodes.ERROR_UNKNOWN;
- }
-
- /**
- * Return the maximum LE advertising data length in bytes,
- * if LE Extended Advertising feature is supported, 0 otherwise.
- *
- * @return the maximum LE advertising data length.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public int getLeMaximumAdvertisingDataLength() {
- if (!getLeAccess()) {
- return 0;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.getLeMaximumAdvertisingDataLength();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return 0;
- }
-
- /**
- * Return true if Hearing Aid Profile is supported.
- *
- * @return true if phone supports Hearing Aid Profile
- */
- @RequiresNoPermission
- private boolean isHearingAidProfileSupported() {
- try {
- return mManagerService.isHearingAidProfileSupported();
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception when calling isHearingAidProfileSupported", e);
- return false;
- }
- }
-
- /**
- * Get the maximum number of connected audio devices.
- *
- * @return the maximum number of connected audio devices
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getMaxConnectedAudioDevices() {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.getMaxConnectedAudioDevices(mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return 1;
- }
-
- /**
- * Return true if hardware has entries available for matching beacons
- *
- * @return true if there are hw entries available for matching beacons
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isHardwareTrackingFiltersAvailable() {
- if (!getLeAccess()) {
- return false;
- }
- try {
- IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
- if (iGatt == null) {
- // BLE is not supported
- return false;
- }
- return (iGatt.numHwTrackFiltersAvailable(mAttributionSource) != 0);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Request the record of {@link BluetoothActivityEnergyInfo} object that
- * has the activity and energy info. This can be used to ascertain what
- * the controller has been up to, since the last sample.
- *
- * A null value for the activity info object may be sent if the bluetooth service is
- * unreachable or the device does not support reporting such information.
- *
- * @param result The callback to which to send the activity info.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public void requestControllerActivityEnergyInfo(ResultReceiver result) {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- mService.requestActivityInfo(result, mAttributionSource);
- result = null;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
- } finally {
- mServiceLock.readLock().unlock();
- if (result != null) {
- // Only send an immediate result if we failed.
- result.send(0, null);
- }
- }
- }
-
- /**
- * Fetches a list of the most recently connected bluetooth devices ordered by how recently they
- * were connected with most recently first and least recently last
- *
- * @return {@link List} of bonded {@link BluetoothDevice} ordered by how recently they were
- * connected
- *
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @NonNull List<BluetoothDevice> getMostRecentlyConnectedDevices() {
- if (getState() != STATE_ON) {
- return new ArrayList<>();
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return Attributable.setAttributionSource(
- mService.getMostRecentlyConnectedDevices(mAttributionSource),
- mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return new ArrayList<>();
- }
-
- /**
- * Return the set of {@link BluetoothDevice} objects that are bonded
- * (paired) to the local adapter.
- * <p>If Bluetooth state is not {@link #STATE_ON}, this API
- * will return an empty set. After turning on Bluetooth,
- * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
- * to get the updated value.
- *
- * @return unmodifiable set of {@link BluetoothDevice}, or null on error
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public Set<BluetoothDevice> getBondedDevices() {
- if (getState() != STATE_ON) {
- return toDeviceSet(Arrays.asList());
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return toDeviceSet(Attributable.setAttributionSource(
- Arrays.asList(mService.getBondedDevices(mAttributionSource)),
- mAttributionSource));
- }
- return toDeviceSet(Arrays.asList());
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return null;
- }
-
- /**
- * Gets the currently supported profiles by the adapter.
- *
- * <p> This can be used to check whether a profile is supported before attempting
- * to connect to its respective proxy.
- *
- * @return a list of integers indicating the ids of supported profiles as defined in {@link
- * BluetoothProfile}.
- * @hide
- */
- @RequiresNoPermission
- public @NonNull List<Integer> getSupportedProfiles() {
- final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
-
- try {
- synchronized (mManagerCallback) {
- if (mService != null) {
- final long supportedProfilesBitMask = mService.getSupportedProfiles();
-
- for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
- if ((supportedProfilesBitMask & (1 << i)) != 0) {
- supportedProfiles.add(i);
- }
- }
- } else {
- // Bluetooth is disabled. Just fill in known supported Profiles
- if (isHearingAidProfileSupported()) {
- supportedProfiles.add(BluetoothProfile.HEARING_AID);
- }
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "getSupportedProfiles:", e);
- }
- return supportedProfiles;
- }
-
- /*
- private static final String BLUETOOTH_GET_ADAPTER_CONNECTION_STATE_CACHE_PROPERTY =
- "cache_key.bluetooth.get_adapter_connection_state";
- private final PropertyInvalidatedCache<Void, Integer>
- mBluetoothGetAdapterConnectionStateCache =
- new PropertyInvalidatedCache<Void, Integer> (
- 8, BLUETOOTH_GET_ADAPTER_CONNECTION_STATE_CACHE_PROPERTY) {
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- protected Integer recompute(Void query) {
- try {
- return mService.getAdapterConnectionState();
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- }
- };
- */
-
- /** @hide */
- /*
- @RequiresNoPermission
- public void disableGetAdapterConnectionStateCache() {
- mBluetoothGetAdapterConnectionStateCache.disableLocal();
- }
- */
-
- /** @hide */
- /*
- public static void invalidateGetAdapterConnectionStateCache() {
- PropertyInvalidatedCache.invalidateCache(
- BLUETOOTH_GET_ADAPTER_CONNECTION_STATE_CACHE_PROPERTY);
- }
- */
-
- /**
- * Get the current connection state of the local Bluetooth adapter.
- * This can be used to check whether the local Bluetooth adapter is connected
- * to any profile of any other remote Bluetooth Device.
- *
- * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
- * intent to get the connection state of the adapter.
- *
- * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link
- * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public int getConnectionState() {
- if (getState() != STATE_ON) {
- return BluetoothAdapter.STATE_DISCONNECTED;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.getAdapterConnectionState();
- }
- //return mBluetoothGetAdapterConnectionStateCache.query(null);
- } catch (RemoteException e) {
- Log.e(TAG, "failed to getConnectionState, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return BluetoothAdapter.STATE_DISCONNECTED;
- }
-
- /*
- private static final String BLUETOOTH_PROFILE_CACHE_PROPERTY =
- "cache_key.bluetooth.get_profile_connection_state";
- private final PropertyInvalidatedCache<Integer, Integer>
- mGetProfileConnectionStateCache =
- new PropertyInvalidatedCache<Integer, Integer>(
- 8, BLUETOOTH_PROFILE_CACHE_PROPERTY) {
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- protected Integer recompute(Integer query) {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.getProfileConnectionState(query);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "getProfileConnectionState:", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return BluetoothProfile.STATE_DISCONNECTED;
- }
- @Override
- public String queryToString(Integer query) {
- return String.format("getProfileConnectionState(profile=\"%d\")",
- query);
- }
- };
- */
-
- /** @hide */
- /*
- @RequiresNoPermission
- public void disableGetProfileConnectionStateCache() {
- mGetProfileConnectionStateCache.disableLocal();
- }
- */
-
- /** @hide */
- /*
- public static void invalidateGetProfileConnectionStateCache() {
- PropertyInvalidatedCache.invalidateCache(BLUETOOTH_PROFILE_CACHE_PROPERTY);
- }
- */
-
- /**
- * Get the current connection state of a profile.
- * This function can be used to check whether the local Bluetooth adapter
- * is connected to any remote device for a specific profile.
- * Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
- *
- * <p> Return value can be one of
- * {@link BluetoothProfile#STATE_DISCONNECTED},
- * {@link BluetoothProfile#STATE_CONNECTING},
- * {@link BluetoothProfile#STATE_CONNECTED},
- * {@link BluetoothProfile#STATE_DISCONNECTING}
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public int getProfileConnectionState(int profile) {
- if (getState() != STATE_ON) {
- return BluetoothProfile.STATE_DISCONNECTED;
- }
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- mService.getProfileConnectionState(profile);
- }
- //return mGetProfileConnectionStateCache.query(new Integer(profile));
- } catch (RemoteException e) {
- Log.e(TAG, "failed to getProfileConnectionState, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return BluetoothProfile.STATE_DISCONNECTED;
- }
-
- /**
- * Create a listening, secure RFCOMM Bluetooth socket.
- * <p>A remote device connecting to this socket will be authenticated and
- * communication on this socket will be encrypted.
- * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
- * connections from a listening {@link BluetoothServerSocket}.
- * <p>Valid RFCOMM channels are in range 1 to 30.
- *
- * @param channel RFCOMM channel to listen on
- * @return a listening RFCOMM BluetoothServerSocket
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions, or channel in use.
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
- return listenUsingRfcommOn(channel, false, false);
- }
-
- /**
- * Create a listening, secure RFCOMM Bluetooth socket.
- * <p>A remote device connecting to this socket will be authenticated and
- * communication on this socket will be encrypted.
- * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
- * connections from a listening {@link BluetoothServerSocket}.
- * <p>Valid RFCOMM channels are in range 1 to 30.
- * <p>To auto assign a channel without creating a SDP record use
- * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
- *
- * @param channel RFCOMM channel to listen on
- * @param mitm enforce person-in-the-middle protection for authentication.
- * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
- * connections.
- * @return a listening RFCOMM BluetoothServerSocket
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions, or channel in use.
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
- boolean min16DigitPin) throws IOException {
- BluetoothServerSocket socket =
- new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm,
- min16DigitPin);
- int errno = socket.mSocket.bindListen();
- if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
- socket.setChannel(socket.mSocket.getPort());
- }
- if (errno != 0) {
- //TODO(BT): Throw the same exception error code
- // that the previous code was using.
- //socket.mSocket.throwErrnoNative(errno);
- throw new IOException("Error: " + errno);
- }
- return socket;
- }
-
- /**
- * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
- * <p>A remote device connecting to this socket will be authenticated and
- * communication on this socket will be encrypted.
- * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
- * connections from a listening {@link BluetoothServerSocket}.
- * <p>The system will assign an unused RFCOMM channel to listen on.
- * <p>The system will also register a Service Discovery
- * Protocol (SDP) record with the local SDP server containing the specified
- * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
- * can use the same UUID to query our SDP server and discover which channel
- * to connect to. This SDP record will be removed when this socket is
- * closed, or if this application closes unexpectedly.
- * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
- * connect to this socket from another device using the same {@link UUID}.
- *
- * @param name service name for SDP record
- * @param uuid uuid for SDP record
- * @return a listening RFCOMM BluetoothServerSocket
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions, or channel in use.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
- throws IOException {
- return createNewRfcommSocketAndRecord(name, uuid, true, true);
- }
-
- /**
- * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
- * <p>The link key is not required to be authenticated, i.e the communication may be
- * vulnerable to Person In the Middle attacks. For Bluetooth 2.1 devices,
- * the link will be encrypted, as encryption is mandatory.
- * For legacy devices (pre Bluetooth 2.1 devices) the link will not
- * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
- * encrypted and authenticated communication channel is desired.
- * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
- * connections from a listening {@link BluetoothServerSocket}.
- * <p>The system will assign an unused RFCOMM channel to listen on.
- * <p>The system will also register a Service Discovery
- * Protocol (SDP) record with the local SDP server containing the specified
- * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
- * can use the same UUID to query our SDP server and discover which channel
- * to connect to. This SDP record will be removed when this socket is
- * closed, or if this application closes unexpectedly.
- * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
- * connect to this socket from another device using the same {@link UUID}.
- *
- * @param name service name for SDP record
- * @param uuid uuid for SDP record
- * @return a listening RFCOMM BluetoothServerSocket
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions, or channel in use.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
- throws IOException {
- return createNewRfcommSocketAndRecord(name, uuid, false, false);
- }
-
- /**
- * Create a listening, encrypted,
- * RFCOMM Bluetooth socket with Service Record.
- * <p>The link will be encrypted, but the link key is not required to be authenticated
- * i.e the communication is vulnerable to Person In the Middle attacks. Use
- * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
- * <p> Use this socket if authentication of link key is not possible.
- * For example, for Bluetooth 2.1 devices, if any of the devices does not have
- * an input and output capability or just has the ability to display a numeric key,
- * a secure socket connection is not possible and this socket can be used.
- * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
- * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandatory.
- * For more details, refer to the Security Model section 5.2 (vol 3) of
- * Bluetooth Core Specification version 2.1 + EDR.
- * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
- * connections from a listening {@link BluetoothServerSocket}.
- * <p>The system will assign an unused RFCOMM channel to listen on.
- * <p>The system will also register a Service Discovery
- * Protocol (SDP) record with the local SDP server containing the specified
- * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
- * can use the same UUID to query our SDP server and discover which channel
- * to connect to. This SDP record will be removed when this socket is
- * closed, or if this application closes unexpectedly.
- * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
- * connect to this socket from another device using the same {@link UUID}.
- *
- * @param name service name for SDP record
- * @param uuid uuid for SDP record
- * @return a listening RFCOMM BluetoothServerSocket
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions, or channel in use.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid)
- throws IOException {
- return createNewRfcommSocketAndRecord(name, uuid, false, true);
- }
-
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
- boolean auth, boolean encrypt) throws IOException {
- BluetoothServerSocket socket;
- socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth, encrypt,
- new ParcelUuid(uuid));
- socket.setServiceName(name);
- int errno = socket.mSocket.bindListen();
- if (errno != 0) {
- //TODO(BT): Throw the same exception error code
- // that the previous code was using.
- //socket.mSocket.throwErrnoNative(errno);
- throw new IOException("Error: " + errno);
- }
- return socket;
- }
-
- /**
- * Construct an unencrypted, unauthenticated, RFCOMM server socket.
- * Call #accept to retrieve connections to this socket.
- *
- * @return An RFCOMM BluetoothServerSocket
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * permissions.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
- BluetoothServerSocket socket =
- new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, false, port);
- int errno = socket.mSocket.bindListen();
- if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
- socket.setChannel(socket.mSocket.getPort());
- }
- if (errno != 0) {
- //TODO(BT): Throw the same exception error code
- // that the previous code was using.
- //socket.mSocket.throwErrnoNative(errno);
- throw new IOException("Error: " + errno);
- }
- return socket;
- }
-
- /**
- * Construct an encrypted, authenticated, L2CAP server socket.
- * Call #accept to retrieve connections to this socket.
- * <p>To auto assign a port without creating a SDP record use
- * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
- *
- * @param port the PSM to listen on
- * @param mitm enforce person-in-the-middle protection for authentication.
- * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
- * connections.
- * @return An L2CAP BluetoothServerSocket
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * permissions.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
- throws IOException {
- BluetoothServerSocket socket =
- new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, true, true, port, mitm,
- min16DigitPin);
- int errno = socket.mSocket.bindListen();
- if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
- int assignedChannel = socket.mSocket.getPort();
- if (DBG) Log.d(TAG, "listenUsingL2capOn: set assigned channel to " + assignedChannel);
- socket.setChannel(assignedChannel);
- }
- if (errno != 0) {
- //TODO(BT): Throw the same exception error code
- // that the previous code was using.
- //socket.mSocket.throwErrnoNative(errno);
- throw new IOException("Error: " + errno);
- }
- return socket;
- }
-
- /**
- * Construct an encrypted, authenticated, L2CAP server socket.
- * Call #accept to retrieve connections to this socket.
- * <p>To auto assign a port without creating a SDP record use
- * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
- *
- * @param port the PSM to listen on
- * @return An L2CAP BluetoothServerSocket
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * permissions.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
- return listenUsingL2capOn(port, false, false);
- }
-
- /**
- * Construct an insecure L2CAP server socket.
- * Call #accept to retrieve connections to this socket.
- * <p>To auto assign a port without creating a SDP record use
- * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
- *
- * @param port the PSM to listen on
- * @return An L2CAP BluetoothServerSocket
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * permissions.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
- Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port);
- BluetoothServerSocket socket =
- new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, false, false, port, false,
- false);
- int errno = socket.mSocket.bindListen();
- if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
- int assignedChannel = socket.mSocket.getPort();
- if (DBG) {
- Log.d(TAG, "listenUsingInsecureL2capOn: set assigned channel to "
- + assignedChannel);
- }
- socket.setChannel(assignedChannel);
- }
- if (errno != 0) {
- //TODO(BT): Throw the same exception error code
- // that the previous code was using.
- //socket.mSocket.throwErrnoNative(errno);
- throw new IOException("Error: " + errno);
- }
- return socket;
-
- }
-
- /**
- * Read the local Out of Band Pairing Data
- *
- * @return Pair<byte[], byte[]> of Hash and Randomizer
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public Pair<byte[], byte[]> readOutOfBandData() {
- return null;
- }
-
- /**
- * Get the profile proxy object associated with the profile.
- *
- * <p>Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP},
- * {@link BluetoothProfile#GATT}, {@link BluetoothProfile#HEARING_AID}, or {@link
- * BluetoothProfile#GATT_SERVER}. Clients must implement {@link
- * BluetoothProfile.ServiceListener} to get notified of the connection status and to get the
- * proxy object.
- *
- * @param context Context of the application
- * @param listener The service Listener for connection callbacks.
- * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEADSET},
- * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, {@link
- * BluetoothProfile#HEARING_AID} or {@link BluetoothProfile#GATT_SERVER}.
- * @return true on success, false on error
- */
- @SuppressLint({
- "AndroidFrameworkRequiresPermission",
- "AndroidFrameworkBluetoothPermission"
- })
- public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
- int profile) {
- if (context == null || listener == null) {
- return false;
- }
-
- if (profile == BluetoothProfile.HEADSET) {
- BluetoothHeadset headset = new BluetoothHeadset(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.A2DP) {
- BluetoothA2dp a2dp = new BluetoothA2dp(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.A2DP_SINK) {
- BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
- BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.HID_HOST) {
- BluetoothHidHost iDev = new BluetoothHidHost(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.PAN) {
- BluetoothPan pan = new BluetoothPan(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.PBAP) {
- BluetoothPbap pbap = new BluetoothPbap(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.HEALTH) {
- Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated");
- return false;
- } else if (profile == BluetoothProfile.MAP) {
- BluetoothMap map = new BluetoothMap(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
- BluetoothHeadsetClient headsetClient =
- new BluetoothHeadsetClient(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.SAP) {
- BluetoothSap sap = new BluetoothSap(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.PBAP_CLIENT) {
- BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.MAP_CLIENT) {
- BluetoothMapClient mapClient = new BluetoothMapClient(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.HID_DEVICE) {
- BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.HEARING_AID) {
- if (isHearingAidProfileSupported()) {
- BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener, this);
- return true;
- }
- return false;
- } else if (profile == BluetoothProfile.LE_AUDIO) {
- BluetoothLeAudio leAudio = new BluetoothLeAudio(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.VOLUME_CONTROL) {
- BluetoothVolumeControl vcs = new BluetoothVolumeControl(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.CSIP_SET_COORDINATOR) {
- BluetoothCsipSetCoordinator csipSetCoordinator =
- new BluetoothCsipSetCoordinator(context, listener, this);
- return true;
- } else if (profile == BluetoothProfile.LE_CALL_CONTROL) {
- BluetoothLeCallControl tbs = new BluetoothLeCallControl(context, listener);
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Close the connection of the profile proxy to the Service.
- *
- * <p> Clients should call this when they are no longer using
- * the proxy obtained from {@link #getProfileProxy}.
- * Profile can be one of {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}
- *
- * @param profile
- * @param proxy Profile proxy object
- */
- @SuppressLint({
- "AndroidFrameworkRequiresPermission",
- "AndroidFrameworkBluetoothPermission"
- })
- public void closeProfileProxy(int profile, BluetoothProfile proxy) {
- if (proxy == null) {
- return;
- }
-
- switch (profile) {
- case BluetoothProfile.HEADSET:
- BluetoothHeadset headset = (BluetoothHeadset) proxy;
- headset.close();
- break;
- case BluetoothProfile.A2DP:
- BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
- a2dp.close();
- break;
- case BluetoothProfile.A2DP_SINK:
- BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink) proxy;
- a2dpSink.close();
- break;
- case BluetoothProfile.AVRCP_CONTROLLER:
- BluetoothAvrcpController avrcp = (BluetoothAvrcpController) proxy;
- avrcp.close();
- break;
- case BluetoothProfile.HID_HOST:
- BluetoothHidHost iDev = (BluetoothHidHost) proxy;
- iDev.close();
- break;
- case BluetoothProfile.PAN:
- BluetoothPan pan = (BluetoothPan) proxy;
- pan.close();
- break;
- case BluetoothProfile.PBAP:
- BluetoothPbap pbap = (BluetoothPbap) proxy;
- pbap.close();
- break;
- case BluetoothProfile.GATT:
- BluetoothGatt gatt = (BluetoothGatt) proxy;
- gatt.close();
- break;
- case BluetoothProfile.GATT_SERVER:
- BluetoothGattServer gattServer = (BluetoothGattServer) proxy;
- gattServer.close();
- break;
- case BluetoothProfile.MAP:
- BluetoothMap map = (BluetoothMap) proxy;
- map.close();
- break;
- case BluetoothProfile.HEADSET_CLIENT:
- BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient) proxy;
- headsetClient.close();
- break;
- case BluetoothProfile.SAP:
- BluetoothSap sap = (BluetoothSap) proxy;
- sap.close();
- break;
- case BluetoothProfile.PBAP_CLIENT:
- BluetoothPbapClient pbapClient = (BluetoothPbapClient) proxy;
- pbapClient.close();
- break;
- case BluetoothProfile.MAP_CLIENT:
- BluetoothMapClient mapClient = (BluetoothMapClient) proxy;
- mapClient.close();
- break;
- case BluetoothProfile.HID_DEVICE:
- BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
- hidDevice.close();
- break;
- case BluetoothProfile.HEARING_AID:
- BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy;
- hearingAid.close();
- break;
- case BluetoothProfile.LE_AUDIO:
- BluetoothLeAudio leAudio = (BluetoothLeAudio) proxy;
- leAudio.close();
- break;
- case BluetoothProfile.VOLUME_CONTROL:
- BluetoothVolumeControl vcs = (BluetoothVolumeControl) proxy;
- vcs.close();
- break;
- case BluetoothProfile.CSIP_SET_COORDINATOR:
- BluetoothCsipSetCoordinator csipSetCoordinator =
- (BluetoothCsipSetCoordinator) proxy;
- csipSetCoordinator.close();
- break;
- case BluetoothProfile.LE_CALL_CONTROL:
- BluetoothLeCallControl tbs = (BluetoothLeCallControl) proxy;
- tbs.close();
- break;
- }
- }
-
- private static final IBluetoothManagerCallback sManagerCallback =
- new IBluetoothManagerCallback.Stub() {
- public void onBluetoothServiceUp(IBluetooth bluetoothService) {
- if (DBG) {
- Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
- }
-
- synchronized (sServiceLock) {
- sService = bluetoothService;
- for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) {
- try {
- if (cb != null) {
- cb.onBluetoothServiceUp(bluetoothService);
- } else {
- Log.d(TAG, "onBluetoothServiceUp: cb is null!");
- }
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
- }
- }
-
- public void onBluetoothServiceDown() {
- if (DBG) {
- Log.d(TAG, "onBluetoothServiceDown");
- }
-
- synchronized (sServiceLock) {
- sService = null;
- for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) {
- try {
- if (cb != null) {
- cb.onBluetoothServiceDown();
- } else {
- Log.d(TAG, "onBluetoothServiceDown: cb is null!");
- }
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
- }
- }
-
- public void onBrEdrDown() {
- if (VDBG) {
- Log.i(TAG, "onBrEdrDown");
- }
-
- synchronized (sServiceLock) {
- for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) {
- try {
- if (cb != null) {
- cb.onBrEdrDown();
- } else {
- Log.d(TAG, "onBrEdrDown: cb is null!");
- }
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
- }
- }
- };
-
- private final IBluetoothManagerCallback mManagerCallback =
- new IBluetoothManagerCallback.Stub() {
- public void onBluetoothServiceUp(IBluetooth bluetoothService) {
- synchronized (mServiceLock.writeLock()) {
- mService = bluetoothService;
- }
- synchronized (mMetadataListeners) {
- mMetadataListeners.forEach((device, pair) -> {
- try {
- mService.registerMetadataListener(mBluetoothMetadataListener,
- device, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to register metadata listener", e);
- }
- });
- }
- synchronized (mBluetoothConnectionCallbackExecutorMap) {
- if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
- try {
- mService.registerBluetoothConnectionCallback(mConnectionCallback,
- mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "onBluetoothServiceUp: Failed to register bluetooth"
- + "connection callback", e);
- }
- }
- }
- }
-
- public void onBluetoothServiceDown() {
- synchronized (mServiceLock.writeLock()) {
- mService = null;
- if (mLeScanClients != null) {
- mLeScanClients.clear();
- }
- if (mBluetoothLeAdvertiser != null) {
- mBluetoothLeAdvertiser.cleanup();
- }
- if (mBluetoothLeScanner != null) {
- mBluetoothLeScanner.cleanup();
- }
- }
- }
-
- public void onBrEdrDown() {
- }
- };
-
- /**
- * Enable the Bluetooth Adapter, but don't auto-connect devices
- * and don't persist state. Only for use by system applications.
- *
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean enableNoAutoConnect() {
- if (isEnabled()) {
- if (DBG) {
- Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
- }
- return true;
- }
- try {
- return mManagerService.enableNoAutoConnect(mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- BluetoothStatusCodes.ERROR_UNKNOWN,
- BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
- BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_OOB_REQUEST,
- })
- public @interface OobError {}
-
- /**
- * Provides callback methods for receiving {@link OobData} from the host stack, as well as an
- * error interface in order to allow the caller to determine next steps based on the {@code
- * ErrorCode}.
- *
- * @hide
- */
- @SystemApi
- public interface OobDataCallback {
- /**
- * Handles the {@link OobData} received from the host stack.
- *
- * @param transport - whether the {@link OobData} is generated for LE or Classic.
- * @param oobData - data generated in the host stack(LE) or controller (Classic)
- */
- void onOobData(@Transport int transport, @NonNull OobData oobData);
-
- /**
- * Provides feedback when things don't go as expected.
- *
- * @param errorCode - the code describing the type of error that occurred.
- */
- void onError(@OobError int errorCode);
- }
-
- /**
- * Wraps an AIDL interface around an {@link OobDataCallback} interface.
- *
- * @see {@link IBluetoothOobDataCallback} for interface definition.
- *
- * @hide
- */
- public class WrappedOobDataCallback extends IBluetoothOobDataCallback.Stub {
- private final OobDataCallback mCallback;
- private final Executor mExecutor;
-
- /**
- * @param callback - object to receive {@link OobData} must be a non null argument
- *
- * @throws NullPointerException if the callback is null.
- */
- WrappedOobDataCallback(@NonNull OobDataCallback callback,
- @NonNull @CallbackExecutor Executor executor) {
- requireNonNull(callback);
- requireNonNull(executor);
- mCallback = callback;
- mExecutor = executor;
- }
- /**
- * Wrapper function to relay to the {@link OobDataCallback#onOobData}
- *
- * @param transport - whether the {@link OobData} is generated for LE or Classic.
- * @param oobData - data generated in the host stack(LE) or controller (Classic)
- *
- * @hide
- */
- public void onOobData(@Transport int transport, @NonNull OobData oobData) {
- mExecutor.execute(new Runnable() {
- public void run() {
- mCallback.onOobData(transport, oobData);
- }
- });
- }
- /**
- * Wrapper function to relay to the {@link OobDataCallback#onError}
- *
- * @param errorCode - the code descibing the type of error that occurred.
- *
- * @hide
- */
- public void onError(@OobError int errorCode) {
- mExecutor.execute(new Runnable() {
- public void run() {
- mCallback.onError(errorCode);
- }
- });
- }
- }
-
- /**
- * Fetches a secret data value that can be used for a secure and simple pairing experience.
- *
- * <p>This is the Local Out of Band data the comes from the
- *
- * <p>This secret is the local Out of Band data. This data is used to securely and quickly
- * pair two devices with minimal user interaction.
- *
- * <p>For example, this secret can be transferred to a remote device out of band (meaning any
- * other way besides using bluetooth). Once the remote device finds this device using the
- * information given in the data, such as the PUBLIC ADDRESS, the remote device could then
- * connect to this device using this secret when the pairing sequenece asks for the secret.
- * This device will respond by automatically accepting the pairing due to the secret being so
- * trustworthy.
- *
- * @param transport - provide type of transport (e.g. LE or Classic).
- * @param callback - target object to receive the {@link OobData} value.
- *
- * @throws NullPointerException if callback is null.
- * @throws IllegalArgumentException if the transport is not valid.
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public void generateLocalOobData(@Transport int transport,
- @NonNull @CallbackExecutor Executor executor, @NonNull OobDataCallback callback) {
- if (transport != BluetoothDevice.TRANSPORT_BREDR && transport
- != BluetoothDevice.TRANSPORT_LE) {
- throw new IllegalArgumentException("Invalid transport '" + transport + "'!");
- }
- requireNonNull(callback);
- if (!isEnabled()) {
- Log.w(TAG, "generateLocalOobData(): Adapter isn't enabled!");
- callback.onError(BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED);
- } else {
- try {
- mService.generateLocalOobData(transport, new WrappedOobDataCallback(callback,
- executor), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- }
-
- /**
- * Enable control of the Bluetooth Adapter for a single application.
- *
- * <p>Some applications need to use Bluetooth for short periods of time to
- * transfer data but don't want all the associated implications like
- * automatic connection to headsets etc.
- *
- * <p> Multiple applications can call this. This is reference counted and
- * Bluetooth disabled only when no one else is using it. There will be no UI
- * shown to the user while bluetooth is being enabled. Any user action will
- * override this call. For example, if user wants Bluetooth on and the last
- * user of this API wanted to disable Bluetooth, Bluetooth will not be
- * turned off.
- *
- * <p> This API is only meant to be used by internal applications. Third
- * party applications but use {@link #enable} and {@link #disable} APIs.
- *
- * <p> If this API returns true, it means the callback will be called.
- * The callback will be called with the current state of Bluetooth.
- * If the state is not what was requested, an internal error would be the
- * reason. If Bluetooth is already on and if this function is called to turn
- * it on, the api will return true and a callback will be called.
- *
- * @param on True for on, false for off.
- * @param callback The callback to notify changes to the state.
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public boolean changeApplicationBluetoothState(boolean on,
- BluetoothStateChangeCallback callback) {
- return false;
- }
-
- /**
- * @hide
- */
- public interface BluetoothStateChangeCallback {
- /**
- * @hide
- */
- void onBluetoothStateChange(boolean on);
- }
-
- /**
- * @hide
- */
- public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
- private BluetoothStateChangeCallback mCallback;
-
- StateChangeCallbackWrapper(BluetoothStateChangeCallback callback) {
- mCallback = callback;
- }
-
- @Override
- public void onBluetoothStateChange(boolean on) {
- mCallback.onBluetoothStateChange(on);
- }
- }
-
- private Set<BluetoothDevice> toDeviceSet(List<BluetoothDevice> devices) {
- Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(devices);
- return Collections.unmodifiableSet(deviceSet);
- }
-
- protected void finalize() throws Throwable {
- try {
- removeServiceStateCallback(mManagerCallback);
- } finally {
- super.finalize();
- }
- }
-
- /**
- * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
- * <p>Alphabetic characters must be uppercase to be valid.
- *
- * @param address Bluetooth address as string
- * @return true if the address is valid, false otherwise
- */
- public static boolean checkBluetoothAddress(String address) {
- if (address == null || address.length() != ADDRESS_LENGTH) {
- return false;
- }
- for (int i = 0; i < ADDRESS_LENGTH; i++) {
- char c = address.charAt(i);
- switch (i % 3) {
- case 0:
- case 1:
- if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
- // hex character, OK
- break;
- }
- return false;
- case 2:
- if (c == ':') {
- break; // OK
- }
- return false;
- }
- }
- return true;
- }
-
- /**
- * Determines whether a String Bluetooth address, such as "F0:43:A8:23:10:00"
- * is a RANDOM STATIC address.
- *
- * RANDOM STATIC: (addr & 0xC0) == 0xC0
- * RANDOM RESOLVABLE: (addr & 0xC0) == 0x40
- * RANDOM non-RESOLVABLE: (addr & 0xC0) == 0x00
- *
- * @param address Bluetooth address as string
- * @return true if the 2 Most Significant Bits of the address equals 0xC0.
- *
- * @hide
- */
- public static boolean isAddressRandomStatic(@NonNull String address) {
- requireNonNull(address);
- return checkBluetoothAddress(address)
- && (Integer.parseInt(address.split(":")[0], 16) & 0xC0) == 0xC0;
- }
-
- /** {@hide} */
- @UnsupportedAppUsage
- @RequiresNoPermission
- public IBluetoothManager getBluetoothManager() {
- return mManagerService;
- }
-
- /** {@hide} */
- @RequiresNoPermission
- public AttributionSource getAttributionSource() {
- return mAttributionSource;
- }
-
- @GuardedBy("sServiceLock")
- private static final WeakHashMap<IBluetoothManagerCallback, Void> sProxyServiceStateCallbacks =
- new WeakHashMap<>();
-
- /*package*/ IBluetooth getBluetoothService() {
- synchronized (sServiceLock) {
- if (sProxyServiceStateCallbacks.isEmpty()) {
- throw new IllegalStateException(
- "Anonymous service access requires at least one lifecycle in process");
- }
- return sService;
- }
- }
-
- @UnsupportedAppUsage
- /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
- Objects.requireNonNull(cb);
- synchronized (sServiceLock) {
- sProxyServiceStateCallbacks.put(cb, null);
- registerOrUnregisterAdapterLocked();
- return sService;
- }
- }
-
- /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
- Objects.requireNonNull(cb);
- synchronized (sServiceLock) {
- sProxyServiceStateCallbacks.remove(cb);
- registerOrUnregisterAdapterLocked();
- }
- }
-
- /**
- * Handle registering (or unregistering) a single process-wide
- * {@link IBluetoothManagerCallback} based on the presence of local
- * {@link #sProxyServiceStateCallbacks} clients.
- */
- @GuardedBy("sServiceLock")
- private void registerOrUnregisterAdapterLocked() {
- final boolean isRegistered = sServiceRegistered;
- final boolean wantRegistered = !sProxyServiceStateCallbacks.isEmpty();
-
- if (isRegistered != wantRegistered) {
- if (wantRegistered) {
- try {
- sService = mManagerService.registerAdapter(sManagerCallback);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- } else {
- try {
- mManagerService.unregisterAdapter(sManagerCallback);
- sService = null;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- sServiceRegistered = wantRegistered;
- }
- }
-
- /**
- * Callback interface used to deliver LE scan results.
- *
- * @see #startLeScan(LeScanCallback)
- * @see #startLeScan(UUID[], LeScanCallback)
- */
- public interface LeScanCallback {
- /**
- * Callback reporting an LE device found during a device scan initiated
- * by the {@link BluetoothAdapter#startLeScan} function.
- *
- * @param device Identifies the remote device
- * @param rssi The RSSI value for the remote device as reported by the Bluetooth hardware. 0
- * if no RSSI value is available.
- * @param scanRecord The content of the advertisement record offered by the remote device.
- */
- void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
- }
-
- /**
- * Register a callback to receive events whenever the bluetooth stack goes down and back up,
- * e.g. in the event the bluetooth is turned off/on via settings.
- *
- * If the bluetooth stack is currently up, there will not be an initial callback call.
- * You can use the return value as an indication of this being the case.
- *
- * Callbacks will be delivered on a binder thread.
- *
- * @return whether bluetooth is already up currently
- *
- * @hide
- */
- public boolean registerServiceLifecycleCallback(ServiceLifecycleCallback callback) {
- return getBluetoothService(callback.mRemote) != null;
- }
-
- /**
- * Unregister a callback registered via {@link #registerServiceLifecycleCallback}
- *
- * @hide
- */
- public void unregisterServiceLifecycleCallback(ServiceLifecycleCallback callback) {
- removeServiceStateCallback(callback.mRemote);
- }
-
- /**
- * A callback for {@link #registerServiceLifecycleCallback}
- *
- * @hide
- */
- public abstract static class ServiceLifecycleCallback {
-
- /** Called when the bluetooth stack is up */
- public abstract void onBluetoothServiceUp();
-
- /** Called when the bluetooth stack is down */
- public abstract void onBluetoothServiceDown();
-
- IBluetoothManagerCallback mRemote = new IBluetoothManagerCallback.Stub() {
- @Override
- public void onBluetoothServiceUp(IBluetooth bluetoothService) {
- ServiceLifecycleCallback.this.onBluetoothServiceUp();
- }
-
- @Override
- public void onBluetoothServiceDown() {
- ServiceLifecycleCallback.this.onBluetoothServiceDown();
- }
-
- @Override
- public void onBrEdrDown() {}
- };
- }
-
- /**
- * Starts a scan for Bluetooth LE devices.
- *
- * <p>Results of the scan are reported using the
- * {@link LeScanCallback#onLeScan} callback.
- *
- * @param callback the callback LE scan results are delivered
- * @return true, if the scan was started successfully
- * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
- * instead.
- */
- @Deprecated
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public boolean startLeScan(LeScanCallback callback) {
- return startLeScan(null, callback);
- }
-
- /**
- * Starts a scan for Bluetooth LE devices, looking for devices that
- * advertise given services.
- *
- * <p>Devices which advertise all specified services are reported using the
- * {@link LeScanCallback#onLeScan} callback.
- *
- * @param serviceUuids Array of services to look for
- * @param callback the callback LE scan results are delivered
- * @return true, if the scan was started successfully
- * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
- * instead.
- */
- @Deprecated
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
- if (DBG) {
- Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
- }
- if (callback == null) {
- if (DBG) {
- Log.e(TAG, "startLeScan: null callback");
- }
- return false;
- }
- BluetoothLeScanner scanner = getBluetoothLeScanner();
- if (scanner == null) {
- if (DBG) {
- Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
- }
- return false;
- }
-
- synchronized (mLeScanClients) {
- if (mLeScanClients.containsKey(callback)) {
- if (DBG) {
- Log.e(TAG, "LE Scan has already started");
- }
- return false;
- }
-
- try {
- IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
- if (iGatt == null) {
- // BLE is not supported
- return false;
- }
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- ScanCallback scanCallback = new ScanCallback() {
- @Override
- public void onScanResult(int callbackType, ScanResult result) {
- if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
- // Should not happen.
- Log.e(TAG, "LE Scan has already started");
- return;
- }
- ScanRecord scanRecord = result.getScanRecord();
- if (scanRecord == null) {
- return;
- }
- if (serviceUuids != null) {
- List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
- for (UUID uuid : serviceUuids) {
- uuids.add(new ParcelUuid(uuid));
- }
- List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
- if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
- if (DBG) {
- Log.d(TAG, "uuids does not match");
- }
- return;
- }
- }
- callback.onLeScan(result.getDevice(), result.getRssi(),
- scanRecord.getBytes());
- }
- };
- ScanSettings settings = new ScanSettings.Builder().setCallbackType(
- ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
- .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
- .build();
-
- List<ScanFilter> filters = new ArrayList<ScanFilter>();
- if (serviceUuids != null && serviceUuids.length > 0) {
- // Note scan filter does not support matching an UUID array so we put one
- // UUID to hardware and match the whole array in callback.
- ScanFilter filter =
- new ScanFilter.Builder().setServiceUuid(new ParcelUuid(serviceUuids[0]))
- .build();
- filters.add(filter);
- }
- scanner.startScan(filters, settings, scanCallback);
-
- mLeScanClients.put(callback, scanCallback);
- return true;
-
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- return false;
- }
-
- /**
- * Stops an ongoing Bluetooth LE device scan.
- *
- * @param callback used to identify which scan to stop must be the same handle used to start the
- * scan
- * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
- */
- @Deprecated
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void stopLeScan(LeScanCallback callback) {
- if (DBG) {
- Log.d(TAG, "stopLeScan()");
- }
- BluetoothLeScanner scanner = getBluetoothLeScanner();
- if (scanner == null) {
- return;
- }
- synchronized (mLeScanClients) {
- ScanCallback scanCallback = mLeScanClients.remove(callback);
- if (scanCallback == null) {
- if (DBG) {
- Log.d(TAG, "scan not started yet");
- }
- return;
- }
- scanner.stopScan(scanCallback);
- }
- }
-
- /**
- * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
- * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
- * for incoming connections. The supported Bluetooth transport is LE only.
- * <p>A remote device connecting to this socket will be authenticated and communication on this
- * socket will be encrypted.
- * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
- * {@link BluetoothServerSocket}.
- * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {@link
- * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is
- * closed, Bluetooth is turned off, or the application exits unexpectedly.
- * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
- * defined and performed by the application.
- * <p>Use {@link BluetoothDevice#createL2capChannel(int)} to connect to this server
- * socket from another Android device that is given the PSM value.
- *
- * @return an L2CAP CoC BluetoothServerSocket
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions, or unable to start this CoC
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @NonNull BluetoothServerSocket listenUsingL2capChannel()
- throws IOException {
- BluetoothServerSocket socket =
- new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
- SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
- int errno = socket.mSocket.bindListen();
- if (errno != 0) {
- throw new IOException("Error: " + errno);
- }
-
- int assignedPsm = socket.mSocket.getPort();
- if (assignedPsm == 0) {
- throw new IOException("Error: Unable to assign PSM value");
- }
- if (DBG) {
- Log.d(TAG, "listenUsingL2capChannel: set assigned PSM to "
- + assignedPsm);
- }
- socket.setChannel(assignedPsm);
-
- return socket;
- }
-
- /**
- * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
- * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
- * supported Bluetooth transport is LE only.
- * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
- * to person-in-the-middle attacks. Use {@link #listenUsingL2capChannel}, if an encrypted and
- * authenticated communication channel is desired.
- * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
- * {@link BluetoothServerSocket}.
- * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value
- * can be read from the {@link BluetoothServerSocket#getPsm()} and this value will be released
- * when this server socket is closed, Bluetooth is turned off, or the application exits
- * unexpectedly.
- * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
- * defined and performed by the application.
- * <p>Use {@link BluetoothDevice#createInsecureL2capChannel(int)} to connect to this server
- * socket from another Android device that is given the PSM value.
- *
- * @return an L2CAP CoC BluetoothServerSocket
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions, or unable to start this CoC
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @NonNull BluetoothServerSocket listenUsingInsecureL2capChannel()
- throws IOException {
- BluetoothServerSocket socket =
- new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
- SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
- int errno = socket.mSocket.bindListen();
- if (errno != 0) {
- throw new IOException("Error: " + errno);
- }
-
- int assignedPsm = socket.mSocket.getPort();
- if (assignedPsm == 0) {
- throw new IOException("Error: Unable to assign PSM value");
- }
- if (DBG) {
- Log.d(TAG, "listenUsingInsecureL2capChannel: set assigned PSM to "
- + assignedPsm);
- }
- socket.setChannel(assignedPsm);
-
- return socket;
- }
-
- /**
- * Register a {@link #OnMetadataChangedListener} to receive update about metadata
- * changes for this {@link BluetoothDevice}.
- * Registration must be done when Bluetooth is ON and will last until
- * {@link #removeOnMetadataChangedListener(BluetoothDevice)} is called, even when Bluetooth
- * restarted in the middle.
- * All input parameters should not be null or {@link NullPointerException} will be triggered.
- * The same {@link BluetoothDevice} and {@link #OnMetadataChangedListener} pair can only be
- * registered once, double registration would cause {@link IllegalArgumentException}.
- *
- * @param device {@link BluetoothDevice} that will be registered
- * @param executor the executor for listener callback
- * @param listener {@link #OnMetadataChangedListener} that will receive asynchronous callbacks
- * @return true on success, false on error
- * @throws NullPointerException If one of {@code listener}, {@code device} or {@code executor}
- * is null.
- * @throws IllegalArgumentException The same {@link #OnMetadataChangedListener} and
- * {@link BluetoothDevice} are registered twice.
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean addOnMetadataChangedListener(@NonNull BluetoothDevice device,
- @NonNull Executor executor, @NonNull OnMetadataChangedListener listener) {
- if (DBG) Log.d(TAG, "addOnMetadataChangedListener()");
-
- final IBluetooth service = mService;
- if (service == null) {
- Log.e(TAG, "Bluetooth is not enabled. Cannot register metadata listener");
- return false;
- }
- if (listener == null) {
- throw new NullPointerException("listener is null");
- }
- if (device == null) {
- throw new NullPointerException("device is null");
- }
- if (executor == null) {
- throw new NullPointerException("executor is null");
- }
-
- synchronized (mMetadataListeners) {
- List<Pair<OnMetadataChangedListener, Executor>> listenerList =
- mMetadataListeners.get(device);
- if (listenerList == null) {
- // Create new listener/executor list for registeration
- listenerList = new ArrayList<>();
- mMetadataListeners.put(device, listenerList);
- } else {
- // Check whether this device was already registed by the lisenter
- if (listenerList.stream().anyMatch((pair) -> (pair.first.equals(listener)))) {
- throw new IllegalArgumentException("listener was already regestered"
- + " for the device");
- }
- }
-
- Pair<OnMetadataChangedListener, Executor> listenerPair = new Pair(listener, executor);
- listenerList.add(listenerPair);
-
- boolean ret = false;
- try {
- ret = service.registerMetadataListener(mBluetoothMetadataListener, device,
- mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "registerMetadataListener fail", e);
- } finally {
- if (!ret) {
- // Remove listener registered earlier when fail.
- listenerList.remove(listenerPair);
- if (listenerList.isEmpty()) {
- // Remove the device if its listener list is empty
- mMetadataListeners.remove(device);
- }
- }
- }
- return ret;
- }
- }
-
- /**
- * Unregister a {@link #OnMetadataChangedListener} from a registered {@link BluetoothDevice}.
- * Unregistration can be done when Bluetooth is either ON or OFF.
- * {@link #addOnMetadataChangedListener(OnMetadataChangedListener, BluetoothDevice, Executor)}
- * must be called before unregisteration.
- *
- * @param device {@link BluetoothDevice} that will be unregistered. It
- * should not be null or {@link NullPointerException} will be triggered.
- * @param listener {@link OnMetadataChangedListener} that will be unregistered. It
- * should not be null or {@link NullPointerException} will be triggered.
- * @return true on success, false on error
- * @throws NullPointerException If {@code listener} or {@code device} is null.
- * @throws IllegalArgumentException If {@code device} has not been registered before.
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean removeOnMetadataChangedListener(@NonNull BluetoothDevice device,
- @NonNull OnMetadataChangedListener listener) {
- if (DBG) Log.d(TAG, "removeOnMetadataChangedListener()");
- if (device == null) {
- throw new NullPointerException("device is null");
- }
- if (listener == null) {
- throw new NullPointerException("listener is null");
- }
-
- synchronized (mMetadataListeners) {
- if (!mMetadataListeners.containsKey(device)) {
- throw new IllegalArgumentException("device was not registered");
- }
- // Remove issued listener from the registered device
- mMetadataListeners.get(device).removeIf((pair) -> (pair.first.equals(listener)));
-
- if (mMetadataListeners.get(device).isEmpty()) {
- // Unregister to Bluetooth service if all listeners are removed from
- // the registered device
- mMetadataListeners.remove(device);
- final IBluetooth service = mService;
- if (service == null) {
- // Bluetooth is OFF, do nothing to Bluetooth service.
- return true;
- }
- try {
- return service.unregisterMetadataListener(device, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "unregisterMetadataListener fail", e);
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * This interface is used to implement {@link BluetoothAdapter} metadata listener.
- * @hide
- */
- @SystemApi
- public interface OnMetadataChangedListener {
- /**
- * Callback triggered if the metadata of {@link BluetoothDevice} registered in
- * {@link #addOnMetadataChangedListener}.
- *
- * @param device changed {@link BluetoothDevice}.
- * @param key changed metadata key, one of BluetoothDevice.METADATA_*.
- * @param value the new value of metadata as byte array.
- */
- void onMetadataChanged(@NonNull BluetoothDevice device, int key,
- @Nullable byte[] value);
- }
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private final IBluetoothConnectionCallback mConnectionCallback =
- new IBluetoothConnectionCallback.Stub() {
- @Override
- public void onDeviceConnected(BluetoothDevice device) {
- Attributable.setAttributionSource(device, mAttributionSource);
- for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
- mBluetoothConnectionCallbackExecutorMap.entrySet()) {
- BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
- Executor executor = callbackExecutorEntry.getValue();
- executor.execute(() -> callback.onDeviceConnected(device));
- }
- }
-
- @Override
- public void onDeviceDisconnected(BluetoothDevice device, int hciReason) {
- Attributable.setAttributionSource(device, mAttributionSource);
- for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
- mBluetoothConnectionCallbackExecutorMap.entrySet()) {
- BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
- Executor executor = callbackExecutorEntry.getValue();
- executor.execute(() -> callback.onDeviceDisconnected(device, hciReason));
- }
- }
- };
-
- /**
- * Registers the BluetoothConnectionCallback to receive callback events when a bluetooth device
- * (classic or low energy) is connected or disconnected.
- *
- * @param executor is the callback executor
- * @param callback is the connection callback you wish to register
- * @return true if the callback was registered successfully, false otherwise
- * @throws IllegalArgumentException if the callback is already registered
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean registerBluetoothConnectionCallback(@NonNull @CallbackExecutor Executor executor,
- @NonNull BluetoothConnectionCallback callback) {
- if (DBG) Log.d(TAG, "registerBluetoothConnectionCallback()");
- if (callback == null) {
- return false;
- }
-
- synchronized (mBluetoothConnectionCallbackExecutorMap) {
- // If the callback map is empty, we register the service-to-app callback
- if (mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- if (!mService.registerBluetoothConnectionCallback(mConnectionCallback,
- mAttributionSource)) {
- return false;
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- mBluetoothConnectionCallbackExecutorMap.remove(callback);
- } finally {
- mServiceLock.readLock().unlock();
- }
- }
-
- // Adds the passed in callback to our map of callbacks to executors
- if (mBluetoothConnectionCallbackExecutorMap.containsKey(callback)) {
- throw new IllegalArgumentException("This callback has already been registered");
- }
- mBluetoothConnectionCallbackExecutorMap.put(callback, executor);
- }
-
- return true;
- }
-
- /**
- * Unregisters the BluetoothConnectionCallback that was previously registered by the application
- *
- * @param callback is the connection callback you wish to unregister
- * @return true if the callback was unregistered successfully, false otherwise
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean unregisterBluetoothConnectionCallback(
- @NonNull BluetoothConnectionCallback callback) {
- if (DBG) Log.d(TAG, "unregisterBluetoothConnectionCallback()");
- if (callback == null) {
- return false;
- }
-
- synchronized (mBluetoothConnectionCallbackExecutorMap) {
- if (mBluetoothConnectionCallbackExecutorMap.remove(callback) != null) {
- return false;
- }
- }
-
- if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
- return true;
- }
-
- // If the callback map is empty, we unregister the service-to-app callback
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.unregisterBluetoothConnectionCallback(mConnectionCallback,
- mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
-
- return false;
- }
-
- /**
- * This abstract class is used to implement callbacks for when a bluetooth classic or Bluetooth
- * Low Energy (BLE) device is either connected or disconnected.
- *
- * @hide
- */
- public abstract static class BluetoothConnectionCallback {
- /**
- * Callback triggered when a bluetooth device (classic or BLE) is connected
- * @param device is the connected bluetooth device
- */
- public void onDeviceConnected(BluetoothDevice device) {}
-
- /**
- * Callback triggered when a bluetooth device (classic or BLE) is disconnected
- * @param device is the disconnected bluetooth device
- * @param reason is the disconnect reason
- */
- public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) {}
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "REASON_" }, value = {
- BluetoothStatusCodes.ERROR_UNKNOWN,
- BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST,
- BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST,
- BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL,
- BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE,
- BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT,
- BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY,
- BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY,
- BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED,
- BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS,
- BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS})
- public @interface DisconnectReason {}
-
- /**
- * Returns human-readable strings corresponding to {@link DisconnectReason}.
- */
- public static String disconnectReasonText(@DisconnectReason int reason) {
- switch (reason) {
- case BluetoothStatusCodes.ERROR_UNKNOWN:
- return "Reason unknown";
- case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST:
- return "Local request";
- case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST:
- return "Remote request";
- case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL:
- return "Local error";
- case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE:
- return "Remote error";
- case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT:
- return "Timeout";
- case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY:
- return "Security";
- case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY:
- return "System policy";
- case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED:
- return "Resource constrained";
- case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS:
- return "Connection already exists";
- case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS:
- return "Bad parameters";
- default:
- return "Unrecognized disconnect reason: " + reason;
- }
- }
- }
-
- /**
- * Converts old constant of priority to the new for connection policy
- *
- * @param priority is the priority to convert to connection policy
- * @return the equivalent connection policy constant to the priority
- *
- * @hide
- */
- public static @ConnectionPolicy int priorityToConnectionPolicy(int priority) {
- switch(priority) {
- case BluetoothProfile.PRIORITY_AUTO_CONNECT:
- return BluetoothProfile.CONNECTION_POLICY_ALLOWED;
- case BluetoothProfile.PRIORITY_ON:
- return BluetoothProfile.CONNECTION_POLICY_ALLOWED;
- case BluetoothProfile.PRIORITY_OFF:
- return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- case BluetoothProfile.PRIORITY_UNDEFINED:
- return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
- default:
- Log.e(TAG, "setPriority: Invalid priority: " + priority);
- return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
- }
- }
-
- /**
- * Converts new constant of connection policy to the old for priority
- *
- * @param connectionPolicy is the connection policy to convert to priority
- * @return the equivalent priority constant to the connectionPolicy
- *
- * @hide
- */
- public static int connectionPolicyToPriority(@ConnectionPolicy int connectionPolicy) {
- switch(connectionPolicy) {
- case BluetoothProfile.CONNECTION_POLICY_ALLOWED:
- return BluetoothProfile.PRIORITY_ON;
- case BluetoothProfile.CONNECTION_POLICY_FORBIDDEN:
- return BluetoothProfile.PRIORITY_OFF;
- case BluetoothProfile.CONNECTION_POLICY_UNKNOWN:
- return BluetoothProfile.PRIORITY_UNDEFINED;
- }
- return BluetoothProfile.PRIORITY_UNDEFINED;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothAssignedNumbers.java b/core/java/android/bluetooth/BluetoothAssignedNumbers.java
deleted file mode 100644
index 41a34e0..0000000
--- a/core/java/android/bluetooth/BluetoothAssignedNumbers.java
+++ /dev/null
@@ -1,1171 +0,0 @@
-/*
- * Copyright (C) 2010 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.bluetooth;
-
-/**
- * Bluetooth Assigned Numbers.
- * <p>
- * For now we only include Company ID values.
- *
- * @see <a href="https://www.bluetooth.org/technical/assignednumbers/identifiers.htm"> The Official
- * Bluetooth SIG Member Website | Company Identifiers</a>
- */
-public class BluetoothAssignedNumbers {
-
- // Bluetooth SIG Company ID values
- /*
- * Ericsson Technology Licensing.
- */
- public static final int ERICSSON_TECHNOLOGY = 0x0000;
-
- /*
- * Nokia Mobile Phones.
- */
- public static final int NOKIA_MOBILE_PHONES = 0x0001;
-
- /*
- * Intel Corp.
- */
- public static final int INTEL = 0x0002;
-
- /*
- * IBM Corp.
- */
- public static final int IBM = 0x0003;
-
- /*
- * Toshiba Corp.
- */
- public static final int TOSHIBA = 0x0004;
-
- /*
- * 3Com.
- */
- public static final int THREECOM = 0x0005;
-
- /*
- * Microsoft.
- */
- public static final int MICROSOFT = 0x0006;
-
- /*
- * Lucent.
- */
- public static final int LUCENT = 0x0007;
-
- /*
- * Motorola.
- */
- public static final int MOTOROLA = 0x0008;
-
- /*
- * Infineon Technologies AG.
- */
- public static final int INFINEON_TECHNOLOGIES = 0x0009;
-
- /*
- * Cambridge Silicon Radio.
- */
- public static final int CAMBRIDGE_SILICON_RADIO = 0x000A;
-
- /*
- * Silicon Wave.
- */
- public static final int SILICON_WAVE = 0x000B;
-
- /*
- * Digianswer A/S.
- */
- public static final int DIGIANSWER = 0x000C;
-
- /*
- * Texas Instruments Inc.
- */
- public static final int TEXAS_INSTRUMENTS = 0x000D;
-
- /*
- * Parthus Technologies Inc.
- */
- public static final int PARTHUS_TECHNOLOGIES = 0x000E;
-
- /*
- * Broadcom Corporation.
- */
- public static final int BROADCOM = 0x000F;
-
- /*
- * Mitel Semiconductor.
- */
- public static final int MITEL_SEMICONDUCTOR = 0x0010;
-
- /*
- * Widcomm, Inc.
- */
- public static final int WIDCOMM = 0x0011;
-
- /*
- * Zeevo, Inc.
- */
- public static final int ZEEVO = 0x0012;
-
- /*
- * Atmel Corporation.
- */
- public static final int ATMEL = 0x0013;
-
- /*
- * Mitsubishi Electric Corporation.
- */
- public static final int MITSUBISHI_ELECTRIC = 0x0014;
-
- /*
- * RTX Telecom A/S.
- */
- public static final int RTX_TELECOM = 0x0015;
-
- /*
- * KC Technology Inc.
- */
- public static final int KC_TECHNOLOGY = 0x0016;
-
- /*
- * Newlogic.
- */
- public static final int NEWLOGIC = 0x0017;
-
- /*
- * Transilica, Inc.
- */
- public static final int TRANSILICA = 0x0018;
-
- /*
- * Rohde & Schwarz GmbH & Co. KG.
- */
- public static final int ROHDE_AND_SCHWARZ = 0x0019;
-
- /*
- * TTPCom Limited.
- */
- public static final int TTPCOM = 0x001A;
-
- /*
- * Signia Technologies, Inc.
- */
- public static final int SIGNIA_TECHNOLOGIES = 0x001B;
-
- /*
- * Conexant Systems Inc.
- */
- public static final int CONEXANT_SYSTEMS = 0x001C;
-
- /*
- * Qualcomm.
- */
- public static final int QUALCOMM = 0x001D;
-
- /*
- * Inventel.
- */
- public static final int INVENTEL = 0x001E;
-
- /*
- * AVM Berlin.
- */
- public static final int AVM_BERLIN = 0x001F;
-
- /*
- * BandSpeed, Inc.
- */
- public static final int BANDSPEED = 0x0020;
-
- /*
- * Mansella Ltd.
- */
- public static final int MANSELLA = 0x0021;
-
- /*
- * NEC Corporation.
- */
- public static final int NEC = 0x0022;
-
- /*
- * WavePlus Technology Co., Ltd.
- */
- public static final int WAVEPLUS_TECHNOLOGY = 0x0023;
-
- /*
- * Alcatel.
- */
- public static final int ALCATEL = 0x0024;
-
- /*
- * Philips Semiconductors.
- */
- public static final int PHILIPS_SEMICONDUCTORS = 0x0025;
-
- /*
- * C Technologies.
- */
- public static final int C_TECHNOLOGIES = 0x0026;
-
- /*
- * Open Interface.
- */
- public static final int OPEN_INTERFACE = 0x0027;
-
- /*
- * R F Micro Devices.
- */
- public static final int RF_MICRO_DEVICES = 0x0028;
-
- /*
- * Hitachi Ltd.
- */
- public static final int HITACHI = 0x0029;
-
- /*
- * Symbol Technologies, Inc.
- */
- public static final int SYMBOL_TECHNOLOGIES = 0x002A;
-
- /*
- * Tenovis.
- */
- public static final int TENOVIS = 0x002B;
-
- /*
- * Macronix International Co. Ltd.
- */
- public static final int MACRONIX = 0x002C;
-
- /*
- * GCT Semiconductor.
- */
- public static final int GCT_SEMICONDUCTOR = 0x002D;
-
- /*
- * Norwood Systems.
- */
- public static final int NORWOOD_SYSTEMS = 0x002E;
-
- /*
- * MewTel Technology Inc.
- */
- public static final int MEWTEL_TECHNOLOGY = 0x002F;
-
- /*
- * ST Microelectronics.
- */
- public static final int ST_MICROELECTRONICS = 0x0030;
-
- /*
- * Synopsys.
- */
- public static final int SYNOPSYS = 0x0031;
-
- /*
- * Red-M (Communications) Ltd.
- */
- public static final int RED_M = 0x0032;
-
- /*
- * Commil Ltd.
- */
- public static final int COMMIL = 0x0033;
-
- /*
- * Computer Access Technology Corporation (CATC).
- */
- public static final int CATC = 0x0034;
-
- /*
- * Eclipse (HQ Espana) S.L.
- */
- public static final int ECLIPSE = 0x0035;
-
- /*
- * Renesas Technology Corp.
- */
- public static final int RENESAS_TECHNOLOGY = 0x0036;
-
- /*
- * Mobilian Corporation.
- */
- public static final int MOBILIAN_CORPORATION = 0x0037;
-
- /*
- * Terax.
- */
- public static final int TERAX = 0x0038;
-
- /*
- * Integrated System Solution Corp.
- */
- public static final int INTEGRATED_SYSTEM_SOLUTION = 0x0039;
-
- /*
- * Matsushita Electric Industrial Co., Ltd.
- */
- public static final int MATSUSHITA_ELECTRIC = 0x003A;
-
- /*
- * Gennum Corporation.
- */
- public static final int GENNUM = 0x003B;
-
- /*
- * Research In Motion.
- */
- public static final int RESEARCH_IN_MOTION = 0x003C;
-
- /*
- * IPextreme, Inc.
- */
- public static final int IPEXTREME = 0x003D;
-
- /*
- * Systems and Chips, Inc.
- */
- public static final int SYSTEMS_AND_CHIPS = 0x003E;
-
- /*
- * Bluetooth SIG, Inc.
- */
- public static final int BLUETOOTH_SIG = 0x003F;
-
- /*
- * Seiko Epson Corporation.
- */
- public static final int SEIKO_EPSON = 0x0040;
-
- /*
- * Integrated Silicon Solution Taiwan, Inc.
- */
- public static final int INTEGRATED_SILICON_SOLUTION = 0x0041;
-
- /*
- * CONWISE Technology Corporation Ltd.
- */
- public static final int CONWISE_TECHNOLOGY = 0x0042;
-
- /*
- * PARROT SA.
- */
- public static final int PARROT = 0x0043;
-
- /*
- * Socket Mobile.
- */
- public static final int SOCKET_MOBILE = 0x0044;
-
- /*
- * Atheros Communications, Inc.
- */
- public static final int ATHEROS_COMMUNICATIONS = 0x0045;
-
- /*
- * MediaTek, Inc.
- */
- public static final int MEDIATEK = 0x0046;
-
- /*
- * Bluegiga.
- */
- public static final int BLUEGIGA = 0x0047;
-
- /*
- * Marvell Technology Group Ltd.
- */
- public static final int MARVELL = 0x0048;
-
- /*
- * 3DSP Corporation.
- */
- public static final int THREE_DSP = 0x0049;
-
- /*
- * Accel Semiconductor Ltd.
- */
- public static final int ACCEL_SEMICONDUCTOR = 0x004A;
-
- /*
- * Continental Automotive Systems.
- */
- public static final int CONTINENTAL_AUTOMOTIVE = 0x004B;
-
- /*
- * Apple, Inc.
- */
- public static final int APPLE = 0x004C;
-
- /*
- * Staccato Communications, Inc.
- */
- public static final int STACCATO_COMMUNICATIONS = 0x004D;
-
- /*
- * Avago Technologies.
- */
- public static final int AVAGO = 0x004E;
-
- /*
- * APT Licensing Ltd.
- */
- public static final int APT_LICENSING = 0x004F;
-
- /*
- * SiRF Technology, Inc.
- */
- public static final int SIRF_TECHNOLOGY = 0x0050;
-
- /*
- * Tzero Technologies, Inc.
- */
- public static final int TZERO_TECHNOLOGIES = 0x0051;
-
- /*
- * J&M Corporation.
- */
- public static final int J_AND_M = 0x0052;
-
- /*
- * Free2move AB.
- */
- public static final int FREE2MOVE = 0x0053;
-
- /*
- * 3DiJoy Corporation.
- */
- public static final int THREE_DIJOY = 0x0054;
-
- /*
- * Plantronics, Inc.
- */
- public static final int PLANTRONICS = 0x0055;
-
- /*
- * Sony Ericsson Mobile Communications.
- */
- public static final int SONY_ERICSSON = 0x0056;
-
- /*
- * Harman International Industries, Inc.
- */
- public static final int HARMAN_INTERNATIONAL = 0x0057;
-
- /*
- * Vizio, Inc.
- */
- public static final int VIZIO = 0x0058;
-
- /*
- * Nordic Semiconductor ASA.
- */
- public static final int NORDIC_SEMICONDUCTOR = 0x0059;
-
- /*
- * EM Microelectronic-Marin SA.
- */
- public static final int EM_MICROELECTRONIC_MARIN = 0x005A;
-
- /*
- * Ralink Technology Corporation.
- */
- public static final int RALINK_TECHNOLOGY = 0x005B;
-
- /*
- * Belkin International, Inc.
- */
- public static final int BELKIN_INTERNATIONAL = 0x005C;
-
- /*
- * Realtek Semiconductor Corporation.
- */
- public static final int REALTEK_SEMICONDUCTOR = 0x005D;
-
- /*
- * Stonestreet One, LLC.
- */
- public static final int STONESTREET_ONE = 0x005E;
-
- /*
- * Wicentric, Inc.
- */
- public static final int WICENTRIC = 0x005F;
-
- /*
- * RivieraWaves S.A.S.
- */
- public static final int RIVIERAWAVES = 0x0060;
-
- /*
- * RDA Microelectronics.
- */
- public static final int RDA_MICROELECTRONICS = 0x0061;
-
- /*
- * Gibson Guitars.
- */
- public static final int GIBSON_GUITARS = 0x0062;
-
- /*
- * MiCommand Inc.
- */
- public static final int MICOMMAND = 0x0063;
-
- /*
- * Band XI International, LLC.
- */
- public static final int BAND_XI_INTERNATIONAL = 0x0064;
-
- /*
- * Hewlett-Packard Company.
- */
- public static final int HEWLETT_PACKARD = 0x0065;
-
- /*
- * 9Solutions Oy.
- */
- public static final int NINE_SOLUTIONS = 0x0066;
-
- /*
- * GN Netcom A/S.
- */
- public static final int GN_NETCOM = 0x0067;
-
- /*
- * General Motors.
- */
- public static final int GENERAL_MOTORS = 0x0068;
-
- /*
- * A&D Engineering, Inc.
- */
- public static final int A_AND_D_ENGINEERING = 0x0069;
-
- /*
- * MindTree Ltd.
- */
- public static final int MINDTREE = 0x006A;
-
- /*
- * Polar Electro OY.
- */
- public static final int POLAR_ELECTRO = 0x006B;
-
- /*
- * Beautiful Enterprise Co., Ltd.
- */
- public static final int BEAUTIFUL_ENTERPRISE = 0x006C;
-
- /*
- * BriarTek, Inc.
- */
- public static final int BRIARTEK = 0x006D;
-
- /*
- * Summit Data Communications, Inc.
- */
- public static final int SUMMIT_DATA_COMMUNICATIONS = 0x006E;
-
- /*
- * Sound ID.
- */
- public static final int SOUND_ID = 0x006F;
-
- /*
- * Monster, LLC.
- */
- public static final int MONSTER = 0x0070;
-
- /*
- * connectBlue AB.
- */
- public static final int CONNECTBLUE = 0x0071;
-
- /*
- * ShangHai Super Smart Electronics Co. Ltd.
- */
- public static final int SHANGHAI_SUPER_SMART_ELECTRONICS = 0x0072;
-
- /*
- * Group Sense Ltd.
- */
- public static final int GROUP_SENSE = 0x0073;
-
- /*
- * Zomm, LLC.
- */
- public static final int ZOMM = 0x0074;
-
- /*
- * Samsung Electronics Co. Ltd.
- */
- public static final int SAMSUNG_ELECTRONICS = 0x0075;
-
- /*
- * Creative Technology Ltd.
- */
- public static final int CREATIVE_TECHNOLOGY = 0x0076;
-
- /*
- * Laird Technologies.
- */
- public static final int LAIRD_TECHNOLOGIES = 0x0077;
-
- /*
- * Nike, Inc.
- */
- public static final int NIKE = 0x0078;
-
- /*
- * lesswire AG.
- */
- public static final int LESSWIRE = 0x0079;
-
- /*
- * MStar Semiconductor, Inc.
- */
- public static final int MSTAR_SEMICONDUCTOR = 0x007A;
-
- /*
- * Hanlynn Technologies.
- */
- public static final int HANLYNN_TECHNOLOGIES = 0x007B;
-
- /*
- * A & R Cambridge.
- */
- public static final int A_AND_R_CAMBRIDGE = 0x007C;
-
- /*
- * Seers Technology Co. Ltd.
- */
- public static final int SEERS_TECHNOLOGY = 0x007D;
-
- /*
- * Sports Tracking Technologies Ltd.
- */
- public static final int SPORTS_TRACKING_TECHNOLOGIES = 0x007E;
-
- /*
- * Autonet Mobile.
- */
- public static final int AUTONET_MOBILE = 0x007F;
-
- /*
- * DeLorme Publishing Company, Inc.
- */
- public static final int DELORME_PUBLISHING_COMPANY = 0x0080;
-
- /*
- * WuXi Vimicro.
- */
- public static final int WUXI_VIMICRO = 0x0081;
-
- /*
- * Sennheiser Communications A/S.
- */
- public static final int SENNHEISER_COMMUNICATIONS = 0x0082;
-
- /*
- * TimeKeeping Systems, Inc.
- */
- public static final int TIMEKEEPING_SYSTEMS = 0x0083;
-
- /*
- * Ludus Helsinki Ltd.
- */
- public static final int LUDUS_HELSINKI = 0x0084;
-
- /*
- * BlueRadios, Inc.
- */
- public static final int BLUERADIOS = 0x0085;
-
- /*
- * equinox AG.
- */
- public static final int EQUINOX_AG = 0x0086;
-
- /*
- * Garmin International, Inc.
- */
- public static final int GARMIN_INTERNATIONAL = 0x0087;
-
- /*
- * Ecotest.
- */
- public static final int ECOTEST = 0x0088;
-
- /*
- * GN ReSound A/S.
- */
- public static final int GN_RESOUND = 0x0089;
-
- /*
- * Jawbone.
- */
- public static final int JAWBONE = 0x008A;
-
- /*
- * Topcorn Positioning Systems, LLC.
- */
- public static final int TOPCORN_POSITIONING_SYSTEMS = 0x008B;
-
- /*
- * Qualcomm Labs, Inc.
- */
- public static final int QUALCOMM_LABS = 0x008C;
-
- /*
- * Zscan Software.
- */
- public static final int ZSCAN_SOFTWARE = 0x008D;
-
- /*
- * Quintic Corp.
- */
- public static final int QUINTIC = 0x008E;
-
- /*
- * Stollman E+V GmbH.
- */
- public static final int STOLLMAN_E_PLUS_V = 0x008F;
-
- /*
- * Funai Electric Co., Ltd.
- */
- public static final int FUNAI_ELECTRIC = 0x0090;
-
- /*
- * Advanced PANMOBIL Systems GmbH & Co. KG.
- */
- public static final int ADVANCED_PANMOBIL_SYSTEMS = 0x0091;
-
- /*
- * ThinkOptics, Inc.
- */
- public static final int THINKOPTICS = 0x0092;
-
- /*
- * Universal Electronics, Inc.
- */
- public static final int UNIVERSAL_ELECTRONICS = 0x0093;
-
- /*
- * Airoha Technology Corp.
- */
- public static final int AIROHA_TECHNOLOGY = 0x0094;
-
- /*
- * NEC Lighting, Ltd.
- */
- public static final int NEC_LIGHTING = 0x0095;
-
- /*
- * ODM Technology, Inc.
- */
- public static final int ODM_TECHNOLOGY = 0x0096;
-
- /*
- * Bluetrek Technologies Limited.
- */
- public static final int BLUETREK_TECHNOLOGIES = 0x0097;
-
- /*
- * zer01.tv GmbH.
- */
- public static final int ZER01_TV = 0x0098;
-
- /*
- * i.Tech Dynamic Global Distribution Ltd.
- */
- public static final int I_TECH_DYNAMIC_GLOBAL_DISTRIBUTION = 0x0099;
-
- /*
- * Alpwise.
- */
- public static final int ALPWISE = 0x009A;
-
- /*
- * Jiangsu Toppower Automotive Electronics Co., Ltd.
- */
- public static final int JIANGSU_TOPPOWER_AUTOMOTIVE_ELECTRONICS = 0x009B;
-
- /*
- * Colorfy, Inc.
- */
- public static final int COLORFY = 0x009C;
-
- /*
- * Geoforce Inc.
- */
- public static final int GEOFORCE = 0x009D;
-
- /*
- * Bose Corporation.
- */
- public static final int BOSE = 0x009E;
-
- /*
- * Suunto Oy.
- */
- public static final int SUUNTO = 0x009F;
-
- /*
- * Kensington Computer Products Group.
- */
- public static final int KENSINGTON_COMPUTER_PRODUCTS_GROUP = 0x00A0;
-
- /*
- * SR-Medizinelektronik.
- */
- public static final int SR_MEDIZINELEKTRONIK = 0x00A1;
-
- /*
- * Vertu Corporation Limited.
- */
- public static final int VERTU = 0x00A2;
-
- /*
- * Meta Watch Ltd.
- */
- public static final int META_WATCH = 0x00A3;
-
- /*
- * LINAK A/S.
- */
- public static final int LINAK = 0x00A4;
-
- /*
- * OTL Dynamics LLC.
- */
- public static final int OTL_DYNAMICS = 0x00A5;
-
- /*
- * Panda Ocean Inc.
- */
- public static final int PANDA_OCEAN = 0x00A6;
-
- /*
- * Visteon Corporation.
- */
- public static final int VISTEON = 0x00A7;
-
- /*
- * ARP Devices Limited.
- */
- public static final int ARP_DEVICES = 0x00A8;
-
- /*
- * Magneti Marelli S.p.A.
- */
- public static final int MAGNETI_MARELLI = 0x00A9;
-
- /*
- * CAEN RFID srl.
- */
- public static final int CAEN_RFID = 0x00AA;
-
- /*
- * Ingenieur-Systemgruppe Zahn GmbH.
- */
- public static final int INGENIEUR_SYSTEMGRUPPE_ZAHN = 0x00AB;
-
- /*
- * Green Throttle Games.
- */
- public static final int GREEN_THROTTLE_GAMES = 0x00AC;
-
- /*
- * Peter Systemtechnik GmbH.
- */
- public static final int PETER_SYSTEMTECHNIK = 0x00AD;
-
- /*
- * Omegawave Oy.
- */
- public static final int OMEGAWAVE = 0x00AE;
-
- /*
- * Cinetix.
- */
- public static final int CINETIX = 0x00AF;
-
- /*
- * Passif Semiconductor Corp.
- */
- public static final int PASSIF_SEMICONDUCTOR = 0x00B0;
-
- /*
- * Saris Cycling Group, Inc.
- */
- public static final int SARIS_CYCLING_GROUP = 0x00B1;
-
- /*
- * Bekey A/S.
- */
- public static final int BEKEY = 0x00B2;
-
- /*
- * Clarinox Technologies Pty. Ltd.
- */
- public static final int CLARINOX_TECHNOLOGIES = 0x00B3;
-
- /*
- * BDE Technology Co., Ltd.
- */
- public static final int BDE_TECHNOLOGY = 0x00B4;
-
- /*
- * Swirl Networks.
- */
- public static final int SWIRL_NETWORKS = 0x00B5;
-
- /*
- * Meso international.
- */
- public static final int MESO_INTERNATIONAL = 0x00B6;
-
- /*
- * TreLab Ltd.
- */
- public static final int TRELAB = 0x00B7;
-
- /*
- * Qualcomm Innovation Center, Inc. (QuIC).
- */
- public static final int QUALCOMM_INNOVATION_CENTER = 0x00B8;
-
- /*
- * Johnson Controls, Inc.
- */
- public static final int JOHNSON_CONTROLS = 0x00B9;
-
- /*
- * Starkey Laboratories Inc.
- */
- public static final int STARKEY_LABORATORIES = 0x00BA;
-
- /*
- * S-Power Electronics Limited.
- */
- public static final int S_POWER_ELECTRONICS = 0x00BB;
-
- /*
- * Ace Sensor Inc.
- */
- public static final int ACE_SENSOR = 0x00BC;
-
- /*
- * Aplix Corporation.
- */
- public static final int APLIX = 0x00BD;
-
- /*
- * AAMP of America.
- */
- public static final int AAMP_OF_AMERICA = 0x00BE;
-
- /*
- * Stalmart Technology Limited.
- */
- public static final int STALMART_TECHNOLOGY = 0x00BF;
-
- /*
- * AMICCOM Electronics Corporation.
- */
- public static final int AMICCOM_ELECTRONICS = 0x00C0;
-
- /*
- * Shenzhen Excelsecu Data Technology Co.,Ltd.
- */
- public static final int SHENZHEN_EXCELSECU_DATA_TECHNOLOGY = 0x00C1;
-
- /*
- * Geneq Inc.
- */
- public static final int GENEQ = 0x00C2;
-
- /*
- * adidas AG.
- */
- public static final int ADIDAS = 0x00C3;
-
- /*
- * LG Electronics.
- */
- public static final int LG_ELECTRONICS = 0x00C4;
-
- /*
- * Onset Computer Corporation.
- */
- public static final int ONSET_COMPUTER = 0x00C5;
-
- /*
- * Selfly BV.
- */
- public static final int SELFLY = 0x00C6;
-
- /*
- * Quuppa Oy.
- */
- public static final int QUUPPA = 0x00C7;
-
- /*
- * GeLo Inc.
- */
- public static final int GELO = 0x00C8;
-
- /*
- * Evluma.
- */
- public static final int EVLUMA = 0x00C9;
-
- /*
- * MC10.
- */
- public static final int MC10 = 0x00CA;
-
- /*
- * Binauric SE.
- */
- public static final int BINAURIC = 0x00CB;
-
- /*
- * Beats Electronics.
- */
- public static final int BEATS_ELECTRONICS = 0x00CC;
-
- /*
- * Microchip Technology Inc.
- */
- public static final int MICROCHIP_TECHNOLOGY = 0x00CD;
-
- /*
- * Elgato Systems GmbH.
- */
- public static final int ELGATO_SYSTEMS = 0x00CE;
-
- /*
- * ARCHOS SA.
- */
- public static final int ARCHOS = 0x00CF;
-
- /*
- * Dexcom, Inc.
- */
- public static final int DEXCOM = 0x00D0;
-
- /*
- * Polar Electro Europe B.V.
- */
- public static final int POLAR_ELECTRO_EUROPE = 0x00D1;
-
- /*
- * Dialog Semiconductor B.V.
- */
- public static final int DIALOG_SEMICONDUCTOR = 0x00D2;
-
- /*
- * Taixingbang Technology (HK) Co,. LTD.
- */
- public static final int TAIXINGBANG_TECHNOLOGY = 0x00D3;
-
- /*
- * Kawantech.
- */
- public static final int KAWANTECH = 0x00D4;
-
- /*
- * Austco Communication Systems.
- */
- public static final int AUSTCO_COMMUNICATION_SYSTEMS = 0x00D5;
-
- /*
- * Timex Group USA, Inc.
- */
- public static final int TIMEX_GROUP_USA = 0x00D6;
-
- /*
- * Qualcomm Technologies, Inc.
- */
- public static final int QUALCOMM_TECHNOLOGIES = 0x00D7;
-
- /*
- * Qualcomm Connected Experiences, Inc.
- */
- public static final int QUALCOMM_CONNECTED_EXPERIENCES = 0x00D8;
-
- /*
- * Voyetra Turtle Beach.
- */
- public static final int VOYETRA_TURTLE_BEACH = 0x00D9;
-
- /*
- * txtr GmbH.
- */
- public static final int TXTR = 0x00DA;
-
- /*
- * Biosentronics.
- */
- public static final int BIOSENTRONICS = 0x00DB;
-
- /*
- * Procter & Gamble.
- */
- public static final int PROCTER_AND_GAMBLE = 0x00DC;
-
- /*
- * Hosiden Corporation.
- */
- public static final int HOSIDEN = 0x00DD;
-
- /*
- * Muzik LLC.
- */
- public static final int MUZIK = 0x00DE;
-
- /*
- * Misfit Wearables Corp.
- */
- public static final int MISFIT_WEARABLES = 0x00DF;
-
- /*
- * Google.
- */
- public static final int GOOGLE = 0x00E0;
-
- /*
- * Danlers Ltd.
- */
- public static final int DANLERS = 0x00E1;
-
- /*
- * Semilink Inc.
- */
- public static final int SEMILINK = 0x00E2;
-
- /*
- * You can't instantiate one of these.
- */
- private BluetoothAssignedNumbers() {
- }
-
-}
diff --git a/core/java/android/bluetooth/BluetoothAudioConfig.java b/core/java/android/bluetooth/BluetoothAudioConfig.java
deleted file mode 100644
index 4c8b8c1..0000000
--- a/core/java/android/bluetooth/BluetoothAudioConfig.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2009 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.bluetooth;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents the audio configuration for a Bluetooth A2DP source device.
- *
- * {@see BluetoothA2dpSink}
- *
- * {@hide}
- */
-public final class BluetoothAudioConfig implements Parcelable {
-
- private final int mSampleRate;
- private final int mChannelConfig;
- private final int mAudioFormat;
-
- public BluetoothAudioConfig(int sampleRate, int channelConfig, int audioFormat) {
- mSampleRate = sampleRate;
- mChannelConfig = channelConfig;
- mAudioFormat = audioFormat;
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (o instanceof BluetoothAudioConfig) {
- BluetoothAudioConfig bac = (BluetoothAudioConfig) o;
- return (bac.mSampleRate == mSampleRate && bac.mChannelConfig == mChannelConfig
- && bac.mAudioFormat == mAudioFormat);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return mSampleRate | (mChannelConfig << 24) | (mAudioFormat << 28);
- }
-
- @Override
- public String toString() {
- return "{mSampleRate:" + mSampleRate + ",mChannelConfig:" + mChannelConfig
- + ",mAudioFormat:" + mAudioFormat + "}";
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothAudioConfig> CREATOR =
- new Parcelable.Creator<BluetoothAudioConfig>() {
- public BluetoothAudioConfig createFromParcel(Parcel in) {
- int sampleRate = in.readInt();
- int channelConfig = in.readInt();
- int audioFormat = in.readInt();
- return new BluetoothAudioConfig(sampleRate, channelConfig, audioFormat);
- }
-
- public BluetoothAudioConfig[] newArray(int size) {
- return new BluetoothAudioConfig[size];
- }
- };
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mSampleRate);
- out.writeInt(mChannelConfig);
- out.writeInt(mAudioFormat);
- }
-
- /**
- * Returns the sample rate in samples per second
- *
- * @return sample rate
- */
- public int getSampleRate() {
- return mSampleRate;
- }
-
- /**
- * Returns the channel configuration (either {@link android.media.AudioFormat#CHANNEL_IN_MONO}
- * or {@link android.media.AudioFormat#CHANNEL_IN_STEREO})
- *
- * @return channel configuration
- */
- public int getChannelConfig() {
- return mChannelConfig;
- }
-
- /**
- * Returns the channel audio format (either {@link android.media.AudioFormat#ENCODING_PCM_16BIT}
- * or {@link android.media.AudioFormat#ENCODING_PCM_8BIT}
- *
- * @return audio format
- */
- public int getAudioFormat() {
- return mAudioFormat;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothAvrcp.java b/core/java/android/bluetooth/BluetoothAvrcp.java
deleted file mode 100644
index 1a4c759..0000000
--- a/core/java/android/bluetooth/BluetoothAvrcp.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * This class contains constants for Bluetooth AVRCP profile.
- *
- * {@hide}
- */
-public final class BluetoothAvrcp {
-
- /*
- * State flags for Passthrough commands
- */
- public static final int PASSTHROUGH_STATE_PRESS = 0;
- public static final int PASSTHROUGH_STATE_RELEASE = 1;
-
- /*
- * Operation IDs for Passthrough commands
- */
- public static final int PASSTHROUGH_ID_SELECT = 0x00; /* select */
- public static final int PASSTHROUGH_ID_UP = 0x01; /* up */
- public static final int PASSTHROUGH_ID_DOWN = 0x02; /* down */
- public static final int PASSTHROUGH_ID_LEFT = 0x03; /* left */
- public static final int PASSTHROUGH_ID_RIGHT = 0x04; /* right */
- public static final int PASSTHROUGH_ID_RIGHT_UP = 0x05; /* right-up */
- public static final int PASSTHROUGH_ID_RIGHT_DOWN = 0x06; /* right-down */
- public static final int PASSTHROUGH_ID_LEFT_UP = 0x07; /* left-up */
- public static final int PASSTHROUGH_ID_LEFT_DOWN = 0x08; /* left-down */
- public static final int PASSTHROUGH_ID_ROOT_MENU = 0x09; /* root menu */
- public static final int PASSTHROUGH_ID_SETUP_MENU = 0x0A; /* setup menu */
- public static final int PASSTHROUGH_ID_CONT_MENU = 0x0B; /* contents menu */
- public static final int PASSTHROUGH_ID_FAV_MENU = 0x0C; /* favorite menu */
- public static final int PASSTHROUGH_ID_EXIT = 0x0D; /* exit */
- public static final int PASSTHROUGH_ID_0 = 0x20; /* 0 */
- public static final int PASSTHROUGH_ID_1 = 0x21; /* 1 */
- public static final int PASSTHROUGH_ID_2 = 0x22; /* 2 */
- public static final int PASSTHROUGH_ID_3 = 0x23; /* 3 */
- public static final int PASSTHROUGH_ID_4 = 0x24; /* 4 */
- public static final int PASSTHROUGH_ID_5 = 0x25; /* 5 */
- public static final int PASSTHROUGH_ID_6 = 0x26; /* 6 */
- public static final int PASSTHROUGH_ID_7 = 0x27; /* 7 */
- public static final int PASSTHROUGH_ID_8 = 0x28; /* 8 */
- public static final int PASSTHROUGH_ID_9 = 0x29; /* 9 */
- public static final int PASSTHROUGH_ID_DOT = 0x2A; /* dot */
- public static final int PASSTHROUGH_ID_ENTER = 0x2B; /* enter */
- public static final int PASSTHROUGH_ID_CLEAR = 0x2C; /* clear */
- public static final int PASSTHROUGH_ID_CHAN_UP = 0x30; /* channel up */
- public static final int PASSTHROUGH_ID_CHAN_DOWN = 0x31; /* channel down */
- public static final int PASSTHROUGH_ID_PREV_CHAN = 0x32; /* previous channel */
- public static final int PASSTHROUGH_ID_SOUND_SEL = 0x33; /* sound select */
- public static final int PASSTHROUGH_ID_INPUT_SEL = 0x34; /* input select */
- public static final int PASSTHROUGH_ID_DISP_INFO = 0x35; /* display information */
- public static final int PASSTHROUGH_ID_HELP = 0x36; /* help */
- public static final int PASSTHROUGH_ID_PAGE_UP = 0x37; /* page up */
- public static final int PASSTHROUGH_ID_PAGE_DOWN = 0x38; /* page down */
- public static final int PASSTHROUGH_ID_POWER = 0x40; /* power */
- public static final int PASSTHROUGH_ID_VOL_UP = 0x41; /* volume up */
- public static final int PASSTHROUGH_ID_VOL_DOWN = 0x42; /* volume down */
- public static final int PASSTHROUGH_ID_MUTE = 0x43; /* mute */
- public static final int PASSTHROUGH_ID_PLAY = 0x44; /* play */
- public static final int PASSTHROUGH_ID_STOP = 0x45; /* stop */
- public static final int PASSTHROUGH_ID_PAUSE = 0x46; /* pause */
- public static final int PASSTHROUGH_ID_RECORD = 0x47; /* record */
- public static final int PASSTHROUGH_ID_REWIND = 0x48; /* rewind */
- public static final int PASSTHROUGH_ID_FAST_FOR = 0x49; /* fast forward */
- public static final int PASSTHROUGH_ID_EJECT = 0x4A; /* eject */
- public static final int PASSTHROUGH_ID_FORWARD = 0x4B; /* forward */
- public static final int PASSTHROUGH_ID_BACKWARD = 0x4C; /* backward */
- public static final int PASSTHROUGH_ID_ANGLE = 0x50; /* angle */
- public static final int PASSTHROUGH_ID_SUBPICT = 0x51; /* subpicture */
- public static final int PASSTHROUGH_ID_F1 = 0x71; /* F1 */
- public static final int PASSTHROUGH_ID_F2 = 0x72; /* F2 */
- public static final int PASSTHROUGH_ID_F3 = 0x73; /* F3 */
- public static final int PASSTHROUGH_ID_F4 = 0x74; /* F4 */
- public static final int PASSTHROUGH_ID_F5 = 0x75; /* F5 */
- public static final int PASSTHROUGH_ID_VENDOR = 0x7E; /* vendor unique */
- public static final int PASSTHROUGH_KEYPRESSED_RELEASE = 0x80;
-}
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
deleted file mode 100644
index 81fc3e1..0000000
--- a/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the Bluetooth AVRCP Controller. It currently
- * supports player information, playback support and track metadata.
- *
- * <p>BluetoothAvrcpController is a proxy object for controlling the Bluetooth AVRCP
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothAvrcpController proxy object.
- *
- * {@hide}
- */
-public final class BluetoothAvrcpController implements BluetoothProfile {
- private static final String TAG = "BluetoothAvrcpController";
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
-
- /**
- * Intent used to broadcast the change in connection state of the AVRCP Controller
- * profile.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED";
-
- /**
- * Intent used to broadcast the change in player application setting state on AVRCP AG.
- *
- * <p>This intent will have the following extras:
- * <ul>
- * <li> {@link #EXTRA_PLAYER_SETTING} - {@link BluetoothAvrcpPlayerSettings} containing the
- * most recent player setting. </li>
- * </ul>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PLAYER_SETTING =
- "android.bluetooth.avrcp-controller.profile.action.PLAYER_SETTING";
-
- public static final String EXTRA_PLAYER_SETTING =
- "android.bluetooth.avrcp-controller.profile.extra.PLAYER_SETTING";
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothAvrcpController> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.AVRCP_CONTROLLER,
- "BluetoothAvrcpController", IBluetoothAvrcpController.class.getName()) {
- @Override
- public IBluetoothAvrcpController getServiceInterface(IBinder service) {
- return IBluetoothAvrcpController.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothAvrcpController proxy object for interacting with the local
- * Bluetooth AVRCP service.
- */
- /* package */ BluetoothAvrcpController(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- /*package*/ void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothAvrcpController getService() {
- return mProfileConnector.getService();
- }
-
- @Override
- public void finalize() {
- close();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
- if (VDBG) log("getConnectedDevices()");
- final IBluetoothAvrcpController service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothAvrcpController service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
- if (VDBG) log("getState(" + device + ")");
- final IBluetoothAvrcpController service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Gets the player application settings.
- *
- * @return the {@link BluetoothAvrcpPlayerSettings} or {@link null} if there is an error.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "getPlayerSettings");
- BluetoothAvrcpPlayerSettings settings = null;
- final IBluetoothAvrcpController service = getService();
- final BluetoothAvrcpPlayerSettings defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<BluetoothAvrcpPlayerSettings> recv =
- new SynchronousResultReceiver();
- service.getPlayerSettings(device, mAttributionSource, recv);
- settings = recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Sets the player app setting for current player.
- * returns true in case setting is supported by remote, false otherwise
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {
- if (DBG) Log.d(TAG, "setPlayerApplicationSetting");
- final IBluetoothAvrcpController service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setPlayerApplicationSetting(plAppSetting, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Send Group Navigation Command to Remote.
- * possible keycode values: next_grp, previous_grp defined above
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {
- Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "
- + keyState);
- final IBluetoothAvrcpController service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.sendGroupNavigationCmd(device, keyCode, keyState, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- return;
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- private boolean isEnabled() {
- return mAdapter.getState() == BluetoothAdapter.STATE_ON;
- }
-
- private static boolean isValidDevice(BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothAvrcpPlayerSettings.java b/core/java/android/bluetooth/BluetoothAvrcpPlayerSettings.java
deleted file mode 100644
index 30aea1a..0000000
--- a/core/java/android/bluetooth/BluetoothAvrcpPlayerSettings.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2015 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.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Class used to identify settings associated with the player on AG.
- *
- * {@hide}
- */
-public final class BluetoothAvrcpPlayerSettings implements Parcelable {
- public static final String TAG = "BluetoothAvrcpPlayerSettings";
-
- /**
- * Equalizer setting.
- */
- public static final int SETTING_EQUALIZER = 0x01;
-
- /**
- * Repeat setting.
- */
- public static final int SETTING_REPEAT = 0x02;
-
- /**
- * Shuffle setting.
- */
- public static final int SETTING_SHUFFLE = 0x04;
-
- /**
- * Scan mode setting.
- */
- public static final int SETTING_SCAN = 0x08;
-
- /**
- * Invalid state.
- *
- * Used for returning error codes.
- */
- public static final int STATE_INVALID = -1;
-
- /**
- * OFF state.
- *
- * Denotes a general OFF state. Applies to all settings.
- */
- public static final int STATE_OFF = 0x00;
-
- /**
- * ON state.
- *
- * Applies to {@link SETTING_EQUALIZER}.
- */
- public static final int STATE_ON = 0x01;
-
- /**
- * Single track repeat.
- *
- * Applies only to {@link SETTING_REPEAT}.
- */
- public static final int STATE_SINGLE_TRACK = 0x02;
-
- /**
- * All track repeat/shuffle.
- *
- * Applies to {@link #SETTING_REPEAT}, {@link #SETTING_SHUFFLE} and {@link #SETTING_SCAN}.
- */
- public static final int STATE_ALL_TRACK = 0x03;
-
- /**
- * Group repeat/shuffle.
- *
- * Applies to {@link #SETTING_REPEAT}, {@link #SETTING_SHUFFLE} and {@link #SETTING_SCAN}.
- */
- public static final int STATE_GROUP = 0x04;
-
- /**
- * List of supported settings ORed.
- */
- private int mSettings;
-
- /**
- * Hash map of current capability values.
- */
- private Map<Integer, Integer> mSettingsValue = new HashMap<Integer, Integer>();
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mSettings);
- out.writeInt(mSettingsValue.size());
- for (int k : mSettingsValue.keySet()) {
- out.writeInt(k);
- out.writeInt(mSettingsValue.get(k));
- }
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothAvrcpPlayerSettings> CREATOR =
- new Parcelable.Creator<BluetoothAvrcpPlayerSettings>() {
- public BluetoothAvrcpPlayerSettings createFromParcel(Parcel in) {
- return new BluetoothAvrcpPlayerSettings(in);
- }
-
- public BluetoothAvrcpPlayerSettings[] newArray(int size) {
- return new BluetoothAvrcpPlayerSettings[size];
- }
- };
-
- private BluetoothAvrcpPlayerSettings(Parcel in) {
- mSettings = in.readInt();
- int numSettings = in.readInt();
- for (int i = 0; i < numSettings; i++) {
- mSettingsValue.put(in.readInt(), in.readInt());
- }
- }
-
- /**
- * Create a new player settings object.
- *
- * @param settings a ORed value of SETTINGS_* defined above.
- */
- public BluetoothAvrcpPlayerSettings(int settings) {
- mSettings = settings;
- }
-
- /**
- * Get the supported settings.
- *
- * @return int ORed value of supported settings.
- */
- public int getSettings() {
- return mSettings;
- }
-
- /**
- * Add a setting value.
- *
- * The setting must be part of possible settings in {@link getSettings()}.
- *
- * @param setting setting config.
- * @param value value for the setting.
- * @throws IllegalStateException if the setting is not supported.
- */
- public void addSettingValue(int setting, int value) {
- if ((setting & mSettings) == 0) {
- Log.e(TAG, "Setting not supported: " + setting + " " + mSettings);
- throw new IllegalStateException("Setting not supported: " + setting);
- }
- mSettingsValue.put(setting, value);
- }
-
- /**
- * Get a setting value.
- *
- * The setting must be part of possible settings in {@link getSettings()}.
- *
- * @param setting setting config.
- * @return value value for the setting.
- * @throws IllegalStateException if the setting is not supported.
- */
- public int getSettingValue(int setting) {
- if ((setting & mSettings) == 0) {
- Log.e(TAG, "Setting not supported: " + setting + " " + mSettings);
- throw new IllegalStateException("Setting not supported: " + setting);
- }
- Integer i = mSettingsValue.get(setting);
- if (i == null) return -1;
- return i;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
deleted file mode 100755
index 8535b4f..0000000
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Copyright (C) 2008 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.bluetooth;
-
-import android.annotation.Nullable;
-import android.annotation.TestApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-
-/**
- * Represents a Bluetooth class, which describes general characteristics
- * and capabilities of a device. For example, a Bluetooth class will
- * specify the general device type such as a phone, a computer, or
- * headset, and whether it's capable of services such as audio or telephony.
- *
- * <p>Every Bluetooth class is composed of zero or more service classes, and
- * exactly one device class. The device class is further broken down into major
- * and minor device class components.
- *
- * <p>{@link BluetoothClass} is useful as a hint to roughly describe a device
- * (for example to show an icon in the UI), but does not reliably describe which
- * Bluetooth profiles or services are actually supported by a device. Accurate
- * service discovery is done through SDP requests, which are automatically
- * performed when creating an RFCOMM socket with {@link
- * BluetoothDevice#createRfcommSocketToServiceRecord} and {@link
- * BluetoothAdapter#listenUsingRfcommWithServiceRecord}</p>
- *
- * <p>Use {@link BluetoothDevice#getBluetoothClass} to retrieve the class for
- * a remote device.
- *
- * <!--
- * The Bluetooth class is a 32 bit field. The format of these bits is defined at
- * http://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
- * (login required). This class contains that 32 bit field, and provides
- * constants and methods to determine which Service Class(es) and Device Class
- * are encoded in that field.
- * -->
- */
-public final class BluetoothClass implements Parcelable {
- /**
- * Legacy error value. Applications should use null instead.
- *
- * @hide
- */
- public static final int ERROR = 0xFF000000;
-
- private final int mClass;
-
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
- public BluetoothClass(int classInt) {
- mClass = classInt;
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (o instanceof BluetoothClass) {
- return mClass == ((BluetoothClass) o).mClass;
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return mClass;
- }
-
- @Override
- public String toString() {
- return Integer.toHexString(mClass);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothClass> CREATOR =
- new Parcelable.Creator<BluetoothClass>() {
- public BluetoothClass createFromParcel(Parcel in) {
- return new BluetoothClass(in.readInt());
- }
-
- public BluetoothClass[] newArray(int size) {
- return new BluetoothClass[size];
- }
- };
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mClass);
- }
-
- /**
- * Defines all service class constants.
- * <p>Each {@link BluetoothClass} encodes zero or more service classes.
- */
- public static final class Service {
- private static final int BITMASK = 0xFFE000;
-
- public static final int LIMITED_DISCOVERABILITY = 0x002000;
- public static final int LE_AUDIO = 0x004000;
- public static final int POSITIONING = 0x010000;
- public static final int NETWORKING = 0x020000;
- public static final int RENDER = 0x040000;
- public static final int CAPTURE = 0x080000;
- public static final int OBJECT_TRANSFER = 0x100000;
- public static final int AUDIO = 0x200000;
- public static final int TELEPHONY = 0x400000;
- public static final int INFORMATION = 0x800000;
- }
-
- /**
- * Return true if the specified service class is supported by this
- * {@link BluetoothClass}.
- * <p>Valid service classes are the public constants in
- * {@link BluetoothClass.Service}. For example, {@link
- * BluetoothClass.Service#AUDIO}.
- *
- * @param service valid service class
- * @return true if the service class is supported
- */
- public boolean hasService(int service) {
- return ((mClass & Service.BITMASK & service) != 0);
- }
-
- /**
- * Defines all device class constants.
- * <p>Each {@link BluetoothClass} encodes exactly one device class, with
- * major and minor components.
- * <p>The constants in {@link
- * BluetoothClass.Device} represent a combination of major and minor
- * device components (the complete device class). The constants in {@link
- * BluetoothClass.Device.Major} represent only major device classes.
- * <p>See {@link BluetoothClass.Service} for service class constants.
- */
- public static class Device {
- private static final int BITMASK = 0x1FFC;
-
- /**
- * Defines all major device class constants.
- * <p>See {@link BluetoothClass.Device} for minor classes.
- */
- public static class Major {
- private static final int BITMASK = 0x1F00;
-
- public static final int MISC = 0x0000;
- public static final int COMPUTER = 0x0100;
- public static final int PHONE = 0x0200;
- public static final int NETWORKING = 0x0300;
- public static final int AUDIO_VIDEO = 0x0400;
- public static final int PERIPHERAL = 0x0500;
- public static final int IMAGING = 0x0600;
- public static final int WEARABLE = 0x0700;
- public static final int TOY = 0x0800;
- public static final int HEALTH = 0x0900;
- public static final int UNCATEGORIZED = 0x1F00;
- }
-
- // Devices in the COMPUTER major class
- public static final int COMPUTER_UNCATEGORIZED = 0x0100;
- public static final int COMPUTER_DESKTOP = 0x0104;
- public static final int COMPUTER_SERVER = 0x0108;
- public static final int COMPUTER_LAPTOP = 0x010C;
- public static final int COMPUTER_HANDHELD_PC_PDA = 0x0110;
- public static final int COMPUTER_PALM_SIZE_PC_PDA = 0x0114;
- public static final int COMPUTER_WEARABLE = 0x0118;
-
- // Devices in the PHONE major class
- public static final int PHONE_UNCATEGORIZED = 0x0200;
- public static final int PHONE_CELLULAR = 0x0204;
- public static final int PHONE_CORDLESS = 0x0208;
- public static final int PHONE_SMART = 0x020C;
- public static final int PHONE_MODEM_OR_GATEWAY = 0x0210;
- public static final int PHONE_ISDN = 0x0214;
-
- // Minor classes for the AUDIO_VIDEO major class
- public static final int AUDIO_VIDEO_UNCATEGORIZED = 0x0400;
- public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 0x0404;
- public static final int AUDIO_VIDEO_HANDSFREE = 0x0408;
- //public static final int AUDIO_VIDEO_RESERVED = 0x040C;
- public static final int AUDIO_VIDEO_MICROPHONE = 0x0410;
- public static final int AUDIO_VIDEO_LOUDSPEAKER = 0x0414;
- public static final int AUDIO_VIDEO_HEADPHONES = 0x0418;
- public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 0x041C;
- public static final int AUDIO_VIDEO_CAR_AUDIO = 0x0420;
- public static final int AUDIO_VIDEO_SET_TOP_BOX = 0x0424;
- public static final int AUDIO_VIDEO_HIFI_AUDIO = 0x0428;
- public static final int AUDIO_VIDEO_VCR = 0x042C;
- public static final int AUDIO_VIDEO_VIDEO_CAMERA = 0x0430;
- public static final int AUDIO_VIDEO_CAMCORDER = 0x0434;
- public static final int AUDIO_VIDEO_VIDEO_MONITOR = 0x0438;
- public static final int AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER = 0x043C;
- public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 0x0440;
- //public static final int AUDIO_VIDEO_RESERVED = 0x0444;
- public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 0x0448;
-
- // Devices in the WEARABLE major class
- public static final int WEARABLE_UNCATEGORIZED = 0x0700;
- public static final int WEARABLE_WRIST_WATCH = 0x0704;
- public static final int WEARABLE_PAGER = 0x0708;
- public static final int WEARABLE_JACKET = 0x070C;
- public static final int WEARABLE_HELMET = 0x0710;
- public static final int WEARABLE_GLASSES = 0x0714;
-
- // Devices in the TOY major class
- public static final int TOY_UNCATEGORIZED = 0x0800;
- public static final int TOY_ROBOT = 0x0804;
- public static final int TOY_VEHICLE = 0x0808;
- public static final int TOY_DOLL_ACTION_FIGURE = 0x080C;
- public static final int TOY_CONTROLLER = 0x0810;
- public static final int TOY_GAME = 0x0814;
-
- // Devices in the HEALTH major class
- public static final int HEALTH_UNCATEGORIZED = 0x0900;
- public static final int HEALTH_BLOOD_PRESSURE = 0x0904;
- public static final int HEALTH_THERMOMETER = 0x0908;
- public static final int HEALTH_WEIGHING = 0x090C;
- public static final int HEALTH_GLUCOSE = 0x0910;
- public static final int HEALTH_PULSE_OXIMETER = 0x0914;
- public static final int HEALTH_PULSE_RATE = 0x0918;
- public static final int HEALTH_DATA_DISPLAY = 0x091C;
-
- // Devices in PERIPHERAL major class
- /**
- * @hide
- */
- public static final int PERIPHERAL_NON_KEYBOARD_NON_POINTING = 0x0500;
- /**
- * @hide
- */
- public static final int PERIPHERAL_KEYBOARD = 0x0540;
- /**
- * @hide
- */
- public static final int PERIPHERAL_POINTING = 0x0580;
- /**
- * @hide
- */
- public static final int PERIPHERAL_KEYBOARD_POINTING = 0x05C0;
- }
-
- /**
- * Return the major device class component of this {@link BluetoothClass}.
- * <p>Values returned from this function can be compared with the
- * public constants in {@link BluetoothClass.Device.Major} to determine
- * which major class is encoded in this Bluetooth class.
- *
- * @return major device class component
- */
- public int getMajorDeviceClass() {
- return (mClass & Device.Major.BITMASK);
- }
-
- /**
- * Return the (major and minor) device class component of this
- * {@link BluetoothClass}.
- * <p>Values returned from this function can be compared with the
- * public constants in {@link BluetoothClass.Device} to determine which
- * device class is encoded in this Bluetooth class.
- *
- * @return device class component
- */
- public int getDeviceClass() {
- return (mClass & Device.BITMASK);
- }
-
- /**
- * Return the Bluetooth Class of Device (CoD) value including the
- * {@link BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and
- * minor device fields.
- *
- * <p>This value is an integer representation of Bluetooth CoD as in
- * Bluetooth specification.
- *
- * @see <a href="Bluetooth CoD">https://www.bluetooth.com/specifications/assigned-numbers/baseband</a>
- *
- * @hide
- */
- @TestApi
- public int getClassOfDevice() {
- return mClass;
- }
-
- /**
- * Return the Bluetooth Class of Device (CoD) value including the
- * {@link BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and
- * minor device fields.
- *
- * <p>This value is a byte array representation of Bluetooth CoD as in
- * Bluetooth specification.
- *
- * <p>Bluetooth COD information is 3 bytes, but stored as an int. Hence the
- * MSB is useless and needs to be thrown away. The lower 3 bytes are
- * converted into a byte array MSB to LSB. Hence, using BIG_ENDIAN.
- *
- * @see <a href="Bluetooth CoD">https://www.bluetooth.com/specifications/assigned-numbers/baseband</a>
- *
- * @hide
- */
- public byte[] getClassOfDeviceBytes() {
- byte[] bytes = ByteBuffer.allocate(4)
- .order(ByteOrder.BIG_ENDIAN)
- .putInt(mClass)
- .array();
-
- // Discard the top byte
- return Arrays.copyOfRange(bytes, 1, bytes.length);
- }
-
- /** @hide */
- @UnsupportedAppUsage
- public static final int PROFILE_HEADSET = 0;
- /** @hide */
- @UnsupportedAppUsage
- public static final int PROFILE_A2DP = 1;
- /** @hide */
- public static final int PROFILE_OPP = 2;
- /** @hide */
- public static final int PROFILE_HID = 3;
- /** @hide */
- public static final int PROFILE_PANU = 4;
- /** @hide */
- public static final int PROFILE_NAP = 5;
- /** @hide */
- public static final int PROFILE_A2DP_SINK = 6;
-
- /**
- * Check class bits for possible bluetooth profile support.
- * This is a simple heuristic that tries to guess if a device with the
- * given class bits might support specified profile. It is not accurate for all
- * devices. It tries to err on the side of false positives.
- *
- * @param profile The profile to be checked
- * @return True if this device might support specified profile.
- * @hide
- */
- @UnsupportedAppUsage
- public boolean doesClassMatch(int profile) {
- if (profile == PROFILE_A2DP) {
- if (hasService(Service.RENDER)) {
- return true;
- }
- // By the A2DP spec, sinks must indicate the RENDER service.
- // However we found some that do not (Chordette). So lets also
- // match on some other class bits.
- switch (getDeviceClass()) {
- case Device.AUDIO_VIDEO_HIFI_AUDIO:
- case Device.AUDIO_VIDEO_HEADPHONES:
- case Device.AUDIO_VIDEO_LOUDSPEAKER:
- case Device.AUDIO_VIDEO_CAR_AUDIO:
- return true;
- default:
- return false;
- }
- } else if (profile == PROFILE_A2DP_SINK) {
- if (hasService(Service.CAPTURE)) {
- return true;
- }
- // By the A2DP spec, srcs must indicate the CAPTURE service.
- // However if some device that do not, we try to
- // match on some other class bits.
- switch (getDeviceClass()) {
- case Device.AUDIO_VIDEO_HIFI_AUDIO:
- case Device.AUDIO_VIDEO_SET_TOP_BOX:
- case Device.AUDIO_VIDEO_VCR:
- return true;
- default:
- return false;
- }
- } else if (profile == PROFILE_HEADSET) {
- // The render service class is required by the spec for HFP, so is a
- // pretty good signal
- if (hasService(Service.RENDER)) {
- return true;
- }
- // Just in case they forgot the render service class
- switch (getDeviceClass()) {
- case Device.AUDIO_VIDEO_HANDSFREE:
- case Device.AUDIO_VIDEO_WEARABLE_HEADSET:
- case Device.AUDIO_VIDEO_CAR_AUDIO:
- return true;
- default:
- return false;
- }
- } else if (profile == PROFILE_OPP) {
- if (hasService(Service.OBJECT_TRANSFER)) {
- return true;
- }
-
- switch (getDeviceClass()) {
- case Device.COMPUTER_UNCATEGORIZED:
- case Device.COMPUTER_DESKTOP:
- case Device.COMPUTER_SERVER:
- case Device.COMPUTER_LAPTOP:
- case Device.COMPUTER_HANDHELD_PC_PDA:
- case Device.COMPUTER_PALM_SIZE_PC_PDA:
- case Device.COMPUTER_WEARABLE:
- case Device.PHONE_UNCATEGORIZED:
- case Device.PHONE_CELLULAR:
- case Device.PHONE_CORDLESS:
- case Device.PHONE_SMART:
- case Device.PHONE_MODEM_OR_GATEWAY:
- case Device.PHONE_ISDN:
- return true;
- default:
- return false;
- }
- } else if (profile == PROFILE_HID) {
- return getMajorDeviceClass() == Device.Major.PERIPHERAL;
- } else if (profile == PROFILE_PANU || profile == PROFILE_NAP) {
- // No good way to distinguish between the two, based on class bits.
- if (hasService(Service.NETWORKING)) {
- return true;
- }
- return getMajorDeviceClass() == Device.Major.NETWORKING;
- } else {
- return false;
- }
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
deleted file mode 100644
index 9a4151a..0000000
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ /dev/null
@@ -1,807 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Represents the codec configuration for a Bluetooth A2DP source device.
- * <p>Contains the source codec type, the codec priority, the codec sample
- * rate, the codec bits per sample, and the codec channel mode.
- * <p>The source codec type values are the same as those supported by the
- * device hardware.
- *
- * {@see BluetoothA2dp}
- */
-public final class BluetoothCodecConfig implements Parcelable {
- /** @hide */
- @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
- SOURCE_CODEC_TYPE_SBC,
- SOURCE_CODEC_TYPE_AAC,
- SOURCE_CODEC_TYPE_APTX,
- SOURCE_CODEC_TYPE_APTX_HD,
- SOURCE_CODEC_TYPE_LDAC,
- SOURCE_CODEC_TYPE_INVALID
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface SourceCodecType {}
-
- /**
- * Source codec type SBC. This is the mandatory source codec
- * type.
- */
- public static final int SOURCE_CODEC_TYPE_SBC = 0;
-
- /**
- * Source codec type AAC.
- */
- public static final int SOURCE_CODEC_TYPE_AAC = 1;
-
- /**
- * Source codec type APTX.
- */
- public static final int SOURCE_CODEC_TYPE_APTX = 2;
-
- /**
- * Source codec type APTX HD.
- */
- public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
-
- /**
- * Source codec type LDAC.
- */
- public static final int SOURCE_CODEC_TYPE_LDAC = 4;
-
- /**
- * Source codec type invalid. This is the default value used for codec
- * type.
- */
- public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
-
- /**
- * Represents the count of valid source codec types. Can be accessed via
- * {@link #getMaxCodecType}.
- */
- private static final int SOURCE_CODEC_TYPE_MAX = 5;
-
- /** @hide */
- @IntDef(prefix = "CODEC_PRIORITY_", value = {
- CODEC_PRIORITY_DISABLED,
- CODEC_PRIORITY_DEFAULT,
- CODEC_PRIORITY_HIGHEST
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface CodecPriority {}
-
- /**
- * Codec priority disabled.
- * Used to indicate that this codec is disabled and should not be used.
- */
- public static final int CODEC_PRIORITY_DISABLED = -1;
-
- /**
- * Codec priority default.
- * Default value used for codec priority.
- */
- public static final int CODEC_PRIORITY_DEFAULT = 0;
-
- /**
- * Codec priority highest.
- * Used to indicate the highest priority a codec can have.
- */
- public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
-
- /** @hide */
- @IntDef(prefix = "SAMPLE_RATE_", value = {
- SAMPLE_RATE_NONE,
- SAMPLE_RATE_44100,
- SAMPLE_RATE_48000,
- SAMPLE_RATE_88200,
- SAMPLE_RATE_96000,
- SAMPLE_RATE_176400,
- SAMPLE_RATE_192000
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface SampleRate {}
-
- /**
- * Codec sample rate 0 Hz. Default value used for
- * codec sample rate.
- */
- public static final int SAMPLE_RATE_NONE = 0;
-
- /**
- * Codec sample rate 44100 Hz.
- */
- public static final int SAMPLE_RATE_44100 = 0x1 << 0;
-
- /**
- * Codec sample rate 48000 Hz.
- */
- public static final int SAMPLE_RATE_48000 = 0x1 << 1;
-
- /**
- * Codec sample rate 88200 Hz.
- */
- public static final int SAMPLE_RATE_88200 = 0x1 << 2;
-
- /**
- * Codec sample rate 96000 Hz.
- */
- public static final int SAMPLE_RATE_96000 = 0x1 << 3;
-
- /**
- * Codec sample rate 176400 Hz.
- */
- public static final int SAMPLE_RATE_176400 = 0x1 << 4;
-
- /**
- * Codec sample rate 192000 Hz.
- */
- public static final int SAMPLE_RATE_192000 = 0x1 << 5;
-
- /** @hide */
- @IntDef(prefix = "BITS_PER_SAMPLE_", value = {
- BITS_PER_SAMPLE_NONE,
- BITS_PER_SAMPLE_16,
- BITS_PER_SAMPLE_24,
- BITS_PER_SAMPLE_32
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface BitsPerSample {}
-
- /**
- * Codec bits per sample 0. Default value of the codec
- * bits per sample.
- */
- public static final int BITS_PER_SAMPLE_NONE = 0;
-
- /**
- * Codec bits per sample 16.
- */
- public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
-
- /**
- * Codec bits per sample 24.
- */
- public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
-
- /**
- * Codec bits per sample 32.
- */
- public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
-
- /** @hide */
- @IntDef(prefix = "CHANNEL_MODE_", value = {
- CHANNEL_MODE_NONE,
- CHANNEL_MODE_MONO,
- CHANNEL_MODE_STEREO
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ChannelMode {}
-
- /**
- * Codec channel mode NONE. Default value of the
- * codec channel mode.
- */
- public static final int CHANNEL_MODE_NONE = 0;
-
- /**
- * Codec channel mode MONO.
- */
- public static final int CHANNEL_MODE_MONO = 0x1 << 0;
-
- /**
- * Codec channel mode STEREO.
- */
- public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
-
- private final @SourceCodecType int mCodecType;
- private @CodecPriority int mCodecPriority;
- private final @SampleRate int mSampleRate;
- private final @BitsPerSample int mBitsPerSample;
- private final @ChannelMode int mChannelMode;
- private final long mCodecSpecific1;
- private final long mCodecSpecific2;
- private final long mCodecSpecific3;
- private final long mCodecSpecific4;
-
- /**
- * Creates a new BluetoothCodecConfig.
- *
- * @param codecType the source codec type
- * @param codecPriority the priority of this codec
- * @param sampleRate the codec sample rate
- * @param bitsPerSample the bits per sample of this codec
- * @param channelMode the channel mode of this codec
- * @param codecSpecific1 the specific value 1
- * @param codecSpecific2 the specific value 2
- * @param codecSpecific3 the specific value 3
- * @param codecSpecific4 the specific value 4
- * values to 0.
- * @hide
- */
- @UnsupportedAppUsage
- public BluetoothCodecConfig(@SourceCodecType int codecType, @CodecPriority int codecPriority,
- @SampleRate int sampleRate, @BitsPerSample int bitsPerSample,
- @ChannelMode int channelMode, long codecSpecific1,
- long codecSpecific2, long codecSpecific3,
- long codecSpecific4) {
- mCodecType = codecType;
- mCodecPriority = codecPriority;
- mSampleRate = sampleRate;
- mBitsPerSample = bitsPerSample;
- mChannelMode = channelMode;
- mCodecSpecific1 = codecSpecific1;
- mCodecSpecific2 = codecSpecific2;
- mCodecSpecific3 = codecSpecific3;
- mCodecSpecific4 = codecSpecific4;
- }
-
- /**
- * Creates a new BluetoothCodecConfig.
- * <p> By default, the codec priority will be set
- * to {@link BluetoothCodecConfig#CODEC_PRIORITY_DEFAULT}, the sample rate to
- * {@link BluetoothCodecConfig#SAMPLE_RATE_NONE}, the bits per sample to
- * {@link BluetoothCodecConfig#BITS_PER_SAMPLE_NONE}, the channel mode to
- * {@link BluetoothCodecConfig#CHANNEL_MODE_NONE}, and all the codec specific
- * values to 0.
- *
- * @param codecType the source codec type
- */
- public BluetoothCodecConfig(@SourceCodecType int codecType) {
- this(codecType, BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_NONE,
- BluetoothCodecConfig.BITS_PER_SAMPLE_NONE,
- BluetoothCodecConfig.CHANNEL_MODE_NONE, 0, 0, 0, 0);
- }
-
- private BluetoothCodecConfig(Parcel in) {
- mCodecType = in.readInt();
- mCodecPriority = in.readInt();
- mSampleRate = in.readInt();
- mBitsPerSample = in.readInt();
- mChannelMode = in.readInt();
- mCodecSpecific1 = in.readLong();
- mCodecSpecific2 = in.readLong();
- mCodecSpecific3 = in.readLong();
- mCodecSpecific4 = in.readLong();
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (o instanceof BluetoothCodecConfig) {
- BluetoothCodecConfig other = (BluetoothCodecConfig) o;
- return (other.mCodecType == mCodecType
- && other.mCodecPriority == mCodecPriority
- && other.mSampleRate == mSampleRate
- && other.mBitsPerSample == mBitsPerSample
- && other.mChannelMode == mChannelMode
- && other.mCodecSpecific1 == mCodecSpecific1
- && other.mCodecSpecific2 == mCodecSpecific2
- && other.mCodecSpecific3 == mCodecSpecific3
- && other.mCodecSpecific4 == mCodecSpecific4);
- }
- return false;
- }
-
- /**
- * Returns a hash representation of this BluetoothCodecConfig
- * based on all the config values.
- */
- @Override
- public int hashCode() {
- return Objects.hash(mCodecType, mCodecPriority, mSampleRate,
- mBitsPerSample, mChannelMode, mCodecSpecific1,
- mCodecSpecific2, mCodecSpecific3, mCodecSpecific4);
- }
-
- /**
- * Adds capability string to an existing string.
- *
- * @param prevStr the previous string with the capabilities. Can be a {@code null} pointer
- * @param capStr the capability string to append to prevStr argument
- * @return the result string in the form "prevStr|capStr"
- */
- private static String appendCapabilityToString(@Nullable String prevStr,
- @NonNull String capStr) {
- if (prevStr == null) {
- return capStr;
- }
- return prevStr + "|" + capStr;
- }
-
- /**
- * Returns a {@link String} that describes each BluetoothCodecConfig parameter
- * current value.
- */
- @Override
- public String toString() {
- String sampleRateStr = null;
- if (mSampleRate == SAMPLE_RATE_NONE) {
- sampleRateStr = appendCapabilityToString(sampleRateStr, "NONE");
- }
- if ((mSampleRate & SAMPLE_RATE_44100) != 0) {
- sampleRateStr = appendCapabilityToString(sampleRateStr, "44100");
- }
- if ((mSampleRate & SAMPLE_RATE_48000) != 0) {
- sampleRateStr = appendCapabilityToString(sampleRateStr, "48000");
- }
- if ((mSampleRate & SAMPLE_RATE_88200) != 0) {
- sampleRateStr = appendCapabilityToString(sampleRateStr, "88200");
- }
- if ((mSampleRate & SAMPLE_RATE_96000) != 0) {
- sampleRateStr = appendCapabilityToString(sampleRateStr, "96000");
- }
- if ((mSampleRate & SAMPLE_RATE_176400) != 0) {
- sampleRateStr = appendCapabilityToString(sampleRateStr, "176400");
- }
- if ((mSampleRate & SAMPLE_RATE_192000) != 0) {
- sampleRateStr = appendCapabilityToString(sampleRateStr, "192000");
- }
-
- String bitsPerSampleStr = null;
- if (mBitsPerSample == BITS_PER_SAMPLE_NONE) {
- bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "NONE");
- }
- if ((mBitsPerSample & BITS_PER_SAMPLE_16) != 0) {
- bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "16");
- }
- if ((mBitsPerSample & BITS_PER_SAMPLE_24) != 0) {
- bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "24");
- }
- if ((mBitsPerSample & BITS_PER_SAMPLE_32) != 0) {
- bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "32");
- }
-
- String channelModeStr = null;
- if (mChannelMode == CHANNEL_MODE_NONE) {
- channelModeStr = appendCapabilityToString(channelModeStr, "NONE");
- }
- if ((mChannelMode & CHANNEL_MODE_MONO) != 0) {
- channelModeStr = appendCapabilityToString(channelModeStr, "MONO");
- }
- if ((mChannelMode & CHANNEL_MODE_STEREO) != 0) {
- channelModeStr = appendCapabilityToString(channelModeStr, "STEREO");
- }
-
- return "{codecName:" + getCodecName()
- + ",mCodecType:" + mCodecType
- + ",mCodecPriority:" + mCodecPriority
- + ",mSampleRate:" + String.format("0x%x", mSampleRate)
- + "(" + sampleRateStr + ")"
- + ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample)
- + "(" + bitsPerSampleStr + ")"
- + ",mChannelMode:" + String.format("0x%x", mChannelMode)
- + "(" + channelModeStr + ")"
- + ",mCodecSpecific1:" + mCodecSpecific1
- + ",mCodecSpecific2:" + mCodecSpecific2
- + ",mCodecSpecific3:" + mCodecSpecific3
- + ",mCodecSpecific4:" + mCodecSpecific4 + "}";
- }
-
- /**
- * @return 0
- * @hide
- */
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothCodecConfig> CREATOR =
- new Parcelable.Creator<BluetoothCodecConfig>() {
- public BluetoothCodecConfig createFromParcel(Parcel in) {
- return new BluetoothCodecConfig(in);
- }
-
- public BluetoothCodecConfig[] newArray(int size) {
- return new BluetoothCodecConfig[size];
- }
- };
-
- /**
- * Flattens the object to a parcel
- *
- * @param out The Parcel in which the object should be written
- * @param flags Additional flags about how the object should be written
- *
- * @hide
- */
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mCodecType);
- out.writeInt(mCodecPriority);
- out.writeInt(mSampleRate);
- out.writeInt(mBitsPerSample);
- out.writeInt(mChannelMode);
- out.writeLong(mCodecSpecific1);
- out.writeLong(mCodecSpecific2);
- out.writeLong(mCodecSpecific3);
- out.writeLong(mCodecSpecific4);
- }
-
- /**
- * Returns the codec name converted to {@link String}.
- * @hide
- */
- public @NonNull String getCodecName() {
- switch (mCodecType) {
- case SOURCE_CODEC_TYPE_SBC:
- return "SBC";
- case SOURCE_CODEC_TYPE_AAC:
- return "AAC";
- case SOURCE_CODEC_TYPE_APTX:
- return "aptX";
- case SOURCE_CODEC_TYPE_APTX_HD:
- return "aptX HD";
- case SOURCE_CODEC_TYPE_LDAC:
- return "LDAC";
- case SOURCE_CODEC_TYPE_INVALID:
- return "INVALID CODEC";
- default:
- break;
- }
- return "UNKNOWN CODEC(" + mCodecType + ")";
- }
-
- /**
- * Returns the source codec type of this config.
- */
- public @SourceCodecType int getCodecType() {
- return mCodecType;
- }
-
- /**
- * Returns the valid codec types count.
- */
- public static int getMaxCodecType() {
- return SOURCE_CODEC_TYPE_MAX;
- }
-
- /**
- * Checks whether the codec is mandatory.
- * <p> The actual mandatory codec type for Android Bluetooth audio is SBC.
- * See {@link #SOURCE_CODEC_TYPE_SBC}.
- *
- * @return {@code true} if the codec is mandatory, {@code false} otherwise
- * @hide
- */
- public boolean isMandatoryCodec() {
- return mCodecType == SOURCE_CODEC_TYPE_SBC;
- }
-
- /**
- * Returns the codec selection priority.
- * <p>The codec selection priority is relative to other codecs: larger value
- * means higher priority.
- */
- public @CodecPriority int getCodecPriority() {
- return mCodecPriority;
- }
-
- /**
- * Sets the codec selection priority.
- * <p>The codec selection priority is relative to other codecs: larger value
- * means higher priority.
- *
- * @param codecPriority the priority this codec should have
- * @hide
- */
- public void setCodecPriority(@CodecPriority int codecPriority) {
- mCodecPriority = codecPriority;
- }
-
- /**
- * Returns the codec sample rate. The value can be a bitmask with all
- * supported sample rates.
- */
- public @SampleRate int getSampleRate() {
- return mSampleRate;
- }
-
- /**
- * Returns the codec bits per sample. The value can be a bitmask with all
- * bits per sample supported.
- */
- public @BitsPerSample int getBitsPerSample() {
- return mBitsPerSample;
- }
-
- /**
- * Returns the codec channel mode. The value can be a bitmask with all
- * supported channel modes.
- */
- public @ChannelMode int getChannelMode() {
- return mChannelMode;
- }
-
- /**
- * Returns the codec specific value1.
- */
- public long getCodecSpecific1() {
- return mCodecSpecific1;
- }
-
- /**
- * Returns the codec specific value2.
- */
- public long getCodecSpecific2() {
- return mCodecSpecific2;
- }
-
- /**
- * Returns the codec specific value3.
- */
- public long getCodecSpecific3() {
- return mCodecSpecific3;
- }
-
- /**
- * Returns the codec specific value4.
- */
- public long getCodecSpecific4() {
- return mCodecSpecific4;
- }
-
- /**
- * Checks whether a value set presented by a bitmask has zero or single bit
- *
- * @param valueSet the value set presented by a bitmask
- * @return {@code true} if the valueSet contains zero or single bit, {@code false} otherwise
- * @hide
- */
- private static boolean hasSingleBit(int valueSet) {
- return (valueSet == 0 || (valueSet & (valueSet - 1)) == 0);
- }
-
- /**
- * Returns whether the object contains none or single sample rate.
- * @hide
- */
- public boolean hasSingleSampleRate() {
- return hasSingleBit(mSampleRate);
- }
-
- /**
- * Returns whether the object contains none or single bits per sample.
- * @hide
- */
- public boolean hasSingleBitsPerSample() {
- return hasSingleBit(mBitsPerSample);
- }
-
- /**
- * Returns whether the object contains none or single channel mode.
- * @hide
- */
- public boolean hasSingleChannelMode() {
- return hasSingleBit(mChannelMode);
- }
-
- /**
- * Checks whether the audio feeding parameters are the same.
- *
- * @param other the codec config to compare against
- * @return {@code true} if the audio feeding parameters are same, {@code false} otherwise
- * @hide
- */
- public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
- return (other != null && other.mSampleRate == mSampleRate
- && other.mBitsPerSample == mBitsPerSample
- && other.mChannelMode == mChannelMode);
- }
-
- /**
- * Checks whether another codec config has the similar feeding parameters.
- * Any parameters with NONE value will be considered to be a wildcard matching.
- *
- * @param other the codec config to compare against
- * @return {@code true} if the audio feeding parameters are similar, {@code false} otherwise
- * @hide
- */
- public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
- if (other == null || mCodecType != other.mCodecType) {
- return false;
- }
- int sampleRate = other.mSampleRate;
- if (mSampleRate == SAMPLE_RATE_NONE
- || sampleRate == SAMPLE_RATE_NONE) {
- sampleRate = mSampleRate;
- }
- int bitsPerSample = other.mBitsPerSample;
- if (mBitsPerSample == BITS_PER_SAMPLE_NONE
- || bitsPerSample == BITS_PER_SAMPLE_NONE) {
- bitsPerSample = mBitsPerSample;
- }
- int channelMode = other.mChannelMode;
- if (mChannelMode == CHANNEL_MODE_NONE
- || channelMode == CHANNEL_MODE_NONE) {
- channelMode = mChannelMode;
- }
- return sameAudioFeedingParameters(new BluetoothCodecConfig(
- mCodecType, /* priority */ 0, sampleRate, bitsPerSample, channelMode,
- /* specific1 */ 0, /* specific2 */ 0, /* specific3 */ 0,
- /* specific4 */ 0));
- }
-
- /**
- * Checks whether the codec specific parameters are the same.
- * <p> Currently, only AAC VBR and LDAC Playback Quality on CodecSpecific1
- * are compared.
- *
- * @param other the codec config to compare against
- * @return {@code true} if the codec specific parameters are the same, {@code false} otherwise
- * @hide
- */
- public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
- if (other == null && mCodecType != other.mCodecType) {
- return false;
- }
- switch (mCodecType) {
- case SOURCE_CODEC_TYPE_AAC:
- case SOURCE_CODEC_TYPE_LDAC:
- if (mCodecSpecific1 != other.mCodecSpecific1) {
- return false;
- }
- default:
- return true;
- }
- }
-
- /**
- * Builder for {@link BluetoothCodecConfig}.
- * <p> By default, the codec type will be set to
- * {@link BluetoothCodecConfig#SOURCE_CODEC_TYPE_INVALID}, the codec priority
- * to {@link BluetoothCodecConfig#CODEC_PRIORITY_DEFAULT}, the sample rate to
- * {@link BluetoothCodecConfig#SAMPLE_RATE_NONE}, the bits per sample to
- * {@link BluetoothCodecConfig#BITS_PER_SAMPLE_NONE}, the channel mode to
- * {@link BluetoothCodecConfig#CHANNEL_MODE_NONE}, and all the codec specific
- * values to 0.
- */
- public static final class Builder {
- private int mCodecType = BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID;
- private int mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
- private int mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
- private int mBitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE;
- private int mChannelMode = BluetoothCodecConfig.CHANNEL_MODE_NONE;
- private long mCodecSpecific1 = 0;
- private long mCodecSpecific2 = 0;
- private long mCodecSpecific3 = 0;
- private long mCodecSpecific4 = 0;
-
- /**
- * Set codec type for Bluetooth codec config.
- *
- * @param codecType of this codec
- * @return the same Builder instance
- */
- public @NonNull Builder setCodecType(@SourceCodecType int codecType) {
- mCodecType = codecType;
- return this;
- }
-
- /**
- * Set codec priority for Bluetooth codec config.
- *
- * @param codecPriority of this codec
- * @return the same Builder instance
- */
- public @NonNull Builder setCodecPriority(@CodecPriority int codecPriority) {
- mCodecPriority = codecPriority;
- return this;
- }
-
- /**
- * Set sample rate for Bluetooth codec config.
- *
- * @param sampleRate of this codec
- * @return the same Builder instance
- */
- public @NonNull Builder setSampleRate(@SampleRate int sampleRate) {
- mSampleRate = sampleRate;
- return this;
- }
-
- /**
- * Set the bits per sample for Bluetooth codec config.
- *
- * @param bitsPerSample of this codec
- * @return the same Builder instance
- */
- public @NonNull Builder setBitsPerSample(@BitsPerSample int bitsPerSample) {
- mBitsPerSample = bitsPerSample;
- return this;
- }
-
- /**
- * Set the channel mode for Bluetooth codec config.
- *
- * @param channelMode of this codec
- * @return the same Builder instance
- */
- public @NonNull Builder setChannelMode(@ChannelMode int channelMode) {
- mChannelMode = channelMode;
- return this;
- }
-
- /**
- * Set the first codec specific values for Bluetooth codec config.
- *
- * @param codecSpecific1 codec specific value or 0 if default
- * @return the same Builder instance
- */
- public @NonNull Builder setCodecSpecific1(long codecSpecific1) {
- mCodecSpecific1 = codecSpecific1;
- return this;
- }
-
- /**
- * Set the second codec specific values for Bluetooth codec config.
- *
- * @param codecSpecific2 codec specific value or 0 if default
- * @return the same Builder instance
- */
- public @NonNull Builder setCodecSpecific2(long codecSpecific2) {
- mCodecSpecific2 = codecSpecific2;
- return this;
- }
-
- /**
- * Set the third codec specific values for Bluetooth codec config.
- *
- * @param codecSpecific3 codec specific value or 0 if default
- * @return the same Builder instance
- */
- public @NonNull Builder setCodecSpecific3(long codecSpecific3) {
- mCodecSpecific3 = codecSpecific3;
- return this;
- }
-
- /**
- * Set the fourth codec specific values for Bluetooth codec config.
- *
- * @param codecSpecific4 codec specific value or 0 if default
- * @return the same Builder instance
- */
- public @NonNull Builder setCodecSpecific4(long codecSpecific4) {
- mCodecSpecific4 = codecSpecific4;
- return this;
- }
-
- /**
- * Build {@link BluetoothCodecConfig}.
- * @return new BluetoothCodecConfig built
- */
- public @NonNull BluetoothCodecConfig build() {
- return new BluetoothCodecConfig(mCodecType, mCodecPriority,
- mSampleRate, mBitsPerSample,
- mChannelMode, mCodecSpecific1,
- mCodecSpecific2, mCodecSpecific3,
- mCodecSpecific4);
- }
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
deleted file mode 100644
index 02606fe..0000000
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Represents the codec status (configuration and capability) for a Bluetooth
- * A2DP source device.
- *
- * {@see BluetoothA2dp}
- */
-public final class BluetoothCodecStatus implements Parcelable {
- /**
- * Extra for the codec configuration intents of the individual profiles.
- *
- * This extra represents the current codec status of the A2DP
- * profile.
- */
- public static final String EXTRA_CODEC_STATUS =
- "android.bluetooth.extra.CODEC_STATUS";
-
- private final @Nullable BluetoothCodecConfig mCodecConfig;
- private final @Nullable List<BluetoothCodecConfig> mCodecsLocalCapabilities;
- private final @Nullable List<BluetoothCodecConfig> mCodecsSelectableCapabilities;
-
- public BluetoothCodecStatus(@Nullable BluetoothCodecConfig codecConfig,
- @Nullable List<BluetoothCodecConfig> codecsLocalCapabilities,
- @Nullable List<BluetoothCodecConfig> codecsSelectableCapabilities) {
- mCodecConfig = codecConfig;
- mCodecsLocalCapabilities = codecsLocalCapabilities;
- mCodecsSelectableCapabilities = codecsSelectableCapabilities;
- }
-
- private BluetoothCodecStatus(Parcel in) {
- mCodecConfig = in.readTypedObject(BluetoothCodecConfig.CREATOR);
- mCodecsLocalCapabilities = in.createTypedArrayList(BluetoothCodecConfig.CREATOR);
- mCodecsSelectableCapabilities = in.createTypedArrayList(BluetoothCodecConfig.CREATOR);
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (o instanceof BluetoothCodecStatus) {
- BluetoothCodecStatus other = (BluetoothCodecStatus) o;
- return (Objects.equals(other.mCodecConfig, mCodecConfig)
- && sameCapabilities(other.mCodecsLocalCapabilities, mCodecsLocalCapabilities)
- && sameCapabilities(other.mCodecsSelectableCapabilities,
- mCodecsSelectableCapabilities));
- }
- return false;
- }
-
- /**
- * Checks whether two lists of capabilities contain same capabilities.
- * The order of the capabilities in each list is ignored.
- *
- * @param c1 the first list of capabilities to compare
- * @param c2 the second list of capabilities to compare
- * @return {@code true} if both lists contain same capabilities
- */
- private static boolean sameCapabilities(@Nullable List<BluetoothCodecConfig> c1,
- @Nullable List<BluetoothCodecConfig> c2) {
- if (c1 == null) {
- return (c2 == null);
- }
- if (c2 == null) {
- return false;
- }
- if (c1.size() != c2.size()) {
- return false;
- }
- return c1.containsAll(c2);
- }
-
- /**
- * Checks whether the codec config matches the selectable capabilities.
- * Any parameters of the codec config with NONE value will be considered a wildcard matching.
- *
- * @param codecConfig the codec config to compare against
- * @return {@code true} if the codec config matches, {@code false} otherwise
- */
- public boolean isCodecConfigSelectable(@Nullable BluetoothCodecConfig codecConfig) {
- if (codecConfig == null || !codecConfig.hasSingleSampleRate()
- || !codecConfig.hasSingleBitsPerSample() || !codecConfig.hasSingleChannelMode()) {
- return false;
- }
- for (BluetoothCodecConfig selectableConfig : mCodecsSelectableCapabilities) {
- if (codecConfig.getCodecType() != selectableConfig.getCodecType()) {
- continue;
- }
- int sampleRate = codecConfig.getSampleRate();
- if ((sampleRate & selectableConfig.getSampleRate()) == 0
- && sampleRate != BluetoothCodecConfig.SAMPLE_RATE_NONE) {
- continue;
- }
- int bitsPerSample = codecConfig.getBitsPerSample();
- if ((bitsPerSample & selectableConfig.getBitsPerSample()) == 0
- && bitsPerSample != BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
- continue;
- }
- int channelMode = codecConfig.getChannelMode();
- if ((channelMode & selectableConfig.getChannelMode()) == 0
- && channelMode != BluetoothCodecConfig.CHANNEL_MODE_NONE) {
- continue;
- }
- return true;
- }
- return false;
- }
-
- /**
- * Returns a hash based on the codec config and local capabilities.
- */
- @Override
- public int hashCode() {
- return Objects.hash(mCodecConfig, mCodecsLocalCapabilities,
- mCodecsLocalCapabilities);
- }
-
- /**
- * Returns a {@link String} that describes each BluetoothCodecStatus parameter
- * current value.
- */
- @Override
- public String toString() {
- return "{mCodecConfig:" + mCodecConfig
- + ",mCodecsLocalCapabilities:" + mCodecsLocalCapabilities
- + ",mCodecsSelectableCapabilities:" + mCodecsSelectableCapabilities
- + "}";
- }
-
- /**
- * @return 0
- * @hide
- */
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothCodecStatus> CREATOR =
- new Parcelable.Creator<BluetoothCodecStatus>() {
- public BluetoothCodecStatus createFromParcel(Parcel in) {
- return new BluetoothCodecStatus(in);
- }
-
- public BluetoothCodecStatus[] newArray(int size) {
- return new BluetoothCodecStatus[size];
- }
- };
-
- /**
- * Flattens the object to a parcel.
- *
- * @param out The Parcel in which the object should be written
- * @param flags Additional flags about how the object should be written
- */
- @Override
- public void writeToParcel(@NonNull Parcel out, int flags) {
- out.writeTypedObject(mCodecConfig, 0);
- out.writeTypedList(mCodecsLocalCapabilities);
- out.writeTypedList(mCodecsSelectableCapabilities);
- }
-
- /**
- * Returns the current codec configuration.
- */
- public @Nullable BluetoothCodecConfig getCodecConfig() {
- return mCodecConfig;
- }
-
- /**
- * Returns the codecs local capabilities.
- */
- public @NonNull List<BluetoothCodecConfig> getCodecsLocalCapabilities() {
- return (mCodecsLocalCapabilities == null)
- ? Collections.emptyList() : mCodecsLocalCapabilities;
- }
-
- /**
- * Returns the codecs selectable capabilities.
- */
- public @NonNull List<BluetoothCodecConfig> getCodecsSelectableCapabilities() {
- return (mCodecsSelectableCapabilities == null)
- ? Collections.emptyList() : mCodecsSelectableCapabilities;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java b/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java
deleted file mode 100644
index ba57ec4..0000000
--- a/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * Copyright 2021 HIMSA II K/S - www.himsa.com.
- * Represented by EHIMA - www.ehima.com
- *
- * 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.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.CallbackExecutor;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.Executor;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the Bluetooth CSIP set coordinator.
- *
- * <p>BluetoothCsipSetCoordinator is a proxy object for controlling the Bluetooth VC
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothCsipSetCoordinator proxy object.
- *
- */
-public final class BluetoothCsipSetCoordinator implements BluetoothProfile, AutoCloseable {
- private static final String TAG = "BluetoothCsipSetCoordinator";
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
-
- private CloseGuard mCloseGuard;
-
- /**
- * @hide
- */
- @SystemApi
- public interface ClientLockCallback {
- /**
- * @hide
- */
- @SystemApi void onGroupLockSet(int groupId, int opStatus, boolean isLocked);
- }
-
- private static class BluetoothCsipSetCoordinatorLockCallbackDelegate
- extends IBluetoothCsipSetCoordinatorLockCallback.Stub {
- private final ClientLockCallback mCallback;
- private final Executor mExecutor;
-
- BluetoothCsipSetCoordinatorLockCallbackDelegate(
- Executor executor, ClientLockCallback callback) {
- mExecutor = executor;
- mCallback = callback;
- }
-
- @Override
- public void onGroupLockSet(int groupId, int opStatus, boolean isLocked) {
- mExecutor.execute(() -> mCallback.onGroupLockSet(groupId, opStatus, isLocked));
- }
- };
-
- /**
- * Intent used to broadcast the change in connection state of the CSIS
- * Client.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CSIS_CONNECTION_STATE_CHANGED =
- "android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED";
-
- /**
- * Intent used to expose broadcast receiving device.
- *
- * <p>This intent will have 2 extras:
- * <ul>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote Broadcast receiver device. </li>
- * <li> {@link #EXTRA_CSIS_GROUP_ID} - Group identifier. </li>
- * <li> {@link #EXTRA_CSIS_GROUP_SIZE} - Group size. </li>
- * <li> {@link #EXTRA_CSIS_GROUP_TYPE_UUID} - Group type UUID. </li>
- * </ul>
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CSIS_DEVICE_AVAILABLE =
- "android.bluetooth.action.CSIS_DEVICE_AVAILABLE";
-
- /**
- * Used as an extra field in {@link #ACTION_CSIS_DEVICE_AVAILABLE} intent.
- * Contains the group id.
- *
- * @hide
- */
- public static final String EXTRA_CSIS_GROUP_ID = "android.bluetooth.extra.CSIS_GROUP_ID";
-
- /**
- * Group size as int extra field in {@link #ACTION_CSIS_DEVICE_AVAILABLE} intent.
- *
- * @hide
- */
- public static final String EXTRA_CSIS_GROUP_SIZE = "android.bluetooth.extra.CSIS_GROUP_SIZE";
-
- /**
- * Group type uuid extra field in {@link #ACTION_CSIS_DEVICE_AVAILABLE} intent.
- *
- * @hide
- */
- public static final String EXTRA_CSIS_GROUP_TYPE_UUID =
- "android.bluetooth.extra.CSIS_GROUP_TYPE_UUID";
-
- /**
- * Intent used to broadcast information about identified set member
- * ready to connect.
- *
- * <p>This intent will have one extra:
- * <ul>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
- * be null if no device is active. </li>
- * <li> {@link #EXTRA_CSIS_GROUP_ID} - Group identifier. </li>
- * </ul>
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CSIS_SET_MEMBER_AVAILABLE =
- "android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE";
-
- /**
- * This represents an invalid group ID.
- *
- * @hide
- */
- public static final int GROUP_ID_INVALID = IBluetoothCsipSetCoordinator.CSIS_GROUP_ID_INVALID;
-
- /**
- * Indicating that group was locked with success.
- *
- * @hide
- */
- public static final int GROUP_LOCK_SUCCESS = 0;
-
- /**
- * Indicating that group locked failed due to invalid group ID.
- *
- * @hide
- */
- public static final int GROUP_LOCK_FAILED_INVALID_GROUP = 1;
-
- /**
- * Indicating that group locked failed due to empty group.
- *
- * @hide
- */
- public static final int GROUP_LOCK_FAILED_GROUP_EMPTY = 2;
-
- /**
- * Indicating that group locked failed due to group members being disconnected.
- *
- * @hide
- */
- public static final int GROUP_LOCK_FAILED_GROUP_NOT_CONNECTED = 3;
-
- /**
- * Indicating that group locked failed due to group member being already locked.
- *
- * @hide
- */
- public static final int GROUP_LOCK_FAILED_LOCKED_BY_OTHER = 4;
-
- /**
- * Indicating that group locked failed due to other reason.
- *
- * @hide
- */
- public static final int GROUP_LOCK_FAILED_OTHER_REASON = 5;
-
- /**
- * Indicating that group member in locked state was lost.
- *
- * @hide
- */
- public static final int LOCKED_GROUP_MEMBER_LOST = 6;
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothCsipSetCoordinator> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.CSIP_SET_COORDINATOR, TAG,
- IBluetoothCsipSetCoordinator.class.getName()) {
- @Override
- public IBluetoothCsipSetCoordinator getServiceInterface(IBinder service) {
- return IBluetoothCsipSetCoordinator.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothCsipSetCoordinator proxy object for interacting with the local
- * Bluetooth CSIS service.
- */
- /*package*/ BluetoothCsipSetCoordinator(Context context, ServiceListener listener, BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- mCloseGuard = new CloseGuard();
- mCloseGuard.open("close");
- }
-
- /**
- * @hide
- */
- protected void finalize() {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
- close();
- }
-
- /**
- * @hide
- */
- public void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothCsipSetCoordinator getService() {
- return mProfileConnector.getService();
- }
-
- /**
- * Lock the set.
- * @param groupId group ID to lock,
- * @param executor callback executor,
- * @param cb callback to report lock and unlock events - stays valid until the app unlocks
- * using the returned lock identifier or the lock timeouts on the remote side,
- * as per CSIS specification,
- * @return unique lock identifier used for unlocking or null if lock has failed.
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public
- @Nullable UUID groupLock(int groupId, @Nullable @CallbackExecutor Executor executor,
- @Nullable ClientLockCallback cb) {
- if (VDBG) log("groupLockSet()");
- final IBluetoothCsipSetCoordinator service = getService();
- final UUID defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- IBluetoothCsipSetCoordinatorLockCallback delegate = null;
- if ((executor != null) && (cb != null)) {
- delegate = new BluetoothCsipSetCoordinatorLockCallbackDelegate(executor, cb);
- }
- try {
- final SynchronousResultReceiver<ParcelUuid> recv = new SynchronousResultReceiver();
- service.groupLock(groupId, delegate, mAttributionSource, recv);
- final ParcelUuid ret = recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- return ret == null ? defaultValue : ret.getUuid();
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Unlock the set.
- * @param lockUuid unique lock identifier
- * @return true if unlocked, false on error
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public boolean groupUnlock(@NonNull UUID lockUuid) {
- if (VDBG) log("groupLockSet()");
- if (lockUuid == null) {
- return false;
- }
- final IBluetoothCsipSetCoordinator service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.groupUnlock(new ParcelUuid(lockUuid), mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- return true;
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get device's groups.
- * @param device the active device
- * @return Map of groups ids and related UUIDs
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public @NonNull Map getGroupUuidMapByDevice(@Nullable BluetoothDevice device) {
- if (VDBG) log("getGroupUuidMapByDevice()");
- final IBluetoothCsipSetCoordinator service = getService();
- final Map defaultValue = new HashMap<>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Map> recv = new SynchronousResultReceiver();
- service.getGroupUuidMapByDevice(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get group id for the given UUID
- * @param uuid
- * @return list of group IDs
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public @NonNull List<Integer> getAllGroupIds(@Nullable ParcelUuid uuid) {
- if (VDBG) log("getAllGroupIds()");
- final IBluetoothCsipSetCoordinator service = getService();
- final List<Integer> defaultValue = new ArrayList<>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<Integer>> recv =
- new SynchronousResultReceiver();
- service.getAllGroupIds(uuid, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public @NonNull List<BluetoothDevice> getConnectedDevices() {
- if (VDBG) log("getConnectedDevices()");
- final IBluetoothCsipSetCoordinator service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public
- @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[] states) {
- if (VDBG) log("getDevicesMatchingStates(states=" + Arrays.toString(states) + ")");
- final IBluetoothCsipSetCoordinator service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public
- @BluetoothProfile.BtProfileState int getConnectionState(@Nullable BluetoothDevice device) {
- if (VDBG) log("getState(" + device + ")");
- final IBluetoothCsipSetCoordinator service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public boolean setConnectionPolicy(
- @Nullable BluetoothDevice device, @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothCsipSetCoordinator service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- final IBluetoothCsipSetCoordinator service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private boolean isEnabled() {
- return mAdapter.getState() == BluetoothAdapter.STATE_ON;
- }
-
- private static boolean isValidDevice(@Nullable BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
deleted file mode 100644
index 1edf5cc..0000000
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ /dev/null
@@ -1,2831 +0,0 @@
-/*
- * Copyright (C) 2009 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi; //import android.app.PropertyInvalidatedCache;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
-import android.bluetooth.annotations.RequiresBluetoothScanPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.companion.AssociationRequest;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-import android.os.Process;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.UUID;
-
-/**
- * Represents a remote Bluetooth device. A {@link BluetoothDevice} lets you
- * create a connection with the respective device or query information about
- * it, such as the name, address, class, and bonding state.
- *
- * <p>This class is really just a thin wrapper for a Bluetooth hardware
- * address. Objects of this class are immutable. Operations on this class
- * are performed on the remote Bluetooth hardware address, using the
- * {@link BluetoothAdapter} that was used to create this {@link
- * BluetoothDevice}.
- *
- * <p>To get a {@link BluetoothDevice}, use
- * {@link BluetoothAdapter#getRemoteDevice(String)
- * BluetoothAdapter.getRemoteDevice(String)} to create one representing a device
- * of a known MAC address (which you can get through device discovery with
- * {@link BluetoothAdapter}) or get one from the set of bonded devices
- * returned by {@link BluetoothAdapter#getBondedDevices()
- * BluetoothAdapter.getBondedDevices()}. You can then open a
- * {@link BluetoothSocket} for communication with the remote device, using
- * {@link #createRfcommSocketToServiceRecord(UUID)} over Bluetooth BR/EDR or using
- * {@link #createL2capChannel(int)} over Bluetooth LE.
- *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>
- * For more information about using Bluetooth, read the <a href=
- * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
- * guide.
- * </p>
- * </div>
- *
- * {@see BluetoothAdapter}
- * {@see BluetoothSocket}
- */
-public final class BluetoothDevice implements Parcelable, Attributable {
- private static final String TAG = "BluetoothDevice";
- private static final boolean DBG = false;
-
- /**
- * Connection state bitmask as returned by getConnectionState.
- */
- private static final int CONNECTION_STATE_DISCONNECTED = 0;
- private static final int CONNECTION_STATE_CONNECTED = 1;
- private static final int CONNECTION_STATE_ENCRYPTED_BREDR = 2;
- private static final int CONNECTION_STATE_ENCRYPTED_LE = 4;
-
- /**
- * Sentinel error value for this class. Guaranteed to not equal any other
- * integer constant in this class. Provided as a convenience for functions
- * that require a sentinel error value, for example:
- * <p><code>Intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
- * BluetoothDevice.ERROR)</code>
- */
- public static final int ERROR = Integer.MIN_VALUE;
-
- /**
- * Broadcast Action: Remote device discovered.
- * <p>Sent when a remote device is found during discovery.
- * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
- * #EXTRA_CLASS}. Can contain the extra fields {@link #EXTRA_NAME} and/or
- * {@link #EXTRA_RSSI} and/or {@link #EXTRA_IS_COORDINATED_SET_MEMBER} if they are available.
- */
- // TODO: Change API to not broadcast RSSI if not available (incoming connection)
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_FOUND =
- "android.bluetooth.device.action.FOUND";
-
- /**
- * Broadcast Action: Bluetooth class of a remote device has changed.
- * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
- * #EXTRA_CLASS}.
- * {@see BluetoothClass}
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CLASS_CHANGED =
- "android.bluetooth.device.action.CLASS_CHANGED";
-
- /**
- * Broadcast Action: Indicates a low level (ACL) connection has been
- * established with a remote device.
- * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
- * <p>ACL connections are managed automatically by the Android Bluetooth
- * stack.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_ACL_CONNECTED =
- "android.bluetooth.device.action.ACL_CONNECTED";
-
- /**
- * Broadcast Action: Indicates that a low level (ACL) disconnection has
- * been requested for a remote device, and it will soon be disconnected.
- * <p>This is useful for graceful disconnection. Applications should use
- * this intent as a hint to immediately terminate higher level connections
- * (RFCOMM, L2CAP, or profile connections) to the remote device.
- * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_ACL_DISCONNECT_REQUESTED =
- "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
-
- /**
- * Broadcast Action: Indicates a low level (ACL) disconnection from a
- * remote device.
- * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
- * <p>ACL connections are managed automatically by the Android Bluetooth
- * stack.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_ACL_DISCONNECTED =
- "android.bluetooth.device.action.ACL_DISCONNECTED";
-
- /**
- * Broadcast Action: Indicates the friendly name of a remote device has
- * been retrieved for the first time, or changed since the last retrieval.
- * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
- * #EXTRA_NAME}.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_NAME_CHANGED =
- "android.bluetooth.device.action.NAME_CHANGED";
-
- /**
- * Broadcast Action: Indicates the alias of a remote device has been
- * changed.
- * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
- */
- @SuppressLint("ActionValue")
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_ALIAS_CHANGED =
- "android.bluetooth.device.action.ALIAS_CHANGED";
-
- /**
- * Broadcast Action: Indicates a change in the bond state of a remote
- * device. For example, if a device is bonded (paired).
- * <p>Always contains the extra fields {@link #EXTRA_DEVICE}, {@link
- * #EXTRA_BOND_STATE} and {@link #EXTRA_PREVIOUS_BOND_STATE}.
- */
- // Note: When EXTRA_BOND_STATE is BOND_NONE then this will also
- // contain a hidden extra field EXTRA_REASON with the result code.
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BOND_STATE_CHANGED =
- "android.bluetooth.device.action.BOND_STATE_CHANGED";
-
- /**
- * Broadcast Action: Indicates the battery level of a remote device has
- * been retrieved for the first time, or changed since the last retrieval
- * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
- * #EXTRA_BATTERY_LEVEL}.
- *
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BATTERY_LEVEL_CHANGED =
- "android.bluetooth.device.action.BATTERY_LEVEL_CHANGED";
-
- /**
- * Used as an Integer extra field in {@link #ACTION_BATTERY_LEVEL_CHANGED}
- * intent. It contains the most recently retrieved battery level information
- * ranging from 0% to 100% for a remote device, {@link #BATTERY_LEVEL_UNKNOWN}
- * when the valid is unknown or there is an error
- *
- * @hide
- */
- public static final String EXTRA_BATTERY_LEVEL =
- "android.bluetooth.device.extra.BATTERY_LEVEL";
-
- /**
- * Used as the unknown value for {@link #EXTRA_BATTERY_LEVEL} and {@link #getBatteryLevel()}
- *
- * @hide
- */
- public static final int BATTERY_LEVEL_UNKNOWN = -1;
-
- /**
- * Used as an error value for {@link #getBatteryLevel()} to represent bluetooth is off
- *
- * @hide
- */
- public static final int BATTERY_LEVEL_BLUETOOTH_OFF = -100;
-
- /**
- * Used as a Parcelable {@link BluetoothDevice} extra field in every intent
- * broadcast by this class. It contains the {@link BluetoothDevice} that
- * the intent applies to.
- */
- public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
-
- /**
- * Used as a String extra field in {@link #ACTION_NAME_CHANGED} and {@link
- * #ACTION_FOUND} intents. It contains the friendly Bluetooth name.
- */
- public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME";
-
- /**
- * Used as an optional short extra field in {@link #ACTION_FOUND} intents.
- * Contains the RSSI value of the remote device as reported by the
- * Bluetooth hardware.
- */
- public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI";
-
- /**
- * Used as an bool extra field in {@link #ACTION_FOUND} intents.
- * It contains the information if device is discovered as member of a coordinated set or not.
- * Pairing with device that belongs to a set would trigger pairing with the rest of set members.
- * See Bluetooth CSIP specification for more details.
- */
- public static final String EXTRA_IS_COORDINATED_SET_MEMBER =
- "android.bluetooth.extra.IS_COORDINATED_SET_MEMBER";
-
- /**
- * Used as a Parcelable {@link BluetoothClass} extra field in {@link
- * #ACTION_FOUND} and {@link #ACTION_CLASS_CHANGED} intents.
- */
- public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS";
-
- /**
- * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
- * Contains the bond state of the remote device.
- * <p>Possible values are:
- * {@link #BOND_NONE},
- * {@link #BOND_BONDING},
- * {@link #BOND_BONDED}.
- */
- public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";
- /**
- * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
- * Contains the previous bond state of the remote device.
- * <p>Possible values are:
- * {@link #BOND_NONE},
- * {@link #BOND_BONDING},
- * {@link #BOND_BONDED}.
- */
- public static final String EXTRA_PREVIOUS_BOND_STATE =
- "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
- /**
- * Indicates the remote device is not bonded (paired).
- * <p>There is no shared link key with the remote device, so communication
- * (if it is allowed at all) will be unauthenticated and unencrypted.
- */
- public static final int BOND_NONE = 10;
- /**
- * Indicates bonding (pairing) is in progress with the remote device.
- */
- public static final int BOND_BONDING = 11;
- /**
- * Indicates the remote device is bonded (paired).
- * <p>A shared link keys exists locally for the remote device, so
- * communication can be authenticated and encrypted.
- * <p><i>Being bonded (paired) with a remote device does not necessarily
- * mean the device is currently connected. It just means that the pending
- * procedure was completed at some earlier time, and the link key is still
- * stored locally, ready to use on the next connection.
- * </i>
- */
- public static final int BOND_BONDED = 12;
-
- /**
- * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
- * intents for unbond reason.
- *
- * @hide
- */
- @UnsupportedAppUsage
- public static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON";
-
- /**
- * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
- * intents to indicate pairing method used. Possible values are:
- * {@link #PAIRING_VARIANT_PIN},
- * {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION},
- */
- public static final String EXTRA_PAIRING_VARIANT =
- "android.bluetooth.device.extra.PAIRING_VARIANT";
-
- /**
- * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
- * intents as the value of passkey.
- */
- public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
-
- /**
- * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
- * intents as the value of passkey.
- * @hide
- */
- public static final String EXTRA_PAIRING_INITIATOR =
- "android.bluetooth.device.extra.PAIRING_INITIATOR";
-
- /**
- * Bluetooth pairing initiator, Foreground App
- * @hide
- */
- public static final int EXTRA_PAIRING_INITIATOR_FOREGROUND = 1;
-
- /**
- * Bluetooth pairing initiator, Background
- * @hide
- */
- public static final int EXTRA_PAIRING_INITIATOR_BACKGROUND = 2;
-
- /**
- * Bluetooth device type, Unknown
- */
- public static final int DEVICE_TYPE_UNKNOWN = 0;
-
- /**
- * Bluetooth device type, Classic - BR/EDR devices
- */
- public static final int DEVICE_TYPE_CLASSIC = 1;
-
- /**
- * Bluetooth device type, Low Energy - LE-only
- */
- public static final int DEVICE_TYPE_LE = 2;
-
- /**
- * Bluetooth device type, Dual Mode - BR/EDR/LE
- */
- public static final int DEVICE_TYPE_DUAL = 3;
-
-
- /** @hide */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final String ACTION_SDP_RECORD =
- "android.bluetooth.device.action.SDP_RECORD";
-
- /** @hide */
- @IntDef(prefix = "METADATA_", value = {
- METADATA_MANUFACTURER_NAME,
- METADATA_MODEL_NAME,
- METADATA_SOFTWARE_VERSION,
- METADATA_HARDWARE_VERSION,
- METADATA_COMPANION_APP,
- METADATA_MAIN_ICON,
- METADATA_IS_UNTETHERED_HEADSET,
- METADATA_UNTETHERED_LEFT_ICON,
- METADATA_UNTETHERED_RIGHT_ICON,
- METADATA_UNTETHERED_CASE_ICON,
- METADATA_UNTETHERED_LEFT_BATTERY,
- METADATA_UNTETHERED_RIGHT_BATTERY,
- METADATA_UNTETHERED_CASE_BATTERY,
- METADATA_UNTETHERED_LEFT_CHARGING,
- METADATA_UNTETHERED_RIGHT_CHARGING,
- METADATA_UNTETHERED_CASE_CHARGING,
- METADATA_ENHANCED_SETTINGS_UI_URI,
- METADATA_DEVICE_TYPE,
- METADATA_MAIN_BATTERY,
- METADATA_MAIN_CHARGING,
- METADATA_MAIN_LOW_BATTERY_THRESHOLD,
- METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD,
- METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD,
- METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD})
- @Retention(RetentionPolicy.SOURCE)
- public @interface MetadataKey{}
-
- /**
- * Maximum length of a metadata entry, this is to avoid exploding Bluetooth
- * disk usage
- * @hide
- */
- @SystemApi
- public static final int METADATA_MAX_LENGTH = 2048;
-
- /**
- * Manufacturer name of this Bluetooth device
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_MANUFACTURER_NAME = 0;
-
- /**
- * Model name of this Bluetooth device
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_MODEL_NAME = 1;
-
- /**
- * Software version of this Bluetooth device
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_SOFTWARE_VERSION = 2;
-
- /**
- * Hardware version of this Bluetooth device
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_HARDWARE_VERSION = 3;
-
- /**
- * Package name of the companion app, if any
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_COMPANION_APP = 4;
-
- /**
- * URI to the main icon shown on the settings UI
- * Data type should be {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_MAIN_ICON = 5;
-
- /**
- * Whether this device is an untethered headset with left, right and case
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_IS_UNTETHERED_HEADSET = 6;
-
- /**
- * URI to icon of the left headset
- * Data type should be {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_LEFT_ICON = 7;
-
- /**
- * URI to icon of the right headset
- * Data type should be {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_RIGHT_ICON = 8;
-
- /**
- * URI to icon of the headset charging case
- * Data type should be {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_CASE_ICON = 9;
-
- /**
- * Battery level of left headset
- * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
- * as invalid.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10;
-
- /**
- * Battery level of rigth headset
- * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
- * as invalid.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11;
-
- /**
- * Battery level of the headset charging case
- * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
- * as invalid.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_CASE_BATTERY = 12;
-
- /**
- * Whether the left headset is charging
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13;
-
- /**
- * Whether the right headset is charging
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14;
-
- /**
- * Whether the headset charging case is charging
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_CASE_CHARGING = 15;
-
- /**
- * URI to the enhanced settings UI slice
- * Data type should be {@String} as {@link Byte} array, null means
- * the UI does not exist.
- * @hide
- */
- @SystemApi
- public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16;
-
- /**
- * Type of the Bluetooth device, must be within the list of
- * BluetoothDevice.DEVICE_TYPE_*
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_DEVICE_TYPE = 17;
-
- /**
- * Battery level of the Bluetooth device, use when the Bluetooth device
- * does not support HFP battery indicator.
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_MAIN_BATTERY = 18;
-
- /**
- * Whether the device is charging.
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_MAIN_CHARGING = 19;
-
- /**
- * The battery threshold of the Bluetooth device to show low battery icon.
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_MAIN_LOW_BATTERY_THRESHOLD = 20;
-
- /**
- * The battery threshold of the left headset to show low battery icon.
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD = 21;
-
- /**
- * The battery threshold of the right headset to show low battery icon.
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD = 22;
-
- /**
- * The battery threshold of the case to show low battery icon.
- * Data type should be {@String} as {@link Byte} array.
- * @hide
- */
- @SystemApi
- public static final int METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD = 23;
-
- /**
- * Device type which is used in METADATA_DEVICE_TYPE
- * Indicates this Bluetooth device is a standard Bluetooth accessory or
- * not listed in METADATA_DEVICE_TYPE_*.
- * @hide
- */
- @SystemApi
- public static final String DEVICE_TYPE_DEFAULT = "Default";
-
- /**
- * Device type which is used in METADATA_DEVICE_TYPE
- * Indicates this Bluetooth device is a watch.
- * @hide
- */
- @SystemApi
- public static final String DEVICE_TYPE_WATCH = "Watch";
-
- /**
- * Device type which is used in METADATA_DEVICE_TYPE
- * Indicates this Bluetooth device is an untethered headset.
- * @hide
- */
- @SystemApi
- public static final String DEVICE_TYPE_UNTETHERED_HEADSET = "Untethered Headset";
-
- /**
- * Broadcast Action: This intent is used to broadcast the {@link UUID}
- * wrapped as a {@link android.os.ParcelUuid} of the remote device after it
- * has been fetched. This intent is sent only when the UUIDs of the remote
- * device are requested to be fetched using Service Discovery Protocol
- * <p> Always contains the extra field {@link #EXTRA_DEVICE}
- * <p> Always contains the extra field {@link #EXTRA_UUID}
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_UUID =
- "android.bluetooth.device.action.UUID";
-
- /** @hide */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MAS_INSTANCE =
- "android.bluetooth.device.action.MAS_INSTANCE";
-
- /**
- * Broadcast Action: Indicates a failure to retrieve the name of a remote
- * device.
- * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
- *
- * @hide
- */
- //TODO: is this actually useful?
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_NAME_FAILED =
- "android.bluetooth.device.action.NAME_FAILED";
-
- /**
- * Broadcast Action: This intent is used to broadcast PAIRING REQUEST
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PAIRING_REQUEST =
- "android.bluetooth.device.action.PAIRING_REQUEST";
- /** @hide */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @UnsupportedAppUsage
- public static final String ACTION_PAIRING_CANCEL =
- "android.bluetooth.device.action.PAIRING_CANCEL";
-
- /** @hide */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_ACCESS_REQUEST =
- "android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST";
-
- /** @hide */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_ACCESS_REPLY =
- "android.bluetooth.device.action.CONNECTION_ACCESS_REPLY";
-
- /** @hide */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_ACCESS_CANCEL =
- "android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL";
-
- /**
- * Intent to broadcast silence mode changed.
- * Alway contains the extra field {@link #EXTRA_DEVICE}
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @SystemApi
- public static final String ACTION_SILENCE_MODE_CHANGED =
- "android.bluetooth.device.action.SILENCE_MODE_CHANGED";
-
- /**
- * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intent.
- *
- * @hide
- */
- public static final String EXTRA_ACCESS_REQUEST_TYPE =
- "android.bluetooth.device.extra.ACCESS_REQUEST_TYPE";
-
- /** @hide */
- public static final int REQUEST_TYPE_PROFILE_CONNECTION = 1;
-
- /** @hide */
- public static final int REQUEST_TYPE_PHONEBOOK_ACCESS = 2;
-
- /** @hide */
- public static final int REQUEST_TYPE_MESSAGE_ACCESS = 3;
-
- /** @hide */
- public static final int REQUEST_TYPE_SIM_ACCESS = 4;
-
- /**
- * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
- * Contains package name to return reply intent to.
- *
- * @hide
- */
- public static final String EXTRA_PACKAGE_NAME = "android.bluetooth.device.extra.PACKAGE_NAME";
-
- /**
- * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
- * Contains class name to return reply intent to.
- *
- * @hide
- */
- public static final String EXTRA_CLASS_NAME = "android.bluetooth.device.extra.CLASS_NAME";
-
- /**
- * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intent.
- *
- * @hide
- */
- public static final String EXTRA_CONNECTION_ACCESS_RESULT =
- "android.bluetooth.device.extra.CONNECTION_ACCESS_RESULT";
-
- /** @hide */
- public static final int CONNECTION_ACCESS_YES = 1;
-
- /** @hide */
- public static final int CONNECTION_ACCESS_NO = 2;
-
- /**
- * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intents,
- * Contains boolean to indicate if the allowed response is once-for-all so that
- * next request will be granted without asking user again.
- *
- * @hide
- */
- public static final String EXTRA_ALWAYS_ALLOWED =
- "android.bluetooth.device.extra.ALWAYS_ALLOWED";
-
- /**
- * A bond attempt succeeded
- *
- * @hide
- */
- public static final int BOND_SUCCESS = 0;
-
- /**
- * A bond attempt failed because pins did not match, or remote device did
- * not respond to pin request in time
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int UNBOND_REASON_AUTH_FAILED = 1;
-
- /**
- * A bond attempt failed because the other side explicitly rejected
- * bonding
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int UNBOND_REASON_AUTH_REJECTED = 2;
-
- /**
- * A bond attempt failed because we canceled the bonding process
- *
- * @hide
- */
- public static final int UNBOND_REASON_AUTH_CANCELED = 3;
-
- /**
- * A bond attempt failed because we could not contact the remote device
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4;
-
- /**
- * A bond attempt failed because a discovery is in progress
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
-
- /**
- * A bond attempt failed because of authentication timeout
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int UNBOND_REASON_AUTH_TIMEOUT = 6;
-
- /**
- * A bond attempt failed because of repeated attempts
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7;
-
- /**
- * A bond attempt failed because we received an Authentication Cancel
- * by remote end
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8;
-
- /**
- * An existing bond was explicitly revoked
- *
- * @hide
- */
- public static final int UNBOND_REASON_REMOVED = 9;
-
- /**
- * The user will be prompted to enter a pin or
- * an app will enter a pin for user.
- */
- public static final int PAIRING_VARIANT_PIN = 0;
-
- /**
- * The user will be prompted to enter a passkey
- *
- * @hide
- */
- public static final int PAIRING_VARIANT_PASSKEY = 1;
-
- /**
- * The user will be prompted to confirm the passkey displayed on the screen or
- * an app will confirm the passkey for the user.
- */
- public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2;
-
- /**
- * The user will be prompted to accept or deny the incoming pairing request
- *
- * @hide
- */
- public static final int PAIRING_VARIANT_CONSENT = 3;
-
- /**
- * The user will be prompted to enter the passkey displayed on remote device
- * This is used for Bluetooth 2.1 pairing.
- *
- * @hide
- */
- public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;
-
- /**
- * The user will be prompted to enter the PIN displayed on remote device.
- * This is used for Bluetooth 2.0 pairing.
- *
- * @hide
- */
- public static final int PAIRING_VARIANT_DISPLAY_PIN = 5;
-
- /**
- * The user will be prompted to accept or deny the OOB pairing request
- *
- * @hide
- */
- public static final int PAIRING_VARIANT_OOB_CONSENT = 6;
-
- /**
- * The user will be prompted to enter a 16 digit pin or
- * an app will enter a 16 digit pin for user.
- *
- * @hide
- */
- public static final int PAIRING_VARIANT_PIN_16_DIGITS = 7;
-
- /**
- * Used as an extra field in {@link #ACTION_UUID} intents,
- * Contains the {@link android.os.ParcelUuid}s of the remote device which
- * is a parcelable version of {@link UUID}.
- */
- public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
-
- /** @hide */
- public static final String EXTRA_SDP_RECORD =
- "android.bluetooth.device.extra.SDP_RECORD";
-
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final String EXTRA_SDP_SEARCH_STATUS =
- "android.bluetooth.device.extra.SDP_SEARCH_STATUS";
-
- /** @hide */
- @IntDef(prefix = "ACCESS_", value = {ACCESS_UNKNOWN,
- ACCESS_ALLOWED, ACCESS_REJECTED})
- @Retention(RetentionPolicy.SOURCE)
- public @interface AccessPermission{}
-
- /**
- * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
- * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
- *
- * @hide
- */
- @SystemApi
- public static final int ACCESS_UNKNOWN = 0;
-
- /**
- * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
- * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
- *
- * @hide
- */
- @SystemApi
- public static final int ACCESS_ALLOWED = 1;
-
- /**
- * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
- * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
- *
- * @hide
- */
- @SystemApi
- public static final int ACCESS_REJECTED = 2;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- prefix = { "TRANSPORT_" },
- value = {
- /** Allow host to automatically select a transport (dual-mode only) */
- TRANSPORT_AUTO,
- /** Use Classic or BR/EDR transport.*/
- TRANSPORT_BREDR,
- /** Use Low Energy transport.*/
- TRANSPORT_LE,
- }
- )
- public @interface Transport {}
-
- /**
- * No preference of physical transport for GATT connections to remote dual-mode devices
- */
- public static final int TRANSPORT_AUTO = 0;
-
- /**
- * Prefer BR/EDR transport for GATT connections to remote dual-mode devices
- */
- public static final int TRANSPORT_BREDR = 1;
-
- /**
- * Prefer LE transport for GATT connections to remote dual-mode devices
- */
- public static final int TRANSPORT_LE = 2;
-
- /**
- * Bluetooth LE 1M PHY. Used to refer to LE 1M Physical Channel for advertising, scanning or
- * connection.
- */
- public static final int PHY_LE_1M = 1;
-
- /**
- * Bluetooth LE 2M PHY. Used to refer to LE 2M Physical Channel for advertising, scanning or
- * connection.
- */
- public static final int PHY_LE_2M = 2;
-
- /**
- * Bluetooth LE Coded PHY. Used to refer to LE Coded Physical Channel for advertising, scanning
- * or connection.
- */
- public static final int PHY_LE_CODED = 3;
-
- /**
- * Bluetooth LE 1M PHY mask. Used to specify LE 1M Physical Channel as one of many available
- * options in a bitmask.
- */
- public static final int PHY_LE_1M_MASK = 1;
-
- /**
- * Bluetooth LE 2M PHY mask. Used to specify LE 2M Physical Channel as one of many available
- * options in a bitmask.
- */
- public static final int PHY_LE_2M_MASK = 2;
-
- /**
- * Bluetooth LE Coded PHY mask. Used to specify LE Coded Physical Channel as one of many
- * available options in a bitmask.
- */
- public static final int PHY_LE_CODED_MASK = 4;
-
- /**
- * No preferred coding when transmitting on the LE Coded PHY.
- */
- public static final int PHY_OPTION_NO_PREFERRED = 0;
-
- /**
- * Prefer the S=2 coding to be used when transmitting on the LE Coded PHY.
- */
- public static final int PHY_OPTION_S2 = 1;
-
- /**
- * Prefer the S=8 coding to be used when transmitting on the LE Coded PHY.
- */
- public static final int PHY_OPTION_S8 = 2;
-
-
- /** @hide */
- public static final String EXTRA_MAS_INSTANCE =
- "android.bluetooth.device.extra.MAS_INSTANCE";
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- prefix = { "ADDRESS_TYPE_" },
- value = {
- /** Hardware MAC Address */
- ADDRESS_TYPE_PUBLIC,
- /** Address is either resolvable, non-resolvable or static.*/
- ADDRESS_TYPE_RANDOM,
- }
- )
- public @interface AddressType {}
-
- /** Hardware MAC Address of the device */
- public static final int ADDRESS_TYPE_PUBLIC = 0;
- /** Address is either resolvable, non-resolvable or static. */
- public static final int ADDRESS_TYPE_RANDOM = 1;
-
- private static final String NULL_MAC_ADDRESS = "00:00:00:00:00:00";
-
- /**
- * Lazy initialization. Guaranteed final after first object constructed, or
- * getService() called.
- * TODO: Unify implementation of sService amongst BluetoothFoo API's
- */
- private static volatile IBluetooth sService;
-
- private final String mAddress;
- @AddressType private final int mAddressType;
-
- private AttributionSource mAttributionSource;
-
- /*package*/
- @UnsupportedAppUsage
- static IBluetooth getService() {
- synchronized (BluetoothDevice.class) {
- if (sService == null) {
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- sService = adapter.getBluetoothService(sStateChangeCallback);
- }
- }
- return sService;
- }
-
- static IBluetoothManagerCallback sStateChangeCallback = new IBluetoothManagerCallback.Stub() {
-
- public void onBluetoothServiceUp(IBluetooth bluetoothService)
- throws RemoteException {
- synchronized (BluetoothDevice.class) {
- if (sService == null) {
- sService = bluetoothService;
- }
- }
- }
-
- public void onBluetoothServiceDown()
- throws RemoteException {
- synchronized (BluetoothDevice.class) {
- sService = null;
- }
- }
-
- public void onBrEdrDown() {
- if (DBG) Log.d(TAG, "onBrEdrDown: reached BLE ON state");
- }
-
- public void onOobData(@Transport int transport, OobData oobData) {
- if (DBG) Log.d(TAG, "onOobData: got data");
- }
- };
-
- /**
- * Create a new BluetoothDevice
- * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB",
- * and is validated in this constructor.
- *
- * @param address valid Bluetooth MAC address
- * @param attributionSource attribution for permission-protected calls
- * @throws RuntimeException Bluetooth is not available on this platform
- * @throws IllegalArgumentException address is invalid
- * @hide
- */
- @UnsupportedAppUsage
- /*package*/ BluetoothDevice(String address) {
- getService(); // ensures sService is initialized
- if (!BluetoothAdapter.checkBluetoothAddress(address)) {
- throw new IllegalArgumentException(address + " is not a valid Bluetooth address");
- }
-
- mAddress = address;
- mAddressType = ADDRESS_TYPE_PUBLIC;
- mAttributionSource = AttributionSource.myAttributionSource();
- }
-
- /** {@hide} */
- public void setAttributionSource(@NonNull AttributionSource attributionSource) {
- mAttributionSource = attributionSource;
- }
-
- /** {@hide} */
- public void prepareToEnterProcess(@NonNull AttributionSource attributionSource) {
- setAttributionSource(attributionSource);
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (o instanceof BluetoothDevice) {
- return mAddress.equals(((BluetoothDevice) o).getAddress());
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return mAddress.hashCode();
- }
-
- /**
- * Returns a string representation of this BluetoothDevice.
- * <p>Currently this is the Bluetooth hardware address, for example
- * "00:11:22:AA:BB:CC". However, you should always use {@link #getAddress}
- * if you explicitly require the Bluetooth hardware address in case the
- * {@link #toString} representation changes in the future.
- *
- * @return string representation of this BluetoothDevice
- */
- @Override
- public String toString() {
- return mAddress;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothDevice> CREATOR =
- new Parcelable.Creator<BluetoothDevice>() {
- public BluetoothDevice createFromParcel(Parcel in) {
- return new BluetoothDevice(in.readString());
- }
-
- public BluetoothDevice[] newArray(int size) {
- return new BluetoothDevice[size];
- }
- };
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mAddress);
- }
-
- /**
- * Returns the hardware address of this BluetoothDevice.
- * <p> For example, "00:11:22:AA:BB:CC".
- *
- * @return Bluetooth hardware address as string
- */
- public String getAddress() {
- if (DBG) Log.d(TAG, "mAddress: " + mAddress);
- return mAddress;
- }
-
- /**
- * Returns the anonymized hardware address of this BluetoothDevice. The first three octets
- * will be suppressed for anonymization.
- * <p> For example, "XX:XX:XX:AA:BB:CC".
- *
- * @return Anonymized bluetooth hardware address as string
- * @hide
- */
- public String getAnonymizedAddress() {
- return "XX:XX:XX" + getAddress().substring(8);
- }
-
- /**
- * Get the friendly Bluetooth name of the remote device.
- *
- * <p>The local adapter will automatically retrieve remote names when
- * performing a device scan, and will cache them. This method just returns
- * the name for this device from the cache.
- *
- * @return the Bluetooth name, or null if there was a problem.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public String getName() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
- return null;
- }
- try {
- String name = service.getRemoteName(this, mAttributionSource);
- if (name != null) {
- // remove whitespace characters from the name
- return name
- .replace('\t', ' ')
- .replace('\n', ' ')
- .replace('\r', ' ');
- }
- return null;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return null;
- }
-
- /**
- * Get the Bluetooth device type of the remote device.
- *
- * @return the device type {@link #DEVICE_TYPE_CLASSIC}, {@link #DEVICE_TYPE_LE} {@link
- * #DEVICE_TYPE_DUAL}. {@link #DEVICE_TYPE_UNKNOWN} if it's not available
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getType() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot get Remote Device type");
- return DEVICE_TYPE_UNKNOWN;
- }
- try {
- return service.getRemoteType(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return DEVICE_TYPE_UNKNOWN;
- }
-
- /**
- * Get the locally modifiable name (alias) of the remote Bluetooth device.
- *
- * @return the Bluetooth alias, the friendly device name if no alias, or
- * null if there was a problem
- */
- @Nullable
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public String getAlias() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias");
- return null;
- }
- try {
- String alias = service.getRemoteAliasWithAttribution(this, mAttributionSource);
- if (alias == null) {
- return getName();
- }
- return alias
- .replace('\t', ' ')
- .replace('\n', ' ')
- .replace('\r', ' ');
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return null;
- }
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- BluetoothStatusCodes.SUCCESS,
- BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
- BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
- BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
- BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED
- })
- public @interface SetAliasReturnValues{}
-
- /**
- * Sets the locally modifiable name (alias) of the remote Bluetooth device. This method
- * overwrites the previously stored alias. The new alias is saved in local
- * storage so that the change is preserved over power cycles.
- *
- * <p>This method requires the calling app to be associated with Companion Device Manager (see
- * {@link android.companion.CompanionDeviceManager#associate(AssociationRequest,
- * android.companion.CompanionDeviceManager.Callback, Handler)}) and have the
- * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission. Alternatively, if the
- * caller has the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission, they can
- * bypass the Companion Device Manager association requirement as well as other permission
- * requirements.
- *
- * @param alias is the new locally modifiable name for the remote Bluetooth device which must
- * be the empty string. If null, we clear the alias.
- * @return whether the alias was successfully changed
- * @throws IllegalArgumentException if the alias is the empty string
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @SetAliasReturnValues int setAlias(@Nullable String alias) {
- if (alias != null && alias.isEmpty()) {
- throw new IllegalArgumentException("alias cannot be the empty string");
- }
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- try {
- return service.setRemoteAlias(this, alias, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get the most recent identified battery level of this Bluetooth device
- *
- * @return Battery level in percents from 0 to 100, {@link #BATTERY_LEVEL_BLUETOOTH_OFF} if
- * Bluetooth is disabled or {@link #BATTERY_LEVEL_UNKNOWN} if device is disconnected, or does
- * not have any battery reporting service, or return value is invalid
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getBatteryLevel() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level");
- return BATTERY_LEVEL_BLUETOOTH_OFF;
- }
- try {
- return service.getBatteryLevel(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return BATTERY_LEVEL_UNKNOWN;
- }
-
- /**
- * Start the bonding (pairing) process with the remote device.
- * <p>This is an asynchronous call, it will return immediately. Register
- * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
- * the bonding process completes, and its result.
- * <p>Android system services will handle the necessary user interactions
- * to confirm and complete the bonding process.
- *
- * @return false on immediate error, true if bonding will begin
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean createBond() {
- return createBond(TRANSPORT_AUTO);
- }
-
- /**
- * Start the bonding (pairing) process with the remote device using the
- * specified transport.
- *
- * <p>This is an asynchronous call, it will return immediately. Register
- * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
- * the bonding process completes, and its result.
- * <p>Android system services will handle the necessary user interactions
- * to confirm and complete the bonding process.
- *
- * @param transport The transport to use for the pairing procedure.
- * @return false on immediate error, true if bonding will begin
- * @throws IllegalArgumentException if an invalid transport was specified
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean createBond(int transport) {
- return createBondInternal(transport, null, null);
- }
-
- /**
- * Start the bonding (pairing) process with the remote device using the
- * Out Of Band mechanism.
- *
- * <p>This is an asynchronous call, it will return immediately. Register
- * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
- * the bonding process completes, and its result.
- *
- * <p>Android system services will handle the necessary user interactions
- * to confirm and complete the bonding process.
- *
- * <p>There are two possible versions of OOB Data. This data can come in as
- * P192 or P256. This is a reference to the cryptography used to generate the key.
- * The caller may pass one or both. If both types of data are passed, then the
- * P256 data will be preferred, and thus used.
- *
- * @param transport - Transport to use
- * @param remoteP192Data - Out Of Band data (P192) or null
- * @param remoteP256Data - Out Of Band data (P256) or null
- * @return false on immediate error, true if bonding will begin
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean createBondOutOfBand(int transport, @Nullable OobData remoteP192Data,
- @Nullable OobData remoteP256Data) {
- if (remoteP192Data == null && remoteP256Data == null) {
- throw new IllegalArgumentException(
- "One or both arguments for the OOB data types are required to not be null."
- + " Please use createBond() instead if you do not have OOB data to pass.");
- }
- return createBondInternal(transport, remoteP192Data, remoteP256Data);
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private boolean createBondInternal(int transport, @Nullable OobData remoteP192Data,
- @Nullable OobData remoteP256Data) {
- final IBluetooth service = sService;
- if (service == null) {
- Log.w(TAG, "BT not enabled, createBondOutOfBand failed");
- return false;
- }
- if (NULL_MAC_ADDRESS.equals(mAddress)) {
- Log.e(TAG, "Unable to create bond, invalid address " + mAddress);
- return false;
- }
- try {
- return service.createBond(
- this, transport, remoteP192Data, remoteP256Data, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Gets whether bonding was initiated locally
- *
- * @return true if bonding is initiated locally, false otherwise
- *
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isBondingInitiatedLocally() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.w(TAG, "BT not enabled, isBondingInitiatedLocally failed");
- return false;
- }
- try {
- return service.isBondingInitiatedLocally(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Cancel an in-progress bonding request started with {@link #createBond}.
- *
- * @return true on success, false on error
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean cancelBondProcess() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond");
- return false;
- }
- try {
- Log.i(TAG, "cancelBondProcess() for device " + getAddress()
- + " called by pid: " + Process.myPid()
- + " tid: " + Process.myTid());
- return service.cancelBondProcess(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Remove bond (pairing) with the remote device.
- * <p>Delete the link key associated with the remote device, and
- * immediately terminate connections to that device that require
- * authentication and encryption.
- *
- * @return true on success, false on error
- * @hide
- */
- @SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean removeBond() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond");
- return false;
- }
- try {
- Log.i(TAG, "removeBond() for device " + getAddress()
- + " called by pid: " + Process.myPid()
- + " tid: " + Process.myTid());
- return service.removeBond(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /*
- private static final String BLUETOOTH_BONDING_CACHE_PROPERTY =
- "cache_key.bluetooth.get_bond_state";
- private final PropertyInvalidatedCache<BluetoothDevice, Integer> mBluetoothBondCache =
- new PropertyInvalidatedCache<BluetoothDevice, Integer>(
- 8, BLUETOOTH_BONDING_CACHE_PROPERTY) {
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- protected Integer recompute(BluetoothDevice query) {
- try {
- return sService.getBondState(query, mAttributionSource);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- }
- };
- */
-
- /** @hide */
- /* public void disableBluetoothGetBondStateCache() {
- mBluetoothBondCache.disableLocal();
- } */
-
- /** @hide */
- /*
- public static void invalidateBluetoothGetBondStateCache() {
- PropertyInvalidatedCache.invalidateCache(BLUETOOTH_BONDING_CACHE_PROPERTY);
- }
- */
-
- /**
- * Get the bond state of the remote device.
- * <p>Possible values for the bond state are:
- * {@link #BOND_NONE},
- * {@link #BOND_BONDING},
- * {@link #BOND_BONDED}.
- *
- * @return the bond state
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public int getBondState() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot get bond state");
- return BOND_NONE;
- }
- try {
- //return mBluetoothBondCache.query(this);
- return sService.getBondState(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "failed to ", e);
- e.rethrowFromSystemServer();
- }
- return BOND_NONE;
- }
-
- /**
- * Checks whether this bluetooth device is associated with CDM and meets the criteria to skip
- * the bluetooth pairing dialog because it has been already consented by the CDM prompt.
- *
- * @return true if we can bond without the dialog, false otherwise
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean canBondWithoutDialog() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot check if we can skip pairing dialog");
- return false;
- }
- try {
- if (DBG) Log.d(TAG, "canBondWithoutDialog, device: " + this);
- return service.canBondWithoutDialog(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- BluetoothStatusCodes.SUCCESS,
- BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
- BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
- BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
- BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED
- })
- public @interface ConnectionReturnValues{}
-
- /**
- * Connects all user enabled and supported bluetooth profiles between the local and remote
- * device. If no profiles are user enabled (e.g. first connection), we connect all supported
- * profiles. If the device is not already connected, this will page the device before initiating
- * profile connections. Connection is asynchronous and you should listen to each profile's
- * broadcast intent ACTION_CONNECTION_STATE_CHANGED to verify whether connection was successful.
- * For example, to verify a2dp is connected, you would listen for
- * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
- *
- * @return whether the messages were successfully sent to try to connect all profiles
- * @throws IllegalArgumentException if the device address is invalid
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public @ConnectionReturnValues int connect() {
- if (!BluetoothAdapter.checkBluetoothAddress(getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
-
- try {
- if (sService == null) {
- Log.e(TAG, "BT not enabled. Cannot connect to remote device.");
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- return sService.connectAllEnabledProfiles(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Disconnects all connected bluetooth profiles between the local and remote device.
- * Disconnection is asynchronous and you should listen to each profile's broadcast intent
- * ACTION_CONNECTION_STATE_CHANGED to verify whether disconnection was successful. For example,
- * to verify a2dp is disconnected, you would listen for
- * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
- *
- * @return whether the messages were successfully sent to try to disconnect all profiles
- * @throws IllegalArgumentException if the device address is invalid
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionReturnValues int disconnect() {
- if (!BluetoothAdapter.checkBluetoothAddress(getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
-
- try {
- if (sService == null) {
- Log.e(TAG, "BT not enabled. Cannot disconnect from remote device.");
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- return sService.disconnectAllEnabledProfiles(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Returns whether there is an open connection to this device.
- *
- * @return True if there is at least one open connection to this device.
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isConnected() {
- final IBluetooth service = sService;
- if (service == null) {
- // BT is not enabled, we cannot be connected.
- return false;
- }
- try {
- return service.getConnectionStateWithAttribution(this, mAttributionSource)
- != CONNECTION_STATE_DISCONNECTED;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
- }
-
- /**
- * Returns whether there is an open connection to this device
- * that has been encrypted.
- *
- * @return True if there is at least one encrypted connection to this device.
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isEncrypted() {
- final IBluetooth service = sService;
- if (service == null) {
- // BT is not enabled, we cannot be connected.
- return false;
- }
- try {
- return service.getConnectionStateWithAttribution(this, mAttributionSource)
- > CONNECTION_STATE_CONNECTED;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
- }
-
- /**
- * Get the Bluetooth class of the remote device.
- *
- * @return Bluetooth class object, or null on error
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothClass getBluetoothClass() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class");
- return null;
- }
- try {
- int classInt = service.getRemoteClass(this, mAttributionSource);
- if (classInt == BluetoothClass.ERROR) return null;
- return new BluetoothClass(classInt);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return null;
- }
-
- /**
- * Returns the supported features (UUIDs) of the remote device.
- *
- * <p>This method does not start a service discovery procedure to retrieve the UUIDs
- * from the remote device. Instead, the local cached copy of the service
- * UUIDs are returned.
- * <p>Use {@link #fetchUuidsWithSdp} if fresh UUIDs are desired.
- *
- * @return the supported features (UUIDs) of the remote device, or null on error
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public ParcelUuid[] getUuids() {
- final IBluetooth service = sService;
- if (service == null || !isBluetoothEnabled()) {
- Log.e(TAG, "BT not enabled. Cannot get remote device Uuids");
- return null;
- }
- try {
- return service.getRemoteUuids(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return null;
- }
-
- /**
- * Perform a service discovery on the remote device to get the UUIDs supported.
- *
- * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent,
- * with the UUIDs supported by the remote end. If there is an error
- * in getting the SDP records or if the process takes a long time, or the device is bonding and
- * we have its UUIDs cached, {@link #ACTION_UUID} intent is sent with the UUIDs that is
- * currently present in the cache. Clients should use the {@link #getUuids} to get UUIDs
- * if service discovery is not to be performed. If there is an ongoing bonding process,
- * service discovery or device inquiry, the request will be queued.
- *
- * @return False if the check fails, True if the process of initiating an ACL connection
- * to the remote device was started or cached UUIDs will be broadcast.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean fetchUuidsWithSdp() {
- return fetchUuidsWithSdp(TRANSPORT_AUTO);
- }
-
- /**
- * Perform a service discovery on the remote device to get the UUIDs supported with the
- * specific transport.
- *
- * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent,
- * with the UUIDs supported by the remote end. If there is an error
- * in getting the SDP or GATT records or if the process takes a long time, or the device
- * is bonding and we have its UUIDs cached, {@link #ACTION_UUID} intent is sent with the
- * UUIDs that is currently present in the cache. Clients should use the {@link #getUuids}
- * to get UUIDs if service discovery is not to be performed. If there is an ongoing bonding
- * process, service discovery or device inquiry, the request will be queued.
- *
- * @param transport - provide type of transport (e.g. LE or Classic).
- * @return False if the check fails, True if the process of initiating an ACL connection
- * to the remote device was started or cached UUIDs will be broadcast with the specific
- * transport.
- *
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean fetchUuidsWithSdp(@Transport int transport) {
- final IBluetooth service = sService;
- if (service == null || !isBluetoothEnabled()) {
- Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp");
- return false;
- }
- try {
- return service.fetchRemoteUuidsWithAttribution(this, transport, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Perform a service discovery on the remote device to get the SDP records associated
- * with the specified UUID.
- *
- * <p>This API is asynchronous and {@link #ACTION_SDP_RECORD} intent is sent,
- * with the SDP records found on the remote end. If there is an error
- * in getting the SDP records or if the process takes a long time,
- * {@link #ACTION_SDP_RECORD} intent is sent with an status value in
- * {@link #EXTRA_SDP_SEARCH_STATUS} different from 0.
- * Detailed status error codes can be found by members of the Bluetooth package in
- * the AbstractionLayer class.
- * <p>The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}.
- * The object type will match one of the SdpXxxRecord types, depending on the UUID searched
- * for.
- *
- * @return False if the check fails, True if the process
- * of initiating an ACL connection to the remote device
- * was started.
- */
- /** @hide */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean sdpSearch(ParcelUuid uuid) {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot query remote device sdp records");
- return false;
- }
- try {
- return service.sdpSearch(this, uuid, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN}
- *
- * @return true pin has been set false for error
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setPin(byte[] pin) {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot set Remote Device pin");
- return false;
- }
- try {
- return service.setPin(this, true, pin.length, pin, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN}
- *
- * @return true pin has been set false for error
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setPin(@NonNull String pin) {
- byte[] pinBytes = convertPinToBytes(pin);
- if (pinBytes == null) {
- return false;
- }
- return setPin(pinBytes);
- }
-
- /**
- * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing.
- *
- * @return true confirmation has been sent out false for error
- */
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setPairingConfirmation(boolean confirm) {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot set pairing confirmation");
- return false;
- }
- try {
- return service.setPairingConfirmation(this, confirm, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Cancels pairing to this device
- *
- * @return true if pairing cancelled successfully, false otherwise
- *
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean cancelPairing() {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "BT not enabled. Cannot cancel pairing");
- return false;
- }
- try {
- return service.cancelBondProcess(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- boolean isBluetoothEnabled() {
- boolean ret = false;
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- if (adapter != null && adapter.isEnabled()) {
- ret = true;
- }
- return ret;
- }
-
- /**
- * Gets whether the phonebook access is allowed for this bluetooth device
- *
- * @return Whether the phonebook access is allowed to this device. Can be {@link
- * #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @AccessPermission int getPhonebookAccessPermission() {
- final IBluetooth service = sService;
- if (service == null) {
- return ACCESS_UNKNOWN;
- }
- try {
- return service.getPhonebookAccessPermission(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return ACCESS_UNKNOWN;
- }
-
- /**
- * Sets whether the {@link BluetoothDevice} enters silence mode. Audio will not
- * be routed to the {@link BluetoothDevice} if set to {@code true}.
- *
- * When the {@link BluetoothDevice} enters silence mode, and the {@link BluetoothDevice}
- * is an active device (for A2DP or HFP), the active device for that profile
- * will be set to null.
- * If the {@link BluetoothDevice} exits silence mode while the A2DP or HFP
- * active device is null, the {@link BluetoothDevice} will be set as the
- * active device for that profile.
- * If the {@link BluetoothDevice} is disconnected, it exits silence mode.
- * If the {@link BluetoothDevice} is set as the active device for A2DP or
- * HFP, while silence mode is enabled, then the device will exit silence mode.
- * If the {@link BluetoothDevice} is in silence mode, AVRCP position change
- * event and HFP AG indicators will be disabled.
- * If the {@link BluetoothDevice} is not connected with A2DP or HFP, it cannot
- * enter silence mode.
- *
- * @param silence true to enter silence mode, false to exit
- * @return true on success, false on error.
- * @throws IllegalStateException if Bluetooth is not turned ON.
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setSilenceMode(boolean silence) {
- final IBluetooth service = sService;
- if (service == null) {
- throw new IllegalStateException("Bluetooth is not turned ON");
- }
- try {
- return service.setSilenceMode(this, silence, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "setSilenceMode fail", e);
- return false;
- }
- }
-
- /**
- * Check whether the {@link BluetoothDevice} is in silence mode
- *
- * @return true on device in silence mode, otherwise false.
- * @throws IllegalStateException if Bluetooth is not turned ON.
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean isInSilenceMode() {
- final IBluetooth service = sService;
- if (service == null) {
- throw new IllegalStateException("Bluetooth is not turned ON");
- }
- try {
- return service.getSilenceMode(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "isInSilenceMode fail", e);
- return false;
- }
- }
-
- /**
- * Sets whether the phonebook access is allowed to this device.
- *
- * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
- * #ACCESS_REJECTED}.
- * @return Whether the value has been successfully set.
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setPhonebookAccessPermission(@AccessPermission int value) {
- final IBluetooth service = sService;
- if (service == null) {
- return false;
- }
- try {
- return service.setPhonebookAccessPermission(this, value, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Gets whether message access is allowed to this bluetooth device
- *
- * @return Whether the message access is allowed to this device.
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @AccessPermission int getMessageAccessPermission() {
- final IBluetooth service = sService;
- if (service == null) {
- return ACCESS_UNKNOWN;
- }
- try {
- return service.getMessageAccessPermission(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return ACCESS_UNKNOWN;
- }
-
- /**
- * Sets whether the message access is allowed to this device.
- *
- * @param value Can be {@link #ACCESS_UNKNOWN} if the device is unbonded,
- * {@link #ACCESS_ALLOWED} if the permission is being granted, or {@link #ACCESS_REJECTED} if
- * the permission is not being granted.
- * @return Whether the value has been successfully set.
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setMessageAccessPermission(@AccessPermission int value) {
- // Validates param value is one of the accepted constants
- if (value != ACCESS_ALLOWED && value != ACCESS_REJECTED && value != ACCESS_UNKNOWN) {
- throw new IllegalArgumentException(value + "is not a valid AccessPermission value");
- }
- final IBluetooth service = sService;
- if (service == null) {
- return false;
- }
- try {
- return service.setMessageAccessPermission(this, value, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Gets whether sim access is allowed for this bluetooth device
- *
- * @return Whether the Sim access is allowed to this device.
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @AccessPermission int getSimAccessPermission() {
- final IBluetooth service = sService;
- if (service == null) {
- return ACCESS_UNKNOWN;
- }
- try {
- return service.getSimAccessPermission(this, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return ACCESS_UNKNOWN;
- }
-
- /**
- * Sets whether the Sim access is allowed to this device.
- *
- * @param value Can be {@link #ACCESS_UNKNOWN} if the device is unbonded,
- * {@link #ACCESS_ALLOWED} if the permission is being granted, or {@link #ACCESS_REJECTED} if
- * the permission is not being granted.
- * @return Whether the value has been successfully set.
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setSimAccessPermission(int value) {
- final IBluetooth service = sService;
- if (service == null) {
- return false;
- }
- try {
- return service.setSimAccessPermission(this, value, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
- * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
- * outgoing connection to this remote device on given channel.
- * <p>The remote device will be authenticated and communication on this
- * socket will be encrypted.
- * <p> Use this socket only if an authenticated socket link is possible.
- * Authentication refers to the authentication of the link key to
- * prevent person-in-the-middle type of attacks.
- * For example, for Bluetooth 2.1 devices, if any of the devices does not
- * have an input and output capability or just has the ability to
- * display a numeric key, a secure socket connection is not possible.
- * In such a case, use {@link createInsecureRfcommSocket}.
- * For more details, refer to the Security Model section 5.2 (vol 3) of
- * Bluetooth Core Specification version 2.1 + EDR.
- * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
- * connection.
- * <p>Valid RFCOMM channels are in range 1 to 30.
- *
- * @param channel RFCOMM channel to connect to
- * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public BluetoothSocket createRfcommSocket(int channel) throws IOException {
- if (!isBluetoothEnabled()) {
- Log.e(TAG, "Bluetooth is not enabled");
- throw new IOException();
- }
- return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, channel,
- null);
- }
-
- /**
- * Create an L2cap {@link BluetoothSocket} ready to start a secure
- * outgoing connection to this remote device on given channel.
- * <p>The remote device will be authenticated and communication on this
- * socket will be encrypted.
- * <p> Use this socket only if an authenticated socket link is possible.
- * Authentication refers to the authentication of the link key to
- * prevent person-in-the-middle type of attacks.
- * For example, for Bluetooth 2.1 devices, if any of the devices does not
- * have an input and output capability or just has the ability to
- * display a numeric key, a secure socket connection is not possible.
- * In such a case, use {@link createInsecureRfcommSocket}.
- * For more details, refer to the Security Model section 5.2 (vol 3) of
- * Bluetooth Core Specification version 2.1 + EDR.
- * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
- * connection.
- * <p>Valid L2CAP PSM channels are in range 1 to 2^16.
- *
- * @param channel L2cap PSM/channel to connect to
- * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public BluetoothSocket createL2capSocket(int channel) throws IOException {
- return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, true, true, this, channel,
- null);
- }
-
- /**
- * Create an L2cap {@link BluetoothSocket} ready to start an insecure
- * outgoing connection to this remote device on given channel.
- * <p>The remote device will be not authenticated and communication on this
- * socket will not be encrypted.
- * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
- * connection.
- * <p>Valid L2CAP PSM channels are in range 1 to 2^16.
- *
- * @param channel L2cap PSM/channel to connect to
- * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public BluetoothSocket createInsecureL2capSocket(int channel) throws IOException {
- return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false, false, this, channel,
- null);
- }
-
- /**
- * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
- * outgoing connection to this remote device using SDP lookup of uuid.
- * <p>This is designed to be used with {@link
- * BluetoothAdapter#listenUsingRfcommWithServiceRecord} for peer-peer
- * Bluetooth applications.
- * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
- * connection. This will also perform an SDP lookup of the given uuid to
- * determine which channel to connect to.
- * <p>The remote device will be authenticated and communication on this
- * socket will be encrypted.
- * <p> Use this socket only if an authenticated socket link is possible.
- * Authentication refers to the authentication of the link key to
- * prevent person-in-the-middle type of attacks.
- * For example, for Bluetooth 2.1 devices, if any of the devices does not
- * have an input and output capability or just has the ability to
- * display a numeric key, a secure socket connection is not possible.
- * In such a case, use {@link #createInsecureRfcommSocketToServiceRecord}.
- * For more details, refer to the Security Model section 5.2 (vol 3) of
- * Bluetooth Core Specification version 2.1 + EDR.
- * <p>Hint: If you are connecting to a Bluetooth serial board then try
- * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB.
- * However if you are connecting to an Android peer then please generate
- * your own unique UUID.
- *
- * @param uuid service record uuid to lookup RFCOMM channel
- * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException {
- if (!isBluetoothEnabled()) {
- Log.e(TAG, "Bluetooth is not enabled");
- throw new IOException();
- }
-
- return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, -1,
- new ParcelUuid(uuid));
- }
-
- /**
- * Create an RFCOMM {@link BluetoothSocket} socket ready to start an insecure
- * outgoing connection to this remote device using SDP lookup of uuid.
- * <p> The communication channel will not have an authenticated link key
- * i.e it will be subject to person-in-the-middle attacks. For Bluetooth 2.1
- * devices, the link key will be encrypted, as encryption is mandatory.
- * For legacy devices (pre Bluetooth 2.1 devices) the link key will
- * be not be encrypted. Use {@link #createRfcommSocketToServiceRecord} if an
- * encrypted and authenticated communication channel is desired.
- * <p>This is designed to be used with {@link
- * BluetoothAdapter#listenUsingInsecureRfcommWithServiceRecord} for peer-peer
- * Bluetooth applications.
- * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
- * connection. This will also perform an SDP lookup of the given uuid to
- * determine which channel to connect to.
- * <p>The remote device will be authenticated and communication on this
- * socket will be encrypted.
- * <p>Hint: If you are connecting to a Bluetooth serial board then try
- * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB.
- * However if you are connecting to an Android peer then please generate
- * your own unique UUID.
- *
- * @param uuid service record uuid to lookup RFCOMM channel
- * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException {
- if (!isBluetoothEnabled()) {
- Log.e(TAG, "Bluetooth is not enabled");
- throw new IOException();
- }
- return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, -1,
- new ParcelUuid(uuid));
- }
-
- /**
- * Construct an insecure RFCOMM socket ready to start an outgoing
- * connection.
- * Call #connect on the returned #BluetoothSocket to begin the connection.
- * The remote device will not be authenticated and communication on this
- * socket will not be encrypted.
- *
- * @param port remote port
- * @return An RFCOMM BluetoothSocket
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * permissions.
- * @hide
- */
- @UnsupportedAppUsage(publicAlternatives = "Use "
- + "{@link #createInsecureRfcommSocketToServiceRecord} instead.")
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException {
- if (!isBluetoothEnabled()) {
- Log.e(TAG, "Bluetooth is not enabled");
- throw new IOException();
- }
- return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, port,
- null);
- }
-
- /**
- * Construct a SCO socket ready to start an outgoing connection.
- * Call #connect on the returned #BluetoothSocket to begin the connection.
- *
- * @return a SCO BluetoothSocket
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions.
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public BluetoothSocket createScoSocket() throws IOException {
- if (!isBluetoothEnabled()) {
- Log.e(TAG, "Bluetooth is not enabled");
- throw new IOException();
- }
- return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1, null);
- }
-
- /**
- * Check that a pin is valid and convert to byte array.
- *
- * Bluetooth pin's are 1 to 16 bytes of UTF-8 characters.
- *
- * @param pin pin as java String
- * @return the pin code as a UTF-8 byte array, or null if it is an invalid Bluetooth pin.
- * @hide
- */
- @UnsupportedAppUsage
- public static byte[] convertPinToBytes(String pin) {
- if (pin == null) {
- return null;
- }
- byte[] pinBytes;
- try {
- pinBytes = pin.getBytes("UTF-8");
- } catch (UnsupportedEncodingException uee) {
- Log.e(TAG, "UTF-8 not supported?!?"); // this should not happen
- return null;
- }
- if (pinBytes.length <= 0 || pinBytes.length > 16) {
- return null;
- }
- return pinBytes;
- }
-
- /**
- * Connect to GATT Server hosted by this device. Caller acts as GATT client.
- * The callback is used to deliver results to Caller, such as connection status as well
- * as any further GATT client operations.
- * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
- * GATT client operations.
- *
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @param autoConnect Whether to directly connect to the remote device (false) or to
- * automatically connect as soon as the remote device becomes available (true).
- * @throws IllegalArgumentException if callback is null
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothGatt connectGatt(Context context, boolean autoConnect,
- BluetoothGattCallback callback) {
- return (connectGatt(context, autoConnect, callback, TRANSPORT_AUTO));
- }
-
- /**
- * Connect to GATT Server hosted by this device. Caller acts as GATT client.
- * The callback is used to deliver results to Caller, such as connection status as well
- * as any further GATT client operations.
- * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
- * GATT client operations.
- *
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @param autoConnect Whether to directly connect to the remote device (false) or to
- * automatically connect as soon as the remote device becomes available (true).
- * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
- * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
- * BluetoothDevice#TRANSPORT_LE}
- * @throws IllegalArgumentException if callback is null
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothGatt connectGatt(Context context, boolean autoConnect,
- BluetoothGattCallback callback, int transport) {
- return (connectGatt(context, autoConnect, callback, transport, PHY_LE_1M_MASK));
- }
-
- /**
- * Connect to GATT Server hosted by this device. Caller acts as GATT client.
- * The callback is used to deliver results to Caller, such as connection status as well
- * as any further GATT client operations.
- * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
- * GATT client operations.
- *
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @param autoConnect Whether to directly connect to the remote device (false) or to
- * automatically connect as soon as the remote device becomes available (true).
- * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
- * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
- * BluetoothDevice#TRANSPORT_LE}
- * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
- * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
- * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
- * is set to true.
- * @throws NullPointerException if callback is null
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothGatt connectGatt(Context context, boolean autoConnect,
- BluetoothGattCallback callback, int transport, int phy) {
- return connectGatt(context, autoConnect, callback, transport, phy, null);
- }
-
- /**
- * Connect to GATT Server hosted by this device. Caller acts as GATT client.
- * The callback is used to deliver results to Caller, such as connection status as well
- * as any further GATT client operations.
- * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
- * GATT client operations.
- *
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @param autoConnect Whether to directly connect to the remote device (false) or to
- * automatically connect as soon as the remote device becomes available (true).
- * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
- * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
- * BluetoothDevice#TRANSPORT_LE}
- * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
- * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link
- * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
- * is set to true.
- * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on
- * an un-specified background thread.
- * @throws NullPointerException if callback is null
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothGatt connectGatt(Context context, boolean autoConnect,
- BluetoothGattCallback callback, int transport, int phy,
- Handler handler) {
- return connectGatt(context, autoConnect, callback, transport, false, phy, handler);
- }
-
- /**
- * Connect to GATT Server hosted by this device. Caller acts as GATT client.
- * The callback is used to deliver results to Caller, such as connection status as well
- * as any further GATT client operations.
- * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
- * GATT client operations.
- *
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @param autoConnect Whether to directly connect to the remote device (false) or to
- * automatically connect as soon as the remote device becomes available (true).
- * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
- * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
- * BluetoothDevice#TRANSPORT_LE}
- * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client
- * does not hold a GATT connection. It automatically disconnects when no other GATT connections
- * are active for the remote device.
- * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
- * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link
- * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
- * is set to true.
- * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on
- * an un-specified background thread.
- * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client
- * operations.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothGatt connectGatt(Context context, boolean autoConnect,
- BluetoothGattCallback callback, int transport,
- boolean opportunistic, int phy, Handler handler) {
- if (callback == null) {
- throw new NullPointerException("callback is null");
- }
-
- // TODO(Bluetooth) check whether platform support BLE
- // Do the check here or in GattServer?
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager managerService = adapter.getBluetoothManager();
- try {
- IBluetoothGatt iGatt = managerService.getBluetoothGatt();
- if (iGatt == null) {
- // BLE is not supported
- return null;
- }
- BluetoothGatt gatt = new BluetoothGatt(
- iGatt, this, transport, opportunistic, phy, mAttributionSource);
- gatt.connect(autoConnect, callback, handler);
- return gatt;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return null;
- }
-
- /**
- * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
- * be used to start a secure outgoing connection to the remote device with the same dynamic
- * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
- * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capChannel()} for
- * peer-peer Bluetooth applications.
- * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
- * <p>Application using this API is responsible for obtaining PSM value from remote device.
- * <p>The remote device will be authenticated and communication on this socket will be
- * encrypted.
- * <p> Use this socket if an authenticated socket link is possible. Authentication refers
- * to the authentication of the link key to prevent person-in-the-middle type of attacks.
- *
- * @param psm dynamic PSM value from remote device
- * @return a CoC #BluetoothSocket ready for an outgoing connection
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public @NonNull BluetoothSocket createL2capChannel(int psm) throws IOException {
- if (!isBluetoothEnabled()) {
- Log.e(TAG, "createL2capChannel: Bluetooth is not enabled");
- throw new IOException();
- }
- if (DBG) Log.d(TAG, "createL2capChannel: psm=" + psm);
- return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, true, true, this, psm,
- null);
- }
-
- /**
- * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
- * be used to start a secure outgoing connection to the remote device with the same dynamic
- * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
- * <p>This is designed to be used with {@link
- * BluetoothAdapter#listenUsingInsecureL2capChannel()} for peer-peer Bluetooth applications.
- * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
- * <p>Application using this API is responsible for obtaining PSM value from remote device.
- * <p> The communication channel may not have an authenticated link key, i.e. it may be subject
- * to person-in-the-middle attacks. Use {@link #createL2capChannel(int)} if an encrypted and
- * authenticated communication channel is possible.
- *
- * @param psm dynamic PSM value from remote device
- * @return a CoC #BluetoothSocket ready for an outgoing connection
- * @throws IOException on error, for example Bluetooth not available, or insufficient
- * permissions
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public @NonNull BluetoothSocket createInsecureL2capChannel(int psm) throws IOException {
- if (!isBluetoothEnabled()) {
- Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled");
- throw new IOException();
- }
- if (DBG) {
- Log.d(TAG, "createInsecureL2capChannel: psm=" + psm);
- }
- return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, false, false, this, psm,
- null);
- }
-
- /**
- * Set a keyed metadata of this {@link BluetoothDevice} to a
- * {@link String} value.
- * Only bonded devices's metadata will be persisted across Bluetooth
- * restart.
- * Metadata will be removed when the device's bond state is moved to
- * {@link #BOND_NONE}.
- *
- * @param key must be within the list of BluetoothDevice.METADATA_*
- * @param value a byte array data to set for key. Must be less than
- * {@link BluetoothAdapter#METADATA_MAX_LENGTH} characters in length
- * @return true on success, false on error
- * @hide
- */
- @SystemApi
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setMetadata(@MetadataKey int key, @NonNull byte[] value) {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "Bluetooth is not enabled. Cannot set metadata");
- return false;
- }
- if (value.length > METADATA_MAX_LENGTH) {
- throw new IllegalArgumentException("value length is " + value.length
- + ", should not over " + METADATA_MAX_LENGTH);
- }
- try {
- return service.setMetadata(this, key, value, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "setMetadata fail", e);
- return false;
- }
- }
-
- /**
- * Get a keyed metadata for this {@link BluetoothDevice} as {@link String}
- *
- * @param key must be within the list of BluetoothDevice.METADATA_*
- * @return Metadata of the key as byte array, null on error or not found
- * @hide
- */
- @SystemApi
- @Nullable
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public byte[] getMetadata(@MetadataKey int key) {
- final IBluetooth service = sService;
- if (service == null) {
- Log.e(TAG, "Bluetooth is not enabled. Cannot get metadata");
- return null;
- }
- try {
- return service.getMetadata(this, key, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "getMetadata fail", e);
- return null;
- }
- }
-
- /**
- * Get the maxinum metadata key ID.
- *
- * @return the last supported metadata key
- * @hide
- */
- public static @MetadataKey int getMaxMetadataKey() {
- return METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothDevicePicker.java b/core/java/android/bluetooth/BluetoothDevicePicker.java
deleted file mode 100644
index 26e4657..0000000
--- a/core/java/android/bluetooth/BluetoothDevicePicker.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2009 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.bluetooth;
-
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-
-/**
- * A helper to show a system "Device Picker" activity to the user.
- *
- * @hide
- */
-public interface BluetoothDevicePicker {
- public static final String EXTRA_NEED_AUTH =
- "android.bluetooth.devicepicker.extra.NEED_AUTH";
- public static final String EXTRA_FILTER_TYPE =
- "android.bluetooth.devicepicker.extra.FILTER_TYPE";
- public static final String EXTRA_LAUNCH_PACKAGE =
- "android.bluetooth.devicepicker.extra.LAUNCH_PACKAGE";
- public static final String EXTRA_LAUNCH_CLASS =
- "android.bluetooth.devicepicker.extra.DEVICE_PICKER_LAUNCH_CLASS";
-
- /**
- * Broadcast when one BT device is selected from BT device picker screen.
- * Selected {@link BluetoothDevice} is returned in extra data named
- * {@link BluetoothDevice#EXTRA_DEVICE}.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_DEVICE_SELECTED =
- "android.bluetooth.devicepicker.action.DEVICE_SELECTED";
-
- /**
- * Broadcast when someone want to select one BT device from devices list.
- * This intent contains below extra data:
- * - {@link #EXTRA_NEED_AUTH} (boolean): if need authentication
- * - {@link #EXTRA_FILTER_TYPE} (int): what kinds of device should be
- * listed
- * - {@link #EXTRA_LAUNCH_PACKAGE} (string): where(which package) this
- * intent come from
- * - {@link #EXTRA_LAUNCH_CLASS} (string): where(which class) this intent
- * come from
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_LAUNCH =
- "android.bluetooth.devicepicker.action.LAUNCH";
-
- /** Ask device picker to show all kinds of BT devices */
- public static final int FILTER_TYPE_ALL = 0;
- /** Ask device picker to show BT devices that support AUDIO profiles */
- public static final int FILTER_TYPE_AUDIO = 1;
- /** Ask device picker to show BT devices that support Object Transfer */
- public static final int FILTER_TYPE_TRANSFER = 2;
- /**
- * Ask device picker to show BT devices that support
- * Personal Area Networking User (PANU) profile
- */
- public static final int FILTER_TYPE_PANU = 3;
- /** Ask device picker to show BT devices that support Network Access Point (NAP) profile */
- public static final int FILTER_TYPE_NAP = 4;
-}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
deleted file mode 100644
index b531829..0000000
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ /dev/null
@@ -1,1848 +0,0 @@
-/*
- * Copyright (C) 2013 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.os.Build;
-import android.os.Handler;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Public API for the Bluetooth GATT Profile.
- *
- * <p>This class provides Bluetooth GATT functionality to enable communication
- * with Bluetooth Smart or Smart Ready devices.
- *
- * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
- * and call {@link BluetoothDevice#connectGatt} to get a instance of this class.
- * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
- * scan process.
- */
-public final class BluetoothGatt implements BluetoothProfile {
- private static final String TAG = "BluetoothGatt";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- @UnsupportedAppUsage
- private IBluetoothGatt mService;
- @UnsupportedAppUsage
- private volatile BluetoothGattCallback mCallback;
- private Handler mHandler;
- @UnsupportedAppUsage
- private int mClientIf;
- private BluetoothDevice mDevice;
- @UnsupportedAppUsage
- private boolean mAutoConnect;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
- private int mAuthRetryState;
- private int mConnState;
- private final Object mStateLock = new Object();
- private final Object mDeviceBusyLock = new Object();
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private Boolean mDeviceBusy = false;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private int mTransport;
- private int mPhy;
- private boolean mOpportunistic;
- private final AttributionSource mAttributionSource;
-
- private static final int AUTH_RETRY_STATE_IDLE = 0;
- private static final int AUTH_RETRY_STATE_NO_MITM = 1;
- private static final int AUTH_RETRY_STATE_MITM = 2;
-
- private static final int CONN_STATE_IDLE = 0;
- private static final int CONN_STATE_CONNECTING = 1;
- private static final int CONN_STATE_CONNECTED = 2;
- private static final int CONN_STATE_DISCONNECTING = 3;
- private static final int CONN_STATE_CLOSED = 4;
-
- private static final int WRITE_CHARACTERISTIC_MAX_RETRIES = 5;
- private static final int WRITE_CHARACTERISTIC_TIME_TO_WAIT = 10; // milliseconds
-
- private List<BluetoothGattService> mServices;
-
- /** A GATT operation completed successfully */
- public static final int GATT_SUCCESS = 0;
-
- /** GATT read operation is not permitted */
- public static final int GATT_READ_NOT_PERMITTED = 0x2;
-
- /** GATT write operation is not permitted */
- public static final int GATT_WRITE_NOT_PERMITTED = 0x3;
-
- /** Insufficient authentication for a given operation */
- public static final int GATT_INSUFFICIENT_AUTHENTICATION = 0x5;
-
- /** The given request is not supported */
- public static final int GATT_REQUEST_NOT_SUPPORTED = 0x6;
-
- /** Insufficient encryption for a given operation */
- public static final int GATT_INSUFFICIENT_ENCRYPTION = 0xf;
-
- /** A read or write operation was requested with an invalid offset */
- public static final int GATT_INVALID_OFFSET = 0x7;
-
- /** Insufficient authorization for a given operation */
- public static final int GATT_INSUFFICIENT_AUTHORIZATION = 0x8;
-
- /** A write operation exceeds the maximum length of the attribute */
- public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd;
-
- /** A remote device connection is congested. */
- public static final int GATT_CONNECTION_CONGESTED = 0x8f;
-
- /** A GATT operation failed, errors other than the above */
- public static final int GATT_FAILURE = 0x101;
-
- /**
- * Connection parameter update - Use the connection parameters recommended by the
- * Bluetooth SIG. This is the default value if no connection parameter update
- * is requested.
- */
- public static final int CONNECTION_PRIORITY_BALANCED = 0;
-
- /**
- * Connection parameter update - Request a high priority, low latency connection.
- * An application should only request high priority connection parameters to transfer large
- * amounts of data over LE quickly. Once the transfer is complete, the application should
- * request {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED} connection parameters to reduce
- * energy use.
- */
- public static final int CONNECTION_PRIORITY_HIGH = 1;
-
- /** Connection parameter update - Request low power, reduced data rate connection parameters. */
- public static final int CONNECTION_PRIORITY_LOW_POWER = 2;
-
- /**
- * No authentication required.
- *
- * @hide
- */
- /*package*/ static final int AUTHENTICATION_NONE = 0;
-
- /**
- * Authentication requested; no person-in-the-middle protection required.
- *
- * @hide
- */
- /*package*/ static final int AUTHENTICATION_NO_MITM = 1;
-
- /**
- * Authentication with person-in-the-middle protection requested.
- *
- * @hide
- */
- /*package*/ static final int AUTHENTICATION_MITM = 2;
-
- /**
- * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation.
- */
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private final IBluetoothGattCallback mBluetoothGattCallback =
- new IBluetoothGattCallback.Stub() {
- /**
- * Application interface registered - app is ready to go
- * @hide
- */
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public void onClientRegistered(int status, int clientIf) {
- if (DBG) {
- Log.d(TAG, "onClientRegistered() - status=" + status
- + " clientIf=" + clientIf);
- }
- if (VDBG) {
- synchronized (mStateLock) {
- if (mConnState != CONN_STATE_CONNECTING) {
- Log.e(TAG, "Bad connection state: " + mConnState);
- }
- }
- }
- mClientIf = clientIf;
- if (status != GATT_SUCCESS) {
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onConnectionStateChange(BluetoothGatt.this,
- GATT_FAILURE,
- BluetoothProfile.STATE_DISCONNECTED);
- }
- }
- });
-
- synchronized (mStateLock) {
- mConnState = CONN_STATE_IDLE;
- }
- return;
- }
- try {
- mService.clientConnect(mClientIf, mDevice.getAddress(),
- !mAutoConnect, mTransport, mOpportunistic,
- mPhy, mAttributionSource); // autoConnect is inverse of "isDirect"
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * Phy update callback
- * @hide
- */
- @Override
- public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) {
- if (DBG) {
- Log.d(TAG, "onPhyUpdate() - status=" + status
- + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy);
- }
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
- }
- }
- });
- }
-
- /**
- * Phy read callback
- * @hide
- */
- @Override
- public void onPhyRead(String address, int txPhy, int rxPhy, int status) {
- if (DBG) {
- Log.d(TAG, "onPhyRead() - status=" + status
- + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy);
- }
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
- }
- }
- });
- }
-
- /**
- * Client connection state changed
- * @hide
- */
- @Override
- public void onClientConnectionState(int status, int clientIf,
- boolean connected, String address) {
- if (DBG) {
- Log.d(TAG, "onClientConnectionState() - status=" + status
- + " clientIf=" + clientIf + " device=" + address);
- }
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
- int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
- BluetoothProfile.STATE_DISCONNECTED;
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onConnectionStateChange(BluetoothGatt.this, status,
- profileState);
- }
- }
- });
-
- synchronized (mStateLock) {
- if (connected) {
- mConnState = CONN_STATE_CONNECTED;
- } else {
- mConnState = CONN_STATE_IDLE;
- }
- }
-
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
- }
-
- /**
- * Remote search has been completed.
- * The internal object structure should now reflect the state
- * of the remote device database. Let the application know that
- * we are done at this point.
- * @hide
- */
- @Override
- public void onSearchComplete(String address, List<BluetoothGattService> services,
- int status) {
- if (DBG) {
- Log.d(TAG,
- "onSearchComplete() = Device=" + address + " Status=" + status);
- }
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- for (BluetoothGattService s : services) {
- //services we receive don't have device set properly.
- s.setDevice(mDevice);
- }
-
- mServices.addAll(services);
-
- // Fix references to included services, as they doesn't point to right objects.
- for (BluetoothGattService fixedService : mServices) {
- ArrayList<BluetoothGattService> includedServices =
- new ArrayList(fixedService.getIncludedServices());
- fixedService.getIncludedServices().clear();
-
- for (BluetoothGattService brokenRef : includedServices) {
- BluetoothGattService includedService = getService(mDevice,
- brokenRef.getUuid(), brokenRef.getInstanceId());
- if (includedService != null) {
- fixedService.addIncludedService(includedService);
- } else {
- Log.e(TAG, "Broken GATT database: can't find included service.");
- }
- }
- }
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onServicesDiscovered(BluetoothGatt.this, status);
- }
- }
- });
- }
-
- /**
- * Remote characteristic has been read.
- * Updates the internal value.
- * @hide
- */
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public void onCharacteristicRead(String address, int status, int handle,
- byte[] value) {
- if (VDBG) {
- Log.d(TAG, "onCharacteristicRead() - Device=" + address
- + " handle=" + handle + " Status=" + status);
- }
-
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
-
- if ((status == GATT_INSUFFICIENT_AUTHENTICATION
- || status == GATT_INSUFFICIENT_ENCRYPTION)
- && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
- try {
- final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
- ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
- mService.readCharacteristic(
- mClientIf, address, handle, authReq, mAttributionSource);
- mAuthRetryState++;
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-
- BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice,
- handle);
- if (characteristic == null) {
- Log.w(TAG, "onCharacteristicRead() failed to find characteristic!");
- return;
- }
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- if (status == 0) characteristic.setValue(value);
- callback.onCharacteristicRead(BluetoothGatt.this, characteristic,
- value, status);
- // Keep calling deprecated callback to maintain app compatibility
- callback.onCharacteristicRead(BluetoothGatt.this, characteristic,
- status);
- }
- }
- });
- }
-
- /**
- * Characteristic has been written to the remote device.
- * Let the app know how we did...
- * @hide
- */
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public void onCharacteristicWrite(String address, int status, int handle,
- byte[] value) {
- if (VDBG) {
- Log.d(TAG, "onCharacteristicWrite() - Device=" + address
- + " handle=" + handle + " Status=" + status);
- }
-
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
-
- BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice,
- handle);
- if (characteristic == null) return;
-
- if ((status == GATT_INSUFFICIENT_AUTHENTICATION
- || status == GATT_INSUFFICIENT_ENCRYPTION)
- && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
- try {
- final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
- ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
- int requestStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
- for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
- requestStatus = mService.writeCharacteristic(mClientIf, address,
- handle, characteristic.getWriteType(), authReq,
- value, mAttributionSource);
- if (requestStatus
- != BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY) {
- break;
- }
- try {
- Thread.sleep(WRITE_CHARACTERISTIC_TIME_TO_WAIT);
- } catch (InterruptedException e) {
- }
- }
- mAuthRetryState++;
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- mAuthRetryState = AUTH_RETRY_STATE_IDLE;
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onCharacteristicWrite(BluetoothGatt.this, characteristic,
- status);
- }
- }
- });
- }
-
- /**
- * Remote characteristic has been updated.
- * Updates the internal value.
- * @hide
- */
- @Override
- public void onNotify(String address, int handle, byte[] value) {
- if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle);
-
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice,
- handle);
- if (characteristic == null) return;
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- characteristic.setValue(value);
- callback.onCharacteristicChanged(BluetoothGatt.this,
- characteristic, value);
- // Keep calling deprecated callback to maintain app compatibility
- callback.onCharacteristicChanged(BluetoothGatt.this,
- characteristic);
- }
- }
- });
- }
-
- /**
- * Descriptor has been read.
- * @hide
- */
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public void onDescriptorRead(String address, int status, int handle, byte[] value) {
- if (VDBG) {
- Log.d(TAG,
- "onDescriptorRead() - Device=" + address + " handle=" + handle);
- }
-
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
-
- BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle);
- if (descriptor == null) return;
-
-
- if ((status == GATT_INSUFFICIENT_AUTHENTICATION
- || status == GATT_INSUFFICIENT_ENCRYPTION)
- && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
- try {
- final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
- ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
- mService.readDescriptor(
- mClientIf, address, handle, authReq, mAttributionSource);
- mAuthRetryState++;
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- if (status == 0) descriptor.setValue(value);
- callback.onDescriptorRead(BluetoothGatt.this, descriptor, status,
- value);
- // Keep calling deprecated callback to maintain app compatibility
- callback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
- }
- }
- });
- }
-
- /**
- * Descriptor write operation complete.
- * @hide
- */
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public void onDescriptorWrite(String address, int status, int handle,
- byte[] value) {
- if (VDBG) {
- Log.d(TAG,
- "onDescriptorWrite() - Device=" + address + " handle=" + handle);
- }
-
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
-
- BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle);
- if (descriptor == null) return;
-
- if ((status == GATT_INSUFFICIENT_AUTHENTICATION
- || status == GATT_INSUFFICIENT_ENCRYPTION)
- && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
- try {
- final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
- ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
- mService.writeDescriptor(mClientIf, address, handle,
- authReq, value, mAttributionSource);
- mAuthRetryState++;
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
- }
- }
- });
- }
-
- /**
- * Prepared write transaction completed (or aborted)
- * @hide
- */
- @Override
- public void onExecuteWrite(String address, int status) {
- if (VDBG) {
- Log.d(TAG, "onExecuteWrite() - Device=" + address
- + " status=" + status);
- }
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onReliableWriteCompleted(BluetoothGatt.this, status);
- }
- }
- });
- }
-
- /**
- * Remote device RSSI has been read
- * @hide
- */
- @Override
- public void onReadRemoteRssi(String address, int rssi, int status) {
- if (VDBG) {
- Log.d(TAG, "onReadRemoteRssi() - Device=" + address
- + " rssi=" + rssi + " status=" + status);
- }
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
- }
- }
- });
- }
-
- /**
- * Callback invoked when the MTU for a given connection changes
- * @hide
- */
- @Override
- public void onConfigureMTU(String address, int mtu, int status) {
- if (DBG) {
- Log.d(TAG, "onConfigureMTU() - Device=" + address
- + " mtu=" + mtu + " status=" + status);
- }
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onMtuChanged(BluetoothGatt.this, mtu, status);
- }
- }
- });
- }
-
- /**
- * Callback invoked when the given connection is updated
- * @hide
- */
- @Override
- public void onConnectionUpdated(String address, int interval, int latency,
- int timeout, int status) {
- if (DBG) {
- Log.d(TAG, "onConnectionUpdated() - Device=" + address
- + " interval=" + interval + " latency=" + latency
- + " timeout=" + timeout + " status=" + status);
- }
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
- timeout, status);
- }
- }
- });
- }
-
- /**
- * Callback invoked when service changed event is received
- * @hide
- */
- @Override
- public void onServiceChanged(String address) {
- if (DBG) {
- Log.d(TAG, "onServiceChanged() - Device=" + address);
- }
-
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
-
- runOrQueueCallback(new Runnable() {
- @Override
- public void run() {
- final BluetoothGattCallback callback = mCallback;
- if (callback != null) {
- callback.onServiceChanged(BluetoothGatt.this);
- }
- }
- });
- }
- };
-
- /* package */ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device, int transport,
- boolean opportunistic, int phy, AttributionSource attributionSource) {
- mService = iGatt;
- mDevice = device;
- mTransport = transport;
- mPhy = phy;
- mOpportunistic = opportunistic;
- mAttributionSource = attributionSource;
- mServices = new ArrayList<BluetoothGattService>();
-
- mConnState = CONN_STATE_IDLE;
- mAuthRetryState = AUTH_RETRY_STATE_IDLE;
- }
-
- /**
- * Close this Bluetooth GATT client.
- *
- * Application should call this method as early as possible after it is done with
- * this GATT client.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void close() {
- if (DBG) Log.d(TAG, "close()");
-
- unregisterApp();
- mConnState = CONN_STATE_CLOSED;
- mAuthRetryState = AUTH_RETRY_STATE_IDLE;
- }
-
- /**
- * Returns a service by UUID, instance and type.
- *
- * @hide
- */
- /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid,
- int instanceId) {
- for (BluetoothGattService svc : mServices) {
- if (svc.getDevice().equals(device)
- && svc.getInstanceId() == instanceId
- && svc.getUuid().equals(uuid)) {
- return svc;
- }
- }
- return null;
- }
-
-
- /**
- * Returns a characteristic with id equal to instanceId.
- *
- * @hide
- */
- /*package*/ BluetoothGattCharacteristic getCharacteristicById(BluetoothDevice device,
- int instanceId) {
- for (BluetoothGattService svc : mServices) {
- for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
- if (charac.getInstanceId() == instanceId) {
- return charac;
- }
- }
- }
- return null;
- }
-
- /**
- * Returns a descriptor with id equal to instanceId.
- *
- * @hide
- */
- /*package*/ BluetoothGattDescriptor getDescriptorById(BluetoothDevice device, int instanceId) {
- for (BluetoothGattService svc : mServices) {
- for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
- for (BluetoothGattDescriptor desc : charac.getDescriptors()) {
- if (desc.getInstanceId() == instanceId) {
- return desc;
- }
- }
- }
- }
- return null;
- }
-
- /**
- * Queue the runnable on a {@link Handler} provided by the user, or execute the runnable
- * immediately if no Handler was provided.
- */
- private void runOrQueueCallback(final Runnable cb) {
- if (mHandler == null) {
- try {
- cb.run();
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
- } else {
- mHandler.post(cb);
- }
- }
-
- /**
- * Register an application callback to start using GATT.
- *
- * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
- * is used to notify success or failure if the function returns true.
- *
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @return If true, the callback will be called to notify success or failure, false on immediate
- * error
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private boolean registerApp(BluetoothGattCallback callback, Handler handler) {
- return registerApp(callback, handler, false);
- }
-
- /**
- * Register an application callback to start using GATT.
- *
- * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
- * is used to notify success or failure if the function returns true.
- *
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @param eatt_support indicate to allow for eatt support
- * @return If true, the callback will be called to notify success or failure, false on immediate
- * error
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private boolean registerApp(BluetoothGattCallback callback, Handler handler,
- boolean eatt_support) {
- if (DBG) Log.d(TAG, "registerApp()");
- if (mService == null) return false;
-
- mCallback = callback;
- mHandler = handler;
- UUID uuid = UUID.randomUUID();
- if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
-
- try {
- mService.registerClient(
- new ParcelUuid(uuid), mBluetoothGattCallback, eatt_support, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Unregister the current application and callbacks.
- */
- @UnsupportedAppUsage
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private void unregisterApp() {
- if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
- if (mService == null || mClientIf == 0) return;
-
- try {
- mCallback = null;
- mService.unregisterClient(mClientIf, mAttributionSource);
- mClientIf = 0;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * Initiate a connection to a Bluetooth GATT capable device.
- *
- * <p>The connection may not be established right away, but will be
- * completed when the remote device is available. A
- * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
- * invoked when the connection state changes as a result of this function.
- *
- * <p>The autoConnect parameter determines whether to actively connect to
- * the remote device, or rather passively scan and finalize the connection
- * when the remote device is in range/available. Generally, the first ever
- * connection to a device should be direct (autoConnect set to false) and
- * subsequent connections to known devices should be invoked with the
- * autoConnect parameter set to true.
- *
- * @param device Remote device to connect to
- * @param autoConnect Whether to directly connect to the remote device (false) or to
- * automatically connect as soon as the remote device becomes available (true).
- * @return true, if the connection attempt was initiated successfully
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
- Handler handler) {
- if (DBG) {
- Log.d(TAG,
- "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
- }
- synchronized (mStateLock) {
- if (mConnState != CONN_STATE_IDLE) {
- throw new IllegalStateException("Not idle");
- }
- mConnState = CONN_STATE_CONNECTING;
- }
-
- mAutoConnect = autoConnect;
-
- if (!registerApp(callback, handler)) {
- synchronized (mStateLock) {
- mConnState = CONN_STATE_IDLE;
- }
- Log.e(TAG, "Failed to register callback");
- return false;
- }
-
- // The connection will continue in the onClientRegistered callback
- return true;
- }
-
- /**
- * Disconnects an established connection, or cancels a connection attempt
- * currently in progress.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void disconnect() {
- if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
- if (mService == null || mClientIf == 0) return;
-
- try {
- mService.clientDisconnect(mClientIf, mDevice.getAddress(), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * Connect back to remote device.
- *
- * <p>This method is used to re-connect to a remote device after the
- * connection has been dropped. If the device is not in range, the
- * re-connection will be triggered once the device is back in range.
- *
- * @return true, if the connection attempt was initiated successfully
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean connect() {
- try {
- // autoConnect is inverse of "isDirect"
- mService.clientConnect(mClientIf, mDevice.getAddress(), false, mTransport,
- mOpportunistic, mPhy, mAttributionSource);
- return true;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
- }
-
- /**
- * Set the preferred connection PHY for this app. Please note that this is just a
- * recommendation, whether the PHY change will happen depends on other applications preferences,
- * local and remote controller capabilities. Controller can override these settings.
- * <p>
- * {@link BluetoothGattCallback#onPhyUpdate} will be triggered as a result of this call, even
- * if no PHY change happens. It is also triggered when remote device updates the PHY.
- *
- * @param txPhy preferred transmitter PHY. Bitwise OR of any of {@link
- * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
- * BluetoothDevice#PHY_LE_CODED_MASK}.
- * @param rxPhy preferred receiver PHY. Bitwise OR of any of {@link
- * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
- * BluetoothDevice#PHY_LE_CODED_MASK}.
- * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
- * of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, {@link BluetoothDevice#PHY_OPTION_S2} or
- * {@link BluetoothDevice#PHY_OPTION_S8}
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void setPreferredPhy(int txPhy, int rxPhy, int phyOptions) {
- try {
- mService.clientSetPreferredPhy(mClientIf, mDevice.getAddress(), txPhy, rxPhy,
- phyOptions, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * Read the current transmitter PHY and receiver PHY of the connection. The values are returned
- * in {@link BluetoothGattCallback#onPhyRead}
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void readPhy() {
- try {
- mService.clientReadPhy(mClientIf, mDevice.getAddress(), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * Return the remote bluetooth device this GATT client targets to
- *
- * @return remote bluetooth device
- */
- @RequiresNoPermission
- public BluetoothDevice getDevice() {
- return mDevice;
- }
-
- /**
- * Discovers services offered by a remote device as well as their
- * characteristics and descriptors.
- *
- * <p>This is an asynchronous operation. Once service discovery is completed,
- * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
- * triggered. If the discovery was successful, the remote services can be
- * retrieved using the {@link #getServices} function.
- *
- * @return true, if the remote service discovery has been started
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean discoverServices() {
- if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
- if (mService == null || mClientIf == 0) return false;
-
- mServices.clear();
-
- try {
- mService.discoverServices(mClientIf, mDevice.getAddress(), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Discovers a service by UUID. This is exposed only for passing PTS tests.
- * It should never be used by real applications. The service is not searched
- * for characteristics and descriptors, or returned in any callback.
- *
- * @return true, if the remote service discovery has been started
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean discoverServiceByUuid(UUID uuid) {
- if (DBG) Log.d(TAG, "discoverServiceByUuid() - device: " + mDevice.getAddress());
- if (mService == null || mClientIf == 0) return false;
-
- mServices.clear();
-
- try {
- mService.discoverServiceByUuid(
- mClientIf, mDevice.getAddress(), new ParcelUuid(uuid), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
- return true;
- }
-
- /**
- * Returns a list of GATT services offered by the remote device.
- *
- * <p>This function requires that service discovery has been completed
- * for the given device.
- *
- * @return List of services on the remote device. Returns an empty list if service discovery has
- * not yet been performed.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public List<BluetoothGattService> getServices() {
- List<BluetoothGattService> result =
- new ArrayList<BluetoothGattService>();
-
- for (BluetoothGattService service : mServices) {
- if (service.getDevice().equals(mDevice)) {
- result.add(service);
- }
- }
-
- return result;
- }
-
- /**
- * Returns a {@link BluetoothGattService}, if the requested UUID is
- * supported by the remote device.
- *
- * <p>This function requires that service discovery has been completed
- * for the given device.
- *
- * <p>If multiple instances of the same service (as identified by UUID)
- * exist, the first instance of the service is returned.
- *
- * @param uuid UUID of the requested service
- * @return BluetoothGattService if supported, or null if the requested service is not offered by
- * the remote device.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public BluetoothGattService getService(UUID uuid) {
- for (BluetoothGattService service : mServices) {
- if (service.getDevice().equals(mDevice) && service.getUuid().equals(uuid)) {
- return service;
- }
- }
-
- return null;
- }
-
- /**
- * Reads the requested characteristic from the associated remote device.
- *
- * <p>This is an asynchronous operation. The result of the read operation
- * is reported by the {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
- * BluetoothGattCharacteristic, byte[], int)} callback.
- *
- * @param characteristic Characteristic to read from the remote device
- * @return true, if the read operation was initiated successfully
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
- if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) == 0) {
- return false;
- }
-
- if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
- if (mService == null || mClientIf == 0) return false;
-
- BluetoothGattService service = characteristic.getService();
- if (service == null) return false;
-
- BluetoothDevice device = service.getDevice();
- if (device == null) return false;
-
- synchronized (mDeviceBusyLock) {
- if (mDeviceBusy) return false;
- mDeviceBusy = true;
- }
-
- try {
- mService.readCharacteristic(mClientIf, device.getAddress(),
- characteristic.getInstanceId(), AUTHENTICATION_NONE, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
- return false;
- }
-
- return true;
- }
-
- /**
- * Reads the characteristic using its UUID from the associated remote device.
- *
- * <p>This is an asynchronous operation. The result of the read operation
- * is reported by the {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
- * BluetoothGattCharacteristic, byte[], int)} callback.
- *
- * @param uuid UUID of characteristic to read from the remote device
- * @return true, if the read operation was initiated successfully
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean readUsingCharacteristicUuid(UUID uuid, int startHandle, int endHandle) {
- if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - uuid: " + uuid);
- if (mService == null || mClientIf == 0) return false;
-
- synchronized (mDeviceBusyLock) {
- if (mDeviceBusy) return false;
- mDeviceBusy = true;
- }
-
- try {
- mService.readUsingCharacteristicUuid(mClientIf, mDevice.getAddress(),
- new ParcelUuid(uuid), startHandle, endHandle, AUTHENTICATION_NONE,
- mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
- return false;
- }
-
- return true;
- }
-
-
- /**
- * Writes a given characteristic and its values to the associated remote device.
- *
- * <p>Once the write operation has been completed, the
- * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
- * reporting the result of the operation.
- *
- * @param characteristic Characteristic to write on the remote device
- * @return true, if the write operation was initiated successfully
- * @throws IllegalArgumentException if characteristic or its value are null
- *
- * @deprecated Use {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[],
- * int)} as this is not memory safe.
- */
- @Deprecated
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
- try {
- return writeCharacteristic(characteristic, characteristic.getValue(),
- characteristic.getWriteType()) == BluetoothStatusCodes.SUCCESS;
- } catch (Exception e) {
- return false;
- }
- }
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- BluetoothStatusCodes.SUCCESS,
- BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
- BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION,
- BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED,
- BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
- BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED,
- BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY,
- BluetoothStatusCodes.ERROR_UNKNOWN
- })
- public @interface WriteOperationReturnValues{}
-
- /**
- * Writes a given characteristic and its values to the associated remote device.
- *
- * <p>Once the write operation has been completed, the
- * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
- * reporting the result of the operation.
- *
- * @param characteristic Characteristic to write on the remote device
- * @return whether the characteristic was successfully written to
- * @throws IllegalArgumentException if characteristic or value are null
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @WriteOperationReturnValues
- public int writeCharacteristic(@NonNull BluetoothGattCharacteristic characteristic,
- @NonNull byte[] value, int writeType) {
- if (characteristic == null) {
- throw new IllegalArgumentException("characteristic must not be null");
- }
- if (value == null) {
- throw new IllegalArgumentException("value must not be null");
- }
- if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
- if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
- && (characteristic.getProperties()
- & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) {
- return BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED;
- }
- if (mService == null || mClientIf == 0) {
- return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
- }
-
- BluetoothGattService service = characteristic.getService();
- if (service == null) {
- throw new IllegalArgumentException("Characteristic must have a non-null service");
- }
-
- BluetoothDevice device = service.getDevice();
- if (device == null) {
- throw new IllegalArgumentException("Service must have a non-null device");
- }
-
- synchronized (mDeviceBusyLock) {
- if (mDeviceBusy) {
- return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
- }
- mDeviceBusy = true;
- }
-
- int requestStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
- try {
- for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
- requestStatus = mService.writeCharacteristic(mClientIf, device.getAddress(),
- characteristic.getInstanceId(), writeType, AUTHENTICATION_NONE, value,
- mAttributionSource);
- if (requestStatus != BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY) {
- break;
- }
- try {
- Thread.sleep(WRITE_CHARACTERISTIC_TIME_TO_WAIT);
- } catch (InterruptedException e) {
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
- throw e.rethrowFromSystemServer();
- }
-
- return requestStatus;
- }
-
- /**
- * Reads the value for a given descriptor from the associated remote device.
- *
- * <p>Once the read operation has been completed, the
- * {@link BluetoothGattCallback#onDescriptorRead} callback is
- * triggered, signaling the result of the operation.
- *
- * @param descriptor Descriptor value to read from the remote device
- * @return true, if the read operation was initiated successfully
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
- if (VDBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid());
- if (mService == null || mClientIf == 0) return false;
-
- BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
- if (characteristic == null) return false;
-
- BluetoothGattService service = characteristic.getService();
- if (service == null) return false;
-
- BluetoothDevice device = service.getDevice();
- if (device == null) return false;
-
- synchronized (mDeviceBusyLock) {
- if (mDeviceBusy) return false;
- mDeviceBusy = true;
- }
-
- try {
- mService.readDescriptor(mClientIf, device.getAddress(),
- descriptor.getInstanceId(), AUTHENTICATION_NONE, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
- return false;
- }
-
- return true;
- }
-
- /**
- * Write the value of a given descriptor to the associated remote device.
- *
- * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is triggered to report the
- * result of the write operation.
- *
- * @param descriptor Descriptor to write to the associated remote device
- * @return true, if the write operation was initiated successfully
- * @throws IllegalArgumentException if descriptor or its value are null
- *
- * @deprecated Use {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])} as
- * this is not memory safe.
- */
- @Deprecated
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
- try {
- return writeDescriptor(descriptor, descriptor.getValue())
- == BluetoothStatusCodes.SUCCESS;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * Write the value of a given descriptor to the associated remote device.
- *
- * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is triggered to report the
- * result of the write operation.
- *
- * @param descriptor Descriptor to write to the associated remote device
- * @return true, if the write operation was initiated successfully
- * @throws IllegalArgumentException if descriptor or value are null
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @WriteOperationReturnValues
- public int writeDescriptor(@NonNull BluetoothGattDescriptor descriptor,
- @NonNull byte[] value) {
- if (descriptor == null) {
- throw new IllegalArgumentException("descriptor must not be null");
- }
- if (value == null) {
- throw new IllegalArgumentException("value must not be null");
- }
- if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
- if (mService == null || mClientIf == 0) {
- return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
- }
-
- BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
- if (characteristic == null) {
- throw new IllegalArgumentException("Descriptor must have a non-null characteristic");
- }
-
- BluetoothGattService service = characteristic.getService();
- if (service == null) {
- throw new IllegalArgumentException("Characteristic must have a non-null service");
- }
-
- BluetoothDevice device = service.getDevice();
- if (device == null) {
- throw new IllegalArgumentException("Service must have a non-null device");
- }
-
- synchronized (mDeviceBusyLock) {
- if (mDeviceBusy) return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
- mDeviceBusy = true;
- }
-
- try {
- return mService.writeDescriptor(mClientIf, device.getAddress(),
- descriptor.getInstanceId(), AUTHENTICATION_NONE, value, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
- e.rethrowFromSystemServer();
- }
- return BluetoothStatusCodes.ERROR_UNKNOWN;
- }
-
- /**
- * Initiates a reliable write transaction for a given remote device.
- *
- * <p>Once a reliable write transaction has been initiated, all calls
- * to {@link #writeCharacteristic} are sent to the remote device for
- * verification and queued up for atomic execution. The application will
- * receive a {@link BluetoothGattCallback#onCharacteristicWrite} callback in response to every
- * {@link #writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} call and is
- * responsible for verifying if the value has been transmitted accurately.
- *
- * <p>After all characteristics have been queued up and verified,
- * {@link #executeReliableWrite} will execute all writes. If a characteristic
- * was not written correctly, calling {@link #abortReliableWrite} will
- * cancel the current transaction without committing any values on the
- * remote device.
- *
- * @return true, if the reliable write transaction has been initiated
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean beginReliableWrite() {
- if (VDBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
- if (mService == null || mClientIf == 0) return false;
-
- try {
- mService.beginReliableWrite(mClientIf, mDevice.getAddress(), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Executes a reliable write transaction for a given remote device.
- *
- * <p>This function will commit all queued up characteristic write
- * operations for a given remote device.
- *
- * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
- * invoked to indicate whether the transaction has been executed correctly.
- *
- * @return true, if the request to execute the transaction has been sent
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean executeReliableWrite() {
- if (VDBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
- if (mService == null || mClientIf == 0) return false;
-
- synchronized (mDeviceBusyLock) {
- if (mDeviceBusy) return false;
- mDeviceBusy = true;
- }
-
- try {
- mService.endReliableWrite(mClientIf, mDevice.getAddress(), true, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- synchronized (mDeviceBusyLock) {
- mDeviceBusy = false;
- }
- return false;
- }
-
- return true;
- }
-
- /**
- * Cancels a reliable write transaction for a given device.
- *
- * <p>Calling this function will discard all queued characteristic write
- * operations for a given remote device.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void abortReliableWrite() {
- if (VDBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
- if (mService == null || mClientIf == 0) return;
-
- try {
- mService.endReliableWrite(mClientIf, mDevice.getAddress(), false, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * @deprecated Use {@link #abortReliableWrite()}
- */
- @Deprecated
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void abortReliableWrite(BluetoothDevice mDevice) {
- abortReliableWrite();
- }
-
- /**
- * Enable or disable notifications/indications for a given characteristic.
- *
- * <p>Once notifications are enabled for a characteristic, a
- * {@link BluetoothGattCallback#onCharacteristicChanged(BluetoothGatt,
- * BluetoothGattCharacteristic, byte[])} callback will be triggered if the remote device
- * indicates that the given characteristic has changed.
- *
- * @param characteristic The characteristic for which to enable notifications
- * @param enable Set to true to enable notifications/indications
- * @return true, if the requested notification status was set successfully
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
- boolean enable) {
- if (DBG) {
- Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid()
- + " enable: " + enable);
- }
- if (mService == null || mClientIf == 0) return false;
-
- BluetoothGattService service = characteristic.getService();
- if (service == null) return false;
-
- BluetoothDevice device = service.getDevice();
- if (device == null) return false;
-
- try {
- mService.registerForNotification(mClientIf, device.getAddress(),
- characteristic.getInstanceId(), enable, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Clears the internal cache and forces a refresh of the services from the
- * remote device.
- *
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean refresh() {
- if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
- if (mService == null || mClientIf == 0) return false;
-
- try {
- mService.refreshDevice(mClientIf, mDevice.getAddress(), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Read the RSSI for a connected remote device.
- *
- * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
- * invoked when the RSSI value has been read.
- *
- * @return true, if the RSSI value has been requested successfully
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean readRemoteRssi() {
- if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
- if (mService == null || mClientIf == 0) return false;
-
- try {
- mService.readRemoteRssi(mClientIf, mDevice.getAddress(), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Request an MTU size used for a given connection.
- *
- * <p>When performing a write request operation (write without response),
- * the data sent is truncated to the MTU size. This function may be used
- * to request a larger MTU size to be able to send more data at once.
- *
- * <p>A {@link BluetoothGattCallback#onMtuChanged} callback will indicate
- * whether this operation was successful.
- *
- * @return true, if the new MTU value has been requested successfully
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean requestMtu(int mtu) {
- if (DBG) {
- Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress()
- + " mtu: " + mtu);
- }
- if (mService == null || mClientIf == 0) return false;
-
- try {
- mService.configureMTU(mClientIf, mDevice.getAddress(), mtu, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Request a connection parameter update.
- *
- * <p>This function will send a connection parameter update request to the
- * remote device.
- *
- * @param connectionPriority Request a specific connection priority. Must be one of {@link
- * BluetoothGatt#CONNECTION_PRIORITY_BALANCED}, {@link BluetoothGatt#CONNECTION_PRIORITY_HIGH}
- * or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}.
- * @throws IllegalArgumentException If the parameters are outside of their specified range.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean requestConnectionPriority(int connectionPriority) {
- if (connectionPriority < CONNECTION_PRIORITY_BALANCED
- || connectionPriority > CONNECTION_PRIORITY_LOW_POWER) {
- throw new IllegalArgumentException("connectionPriority not within valid range");
- }
-
- if (DBG) Log.d(TAG, "requestConnectionPriority() - params: " + connectionPriority);
- if (mService == null || mClientIf == 0) return false;
-
- try {
- mService.connectionParameterUpdate(
- mClientIf, mDevice.getAddress(), connectionPriority, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Request an LE connection parameter update.
- *
- * <p>This function will send an LE connection parameters update request to the remote device.
- *
- * @return true, if the request is send to the Bluetooth stack.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean requestLeConnectionUpdate(int minConnectionInterval, int maxConnectionInterval,
- int slaveLatency, int supervisionTimeout,
- int minConnectionEventLen, int maxConnectionEventLen) {
- if (DBG) {
- Log.d(TAG, "requestLeConnectionUpdate() - min=(" + minConnectionInterval
- + ")" + (1.25 * minConnectionInterval)
- + "msec, max=(" + maxConnectionInterval + ")"
- + (1.25 * maxConnectionInterval) + "msec, latency=" + slaveLatency
- + ", timeout=" + supervisionTimeout + "msec" + ", min_ce="
- + minConnectionEventLen + ", max_ce=" + maxConnectionEventLen);
- }
- if (mService == null || mClientIf == 0) return false;
-
- try {
- mService.leConnectionUpdate(mClientIf, mDevice.getAddress(),
- minConnectionInterval, maxConnectionInterval,
- slaveLatency, supervisionTimeout,
- minConnectionEventLen, maxConnectionEventLen,
- mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * @deprecated Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
- * with {@link BluetoothProfile#GATT} as argument
- * @throws UnsupportedOperationException
- */
- @Override
- @RequiresNoPermission
- @Deprecated
- public int getConnectionState(BluetoothDevice device) {
- throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
- }
-
- /**
- * @deprecated Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
- * with {@link BluetoothProfile#GATT} as argument
- *
- * @throws UnsupportedOperationException
- */
- @Override
- @RequiresNoPermission
- @Deprecated
- public List<BluetoothDevice> getConnectedDevices() {
- throw new UnsupportedOperationException(
- "Use BluetoothManager#getConnectedDevices instead.");
- }
-
- /**
- * @deprecated Not supported - please use
- * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
- * with {@link BluetoothProfile#GATT} as first argument
- *
- * @throws UnsupportedOperationException
- */
- @Override
- @RequiresNoPermission
- @Deprecated
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- throw new UnsupportedOperationException(
- "Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
deleted file mode 100644
index d0a5a1e..0000000
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.NonNull;
-
-/**
- * This abstract class is used to implement {@link BluetoothGatt} callbacks.
- */
-public abstract class BluetoothGattCallback {
-
- /**
- * Callback triggered as result of {@link BluetoothGatt#setPreferredPhy}, or as a result of
- * remote device changing the PHY.
- *
- * @param gatt GATT client
- * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
- * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
- * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
- * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
- * @param status Status of the PHY update operation. {@link BluetoothGatt#GATT_SUCCESS} if the
- * operation succeeds.
- */
- public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
- }
-
- /**
- * Callback triggered as result of {@link BluetoothGatt#readPhy}
- *
- * @param gatt GATT client
- * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
- * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
- * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
- * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
- * @param status Status of the PHY read operation. {@link BluetoothGatt#GATT_SUCCESS} if the
- * operation succeeds.
- */
- public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
- }
-
- /**
- * Callback indicating when GATT client has connected/disconnected to/from a remote
- * GATT server.
- *
- * @param gatt GATT client
- * @param status Status of the connect or disconnect operation. {@link
- * BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
- * @param newState Returns the new connection state. Can be one of {@link
- * BluetoothProfile#STATE_DISCONNECTED} or {@link BluetoothProfile#STATE_CONNECTED}
- */
- public void onConnectionStateChange(BluetoothGatt gatt, int status,
- int newState) {
- }
-
- /**
- * Callback invoked when the list of remote services, characteristics and descriptors
- * for the remote device have been updated, ie new services have been discovered.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#discoverServices}
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device has been explored
- * successfully.
- */
- public void onServicesDiscovered(BluetoothGatt gatt, int status) {
- }
-
- /**
- * Callback reporting the result of a characteristic read operation.
- *
- * @param gatt GATT client invoked
- * {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)}
- * @param characteristic Characteristic that was read from the associated remote device.
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
- * successfully.
- * @deprecated Use {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
- * BluetoothGattCharacteristic, byte[], int)} as it is memory safe
- */
- @Deprecated
- public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
- int status) {
- }
-
- /**
- * Callback reporting the result of a characteristic read operation.
- *
- * @param gatt GATT client invoked
- * {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)}
- * @param characteristic Characteristic that was read from the associated remote device.
- * @param value the value of the characteristic
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
- * successfully.
- */
- public void onCharacteristicRead(@NonNull BluetoothGatt gatt, @NonNull
- BluetoothGattCharacteristic characteristic, @NonNull byte[] value, int status) {
- }
-
- /**
- * Callback indicating the result of a characteristic write operation.
- *
- * <p>If this callback is invoked while a reliable write transaction is
- * in progress, the value of the characteristic represents the value
- * reported by the remote device. An application should compare this
- * value to the desired value to be written. If the values don't match,
- * the application must abort the reliable write transaction.
- *
- * @param gatt GATT client that invoked
- * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic,
- * byte[], int)}
- * @param characteristic Characteristic that was written to the associated remote device.
- * @param status The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if
- * the
- * operation succeeds.
- */
- public void onCharacteristicWrite(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic, int status) {
- }
-
- /**
- * Callback triggered as a result of a remote characteristic notification.
- *
- * @param gatt GATT client the characteristic is associated with
- * @param characteristic Characteristic that has been updated as a result of a remote
- * notification event.
- * @deprecated Use {@link BluetoothGattCallback#onCharacteristicChanged(BluetoothGatt,
- * BluetoothGattCharacteristic, byte[])} as it is memory safe by providing the characteristic
- * value at the time of notification.
- */
- @Deprecated
- public void onCharacteristicChanged(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic) {
- }
-
- /**
- * Callback triggered as a result of a remote characteristic notification. Note that the value
- * within the characteristic object may have changed since receiving the remote characteristic
- * notification, so check the parameter value for the value at the time of notification.
- *
- * @param gatt GATT client the characteristic is associated with
- * @param characteristic Characteristic that has been updated as a result of a remote
- * notification event.
- * @param value notified characteristic value
- */
- public void onCharacteristicChanged(@NonNull BluetoothGatt gatt,
- @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) {
- }
-
- /**
- * Callback reporting the result of a descriptor read operation.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
- * @param descriptor Descriptor that was read from the associated remote device.
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
- * successfully
- * @deprecated Use {@link BluetoothGattCallback#onDescriptorRead(BluetoothGatt,
- * BluetoothGattDescriptor, int, byte[])} as it is memory safe by providing the descriptor
- * value at the time it was read.
- */
- @Deprecated
- public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
- int status) {
- }
-
- /**
- * Callback reporting the result of a descriptor read operation.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
- * @param descriptor Descriptor that was read from the associated remote device.
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
- * successfully
- * @param value the descriptor value at the time of the read operation
- */
- public void onDescriptorRead(@NonNull BluetoothGatt gatt,
- @NonNull BluetoothGattDescriptor descriptor, int status, @NonNull byte[] value) {
- }
-
- /**
- * Callback indicating the result of a descriptor write operation.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor}
- * @param descriptor Descriptor that was writte to the associated remote device.
- * @param status The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if the
- * operation succeeds.
- */
- public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
- int status) {
- }
-
- /**
- * Callback invoked when a reliable write transaction has been completed.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#executeReliableWrite}
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the reliable write transaction was
- * executed successfully
- */
- public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
- }
-
- /**
- * Callback reporting the RSSI for a remote device connection.
- *
- * This callback is triggered in response to the
- * {@link BluetoothGatt#readRemoteRssi} function.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#readRemoteRssi}
- * @param rssi The RSSI value for the remote device
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the RSSI was read successfully
- */
- public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
- }
-
- /**
- * Callback indicating the MTU for a given device connection has changed.
- *
- * This callback is triggered in response to the
- * {@link BluetoothGatt#requestMtu} function, or in response to a connection
- * event.
- *
- * @param gatt GATT client invoked {@link BluetoothGatt#requestMtu}
- * @param mtu The new MTU size
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
- */
- public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
- }
-
- /**
- * Callback indicating the connection parameters were updated.
- *
- * @param gatt GATT client involved
- * @param interval Connection interval used on this connection, 1.25ms unit. Valid range is from
- * 6 (7.5ms) to 3200 (4000ms).
- * @param latency Worker latency for the connection in number of connection events. Valid range
- * is from 0 to 499
- * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is from 10
- * (0.1s) to 3200 (32s)
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated
- * successfully
- * @hide
- */
- public void onConnectionUpdated(BluetoothGatt gatt, int interval, int latency, int timeout,
- int status) {
- }
-
- /**
- * Callback indicating service changed event is received
- *
- * <p>Receiving this event means that the GATT database is out of sync with
- * the remote device. {@link BluetoothGatt#discoverServices} should be
- * called to re-discover the services.
- *
- * @param gatt GATT client involved
- */
- public void onServiceChanged(@NonNull BluetoothGatt gatt) {
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
deleted file mode 100644
index c5e986e..0000000
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ /dev/null
@@ -1,806 +0,0 @@
-/*
- * Copyright (C) 2013 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.bluetooth;
-
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Represents a Bluetooth GATT Characteristic
- *
- * <p>A GATT characteristic is a basic data element used to construct a GATT service,
- * {@link BluetoothGattService}. The characteristic contains a value as well as
- * additional information and optional GATT descriptors, {@link BluetoothGattDescriptor}.
- */
-public class BluetoothGattCharacteristic implements Parcelable {
-
- /**
- * Characteristic proprty: Characteristic is broadcastable.
- */
- public static final int PROPERTY_BROADCAST = 0x01;
-
- /**
- * Characteristic property: Characteristic is readable.
- */
- public static final int PROPERTY_READ = 0x02;
-
- /**
- * Characteristic property: Characteristic can be written without response.
- */
- public static final int PROPERTY_WRITE_NO_RESPONSE = 0x04;
-
- /**
- * Characteristic property: Characteristic can be written.
- */
- public static final int PROPERTY_WRITE = 0x08;
-
- /**
- * Characteristic property: Characteristic supports notification
- */
- public static final int PROPERTY_NOTIFY = 0x10;
-
- /**
- * Characteristic property: Characteristic supports indication
- */
- public static final int PROPERTY_INDICATE = 0x20;
-
- /**
- * Characteristic property: Characteristic supports write with signature
- */
- public static final int PROPERTY_SIGNED_WRITE = 0x40;
-
- /**
- * Characteristic property: Characteristic has extended properties
- */
- public static final int PROPERTY_EXTENDED_PROPS = 0x80;
-
- /**
- * Characteristic read permission
- */
- public static final int PERMISSION_READ = 0x01;
-
- /**
- * Characteristic permission: Allow encrypted read operations
- */
- public static final int PERMISSION_READ_ENCRYPTED = 0x02;
-
- /**
- * Characteristic permission: Allow reading with person-in-the-middle protection
- */
- public static final int PERMISSION_READ_ENCRYPTED_MITM = 0x04;
-
- /**
- * Characteristic write permission
- */
- public static final int PERMISSION_WRITE = 0x10;
-
- /**
- * Characteristic permission: Allow encrypted writes
- */
- public static final int PERMISSION_WRITE_ENCRYPTED = 0x20;
-
- /**
- * Characteristic permission: Allow encrypted writes with person-in-the-middle
- * protection
- */
- public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 0x40;
-
- /**
- * Characteristic permission: Allow signed write operations
- */
- public static final int PERMISSION_WRITE_SIGNED = 0x80;
-
- /**
- * Characteristic permission: Allow signed write operations with
- * person-in-the-middle protection
- */
- public static final int PERMISSION_WRITE_SIGNED_MITM = 0x100;
-
- /**
- * Write characteristic, requesting acknoledgement by the remote device
- */
- public static final int WRITE_TYPE_DEFAULT = 0x02;
-
- /**
- * Write characteristic without requiring a response by the remote device
- */
- public static final int WRITE_TYPE_NO_RESPONSE = 0x01;
-
- /**
- * Write characteristic including authentication signature
- */
- public static final int WRITE_TYPE_SIGNED = 0x04;
-
- /**
- * Characteristic value format type uint8
- */
- public static final int FORMAT_UINT8 = 0x11;
-
- /**
- * Characteristic value format type uint16
- */
- public static final int FORMAT_UINT16 = 0x12;
-
- /**
- * Characteristic value format type uint32
- */
- public static final int FORMAT_UINT32 = 0x14;
-
- /**
- * Characteristic value format type sint8
- */
- public static final int FORMAT_SINT8 = 0x21;
-
- /**
- * Characteristic value format type sint16
- */
- public static final int FORMAT_SINT16 = 0x22;
-
- /**
- * Characteristic value format type sint32
- */
- public static final int FORMAT_SINT32 = 0x24;
-
- /**
- * Characteristic value format type sfloat (16-bit float)
- */
- public static final int FORMAT_SFLOAT = 0x32;
-
- /**
- * Characteristic value format type float (32-bit float)
- */
- public static final int FORMAT_FLOAT = 0x34;
-
-
- /**
- * The UUID of this characteristic.
- *
- * @hide
- */
- protected UUID mUuid;
-
- /**
- * Instance ID for this characteristic.
- *
- * @hide
- */
- @UnsupportedAppUsage
- protected int mInstance;
-
- /**
- * Characteristic properties.
- *
- * @hide
- */
- protected int mProperties;
-
- /**
- * Characteristic permissions.
- *
- * @hide
- */
- protected int mPermissions;
-
- /**
- * Key size (default = 16).
- *
- * @hide
- */
- protected int mKeySize = 16;
-
- /**
- * Write type for this characteristic.
- * See WRITE_TYPE_* constants.
- *
- * @hide
- */
- protected int mWriteType;
-
- /**
- * Back-reference to the service this characteristic belongs to.
- *
- * @hide
- */
- @UnsupportedAppUsage
- protected BluetoothGattService mService;
-
- /**
- * The cached value of this characteristic.
- *
- * @hide
- */
- protected byte[] mValue;
-
- /**
- * List of descriptors included in this characteristic.
- */
- protected List<BluetoothGattDescriptor> mDescriptors;
-
- /**
- * Create a new BluetoothGattCharacteristic.
- *
- * @param uuid The UUID for this characteristic
- * @param properties Properties of this characteristic
- * @param permissions Permissions for this characteristic
- */
- public BluetoothGattCharacteristic(UUID uuid, int properties, int permissions) {
- initCharacteristic(null, uuid, 0, properties, permissions);
- }
-
- /**
- * Create a new BluetoothGattCharacteristic
- *
- * @hide
- */
- /*package*/ BluetoothGattCharacteristic(BluetoothGattService service,
- UUID uuid, int instanceId,
- int properties, int permissions) {
- initCharacteristic(service, uuid, instanceId, properties, permissions);
- }
-
- /**
- * Create a new BluetoothGattCharacteristic
- *
- * @hide
- */
- public BluetoothGattCharacteristic(UUID uuid, int instanceId,
- int properties, int permissions) {
- initCharacteristic(null, uuid, instanceId, properties, permissions);
- }
-
- private void initCharacteristic(BluetoothGattService service,
- UUID uuid, int instanceId,
- int properties, int permissions) {
- mUuid = uuid;
- mInstance = instanceId;
- mProperties = properties;
- mPermissions = permissions;
- mService = service;
- mValue = null;
- mDescriptors = new ArrayList<BluetoothGattDescriptor>();
-
- if ((mProperties & PROPERTY_WRITE_NO_RESPONSE) != 0) {
- mWriteType = WRITE_TYPE_NO_RESPONSE;
- } else {
- mWriteType = WRITE_TYPE_DEFAULT;
- }
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(new ParcelUuid(mUuid), 0);
- out.writeInt(mInstance);
- out.writeInt(mProperties);
- out.writeInt(mPermissions);
- out.writeInt(mKeySize);
- out.writeInt(mWriteType);
- out.writeTypedList(mDescriptors);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothGattCharacteristic> CREATOR =
- new Parcelable.Creator<BluetoothGattCharacteristic>() {
- public BluetoothGattCharacteristic createFromParcel(Parcel in) {
- return new BluetoothGattCharacteristic(in);
- }
-
- public BluetoothGattCharacteristic[] newArray(int size) {
- return new BluetoothGattCharacteristic[size];
- }
- };
-
- private BluetoothGattCharacteristic(Parcel in) {
- mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
- mInstance = in.readInt();
- mProperties = in.readInt();
- mPermissions = in.readInt();
- mKeySize = in.readInt();
- mWriteType = in.readInt();
-
- mDescriptors = new ArrayList<BluetoothGattDescriptor>();
-
- ArrayList<BluetoothGattDescriptor> descs =
- in.createTypedArrayList(BluetoothGattDescriptor.CREATOR);
- if (descs != null) {
- for (BluetoothGattDescriptor desc : descs) {
- desc.setCharacteristic(this);
- mDescriptors.add(desc);
- }
- }
- }
-
- /**
- * Returns the desired key size.
- *
- * @hide
- */
- public int getKeySize() {
- return mKeySize;
- }
-
- /**
- * Adds a descriptor to this characteristic.
- *
- * @param descriptor Descriptor to be added to this characteristic.
- * @return true, if the descriptor was added to the characteristic
- */
- public boolean addDescriptor(BluetoothGattDescriptor descriptor) {
- mDescriptors.add(descriptor);
- descriptor.setCharacteristic(this);
- return true;
- }
-
- /**
- * Get a descriptor by UUID and isntance id.
- *
- * @hide
- */
- /*package*/ BluetoothGattDescriptor getDescriptor(UUID uuid, int instanceId) {
- for (BluetoothGattDescriptor descriptor : mDescriptors) {
- if (descriptor.getUuid().equals(uuid)
- && descriptor.getInstanceId() == instanceId) {
- return descriptor;
- }
- }
- return null;
- }
-
- /**
- * Returns the service this characteristic belongs to.
- *
- * @return The asscociated service
- */
- public BluetoothGattService getService() {
- return mService;
- }
-
- /**
- * Sets the service associated with this device.
- *
- * @hide
- */
- @UnsupportedAppUsage
- /*package*/ void setService(BluetoothGattService service) {
- mService = service;
- }
-
- /**
- * Returns the UUID of this characteristic
- *
- * @return UUID of this characteristic
- */
- public UUID getUuid() {
- return mUuid;
- }
-
- /**
- * Returns the instance ID for this characteristic.
- *
- * <p>If a remote device offers multiple characteristics with the same UUID,
- * the instance ID is used to distuinguish between characteristics.
- *
- * @return Instance ID of this characteristic
- */
- public int getInstanceId() {
- return mInstance;
- }
-
- /**
- * Force the instance ID.
- *
- * @hide
- */
- public void setInstanceId(int instanceId) {
- mInstance = instanceId;
- }
-
- /**
- * Returns the properties of this characteristic.
- *
- * <p>The properties contain a bit mask of property flags indicating
- * the features of this characteristic.
- *
- * @return Properties of this characteristic
- */
- public int getProperties() {
- return mProperties;
- }
-
- /**
- * Returns the permissions for this characteristic.
- *
- * @return Permissions of this characteristic
- */
- public int getPermissions() {
- return mPermissions;
- }
-
- /**
- * Gets the write type for this characteristic.
- *
- * @return Write type for this characteristic
- */
- public int getWriteType() {
- return mWriteType;
- }
-
- /**
- * Set the write type for this characteristic
- *
- * <p>Setting the write type of a characteristic determines how the
- * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} function
- * write this characteristic.
- *
- * @param writeType The write type to for this characteristic. Can be one of: {@link
- * #WRITE_TYPE_DEFAULT}, {@link #WRITE_TYPE_NO_RESPONSE} or {@link #WRITE_TYPE_SIGNED}.
- */
- public void setWriteType(int writeType) {
- mWriteType = writeType;
- }
-
- /**
- * Set the desired key size.
- *
- * @hide
- */
- @UnsupportedAppUsage
- public void setKeySize(int keySize) {
- mKeySize = keySize;
- }
-
- /**
- * Returns a list of descriptors for this characteristic.
- *
- * @return Descriptors for this characteristic
- */
- public List<BluetoothGattDescriptor> getDescriptors() {
- return mDescriptors;
- }
-
- /**
- * Returns a descriptor with a given UUID out of the list of
- * descriptors for this characteristic.
- *
- * @return GATT descriptor object or null if no descriptor with the given UUID was found.
- */
- public BluetoothGattDescriptor getDescriptor(UUID uuid) {
- for (BluetoothGattDescriptor descriptor : mDescriptors) {
- if (descriptor.getUuid().equals(uuid)) {
- return descriptor;
- }
- }
- return null;
- }
-
- /**
- * Get the stored value for this characteristic.
- *
- * <p>This function returns the stored value for this characteristic as
- * retrieved by calling {@link BluetoothGatt#readCharacteristic}. The cached
- * value of the characteristic is updated as a result of a read characteristic
- * operation or if a characteristic update notification has been received.
- *
- * @return Cached value of the characteristic
- *
- * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} instead
- */
- @Deprecated
- public byte[] getValue() {
- return mValue;
- }
-
- /**
- * Return the stored value of this characteristic.
- *
- * <p>The formatType parameter determines how the characteristic value
- * is to be interpreted. For example, settting formatType to
- * {@link #FORMAT_UINT16} specifies that the first two bytes of the
- * characteristic value at the given offset are interpreted to generate the
- * return value.
- *
- * @param formatType The format type used to interpret the characteristic value.
- * @param offset Offset at which the integer value can be found.
- * @return Cached value of the characteristic or null of offset exceeds value size.
- *
- * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
- * the characteristic value
- */
- @Deprecated
- public Integer getIntValue(int formatType, int offset) {
- if ((offset + getTypeLen(formatType)) > mValue.length) return null;
-
- switch (formatType) {
- case FORMAT_UINT8:
- return unsignedByteToInt(mValue[offset]);
-
- case FORMAT_UINT16:
- return unsignedBytesToInt(mValue[offset], mValue[offset + 1]);
-
- case FORMAT_UINT32:
- return unsignedBytesToInt(mValue[offset], mValue[offset + 1],
- mValue[offset + 2], mValue[offset + 3]);
- case FORMAT_SINT8:
- return unsignedToSigned(unsignedByteToInt(mValue[offset]), 8);
-
- case FORMAT_SINT16:
- return unsignedToSigned(unsignedBytesToInt(mValue[offset],
- mValue[offset + 1]), 16);
-
- case FORMAT_SINT32:
- return unsignedToSigned(unsignedBytesToInt(mValue[offset],
- mValue[offset + 1], mValue[offset + 2], mValue[offset + 3]), 32);
- }
-
- return null;
- }
-
- /**
- * Return the stored value of this characteristic.
- * <p>See {@link #getValue} for details.
- *
- * @param formatType The format type used to interpret the characteristic value.
- * @param offset Offset at which the float value can be found.
- * @return Cached value of the characteristic at a given offset or null if the requested offset
- * exceeds the value size.
- *
- * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
- * the characteristic value
- */
- @Deprecated
- public Float getFloatValue(int formatType, int offset) {
- if ((offset + getTypeLen(formatType)) > mValue.length) return null;
-
- switch (formatType) {
- case FORMAT_SFLOAT:
- return bytesToFloat(mValue[offset], mValue[offset + 1]);
-
- case FORMAT_FLOAT:
- return bytesToFloat(mValue[offset], mValue[offset + 1],
- mValue[offset + 2], mValue[offset + 3]);
- }
-
- return null;
- }
-
- /**
- * Return the stored value of this characteristic.
- * <p>See {@link #getValue} for details.
- *
- * @param offset Offset at which the string value can be found.
- * @return Cached value of the characteristic
- *
- * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
- * the characteristic value
- */
- @Deprecated
- public String getStringValue(int offset) {
- if (mValue == null || offset > mValue.length) return null;
- byte[] strBytes = new byte[mValue.length - offset];
- for (int i = 0; i != (mValue.length - offset); ++i) strBytes[i] = mValue[offset + i];
- return new String(strBytes);
- }
-
- /**
- * Updates the locally stored value of this characteristic.
- *
- * <p>This function modifies the locally stored cached value of this
- * characteristic. To send the value to the remote device, call
- * {@link BluetoothGatt#writeCharacteristic} to send the value to the
- * remote device.
- *
- * @param value New value for this characteristic
- * @return true if the locally stored value has been set, false if the requested value could not
- * be stored locally.
- *
- * @deprecated Pass the characteristic value directly into
- * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
- */
- @Deprecated
- public boolean setValue(byte[] value) {
- mValue = value;
- return true;
- }
-
- /**
- * Set the locally stored value of this characteristic.
- * <p>See {@link #setValue(byte[])} for details.
- *
- * @param value New value for this characteristic
- * @param formatType Integer format type used to transform the value parameter
- * @param offset Offset at which the value should be placed
- * @return true if the locally stored value has been set
- *
- * @deprecated Pass the characteristic value directly into
- * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
- */
- @Deprecated
- public boolean setValue(int value, int formatType, int offset) {
- int len = offset + getTypeLen(formatType);
- if (mValue == null) mValue = new byte[len];
- if (len > mValue.length) return false;
-
- switch (formatType) {
- case FORMAT_SINT8:
- value = intToSignedBits(value, 8);
- // Fall-through intended
- case FORMAT_UINT8:
- mValue[offset] = (byte) (value & 0xFF);
- break;
-
- case FORMAT_SINT16:
- value = intToSignedBits(value, 16);
- // Fall-through intended
- case FORMAT_UINT16:
- mValue[offset++] = (byte) (value & 0xFF);
- mValue[offset] = (byte) ((value >> 8) & 0xFF);
- break;
-
- case FORMAT_SINT32:
- value = intToSignedBits(value, 32);
- // Fall-through intended
- case FORMAT_UINT32:
- mValue[offset++] = (byte) (value & 0xFF);
- mValue[offset++] = (byte) ((value >> 8) & 0xFF);
- mValue[offset++] = (byte) ((value >> 16) & 0xFF);
- mValue[offset] = (byte) ((value >> 24) & 0xFF);
- break;
-
- default:
- return false;
- }
- return true;
- }
-
- /**
- * Set the locally stored value of this characteristic.
- * <p>See {@link #setValue(byte[])} for details.
- *
- * @param mantissa Mantissa for this characteristic
- * @param exponent exponent value for this characteristic
- * @param formatType Float format type used to transform the value parameter
- * @param offset Offset at which the value should be placed
- * @return true if the locally stored value has been set
- *
- * @deprecated Pass the characteristic value directly into
- * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
- */
- @Deprecated
- public boolean setValue(int mantissa, int exponent, int formatType, int offset) {
- int len = offset + getTypeLen(formatType);
- if (mValue == null) mValue = new byte[len];
- if (len > mValue.length) return false;
-
- switch (formatType) {
- case FORMAT_SFLOAT:
- mantissa = intToSignedBits(mantissa, 12);
- exponent = intToSignedBits(exponent, 4);
- mValue[offset++] = (byte) (mantissa & 0xFF);
- mValue[offset] = (byte) ((mantissa >> 8) & 0x0F);
- mValue[offset] += (byte) ((exponent & 0x0F) << 4);
- break;
-
- case FORMAT_FLOAT:
- mantissa = intToSignedBits(mantissa, 24);
- exponent = intToSignedBits(exponent, 8);
- mValue[offset++] = (byte) (mantissa & 0xFF);
- mValue[offset++] = (byte) ((mantissa >> 8) & 0xFF);
- mValue[offset++] = (byte) ((mantissa >> 16) & 0xFF);
- mValue[offset] += (byte) (exponent & 0xFF);
- break;
-
- default:
- return false;
- }
-
- return true;
- }
-
- /**
- * Set the locally stored value of this characteristic.
- * <p>See {@link #setValue(byte[])} for details.
- *
- * @param value New value for this characteristic
- * @return true if the locally stored value has been set
- *
- * @deprecated Pass the characteristic value directly into
- * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
- */
- @Deprecated
- public boolean setValue(String value) {
- mValue = value.getBytes();
- return true;
- }
-
- /**
- * Returns the size of a give value type.
- */
- private int getTypeLen(int formatType) {
- return formatType & 0xF;
- }
-
- /**
- * Convert a signed byte to an unsigned int.
- */
- private int unsignedByteToInt(byte b) {
- return b & 0xFF;
- }
-
- /**
- * Convert signed bytes to a 16-bit unsigned int.
- */
- private int unsignedBytesToInt(byte b0, byte b1) {
- return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8));
- }
-
- /**
- * Convert signed bytes to a 32-bit unsigned int.
- */
- private int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) {
- return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8))
- + (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24);
- }
-
- /**
- * Convert signed bytes to a 16-bit short float value.
- */
- private float bytesToFloat(byte b0, byte b1) {
- int mantissa = unsignedToSigned(unsignedByteToInt(b0)
- + ((unsignedByteToInt(b1) & 0x0F) << 8), 12);
- int exponent = unsignedToSigned(unsignedByteToInt(b1) >> 4, 4);
- return (float) (mantissa * Math.pow(10, exponent));
- }
-
- /**
- * Convert signed bytes to a 32-bit short float value.
- */
- private float bytesToFloat(byte b0, byte b1, byte b2, byte b3) {
- int mantissa = unsignedToSigned(unsignedByteToInt(b0)
- + (unsignedByteToInt(b1) << 8)
- + (unsignedByteToInt(b2) << 16), 24);
- return (float) (mantissa * Math.pow(10, b3));
- }
-
- /**
- * Convert an unsigned integer value to a two's-complement encoded
- * signed value.
- */
- private int unsignedToSigned(int unsigned, int size) {
- if ((unsigned & (1 << size - 1)) != 0) {
- unsigned = -1 * ((1 << size - 1) - (unsigned & ((1 << size - 1) - 1)));
- }
- return unsigned;
- }
-
- /**
- * Convert an integer into the signed bits of a given length.
- */
- private int intToSignedBits(int i, int size) {
- if (i < 0) {
- i = (1 << size - 1) + (i & ((1 << size - 1) - 1));
- }
- return i;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
deleted file mode 100644
index a35d5b9..0000000
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) 2013 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.bluetooth;
-
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-
-import java.util.UUID;
-
-/**
- * Represents a Bluetooth GATT Descriptor
- *
- * <p> GATT Descriptors contain additional information and attributes of a GATT
- * characteristic, {@link BluetoothGattCharacteristic}. They can be used to describe
- * the characteristic's features or to control certain behaviours of the characteristic.
- */
-public class BluetoothGattDescriptor implements Parcelable {
-
- /**
- * Value used to enable notification for a client configuration descriptor
- */
- public static final byte[] ENABLE_NOTIFICATION_VALUE = {0x01, 0x00};
-
- /**
- * Value used to enable indication for a client configuration descriptor
- */
- public static final byte[] ENABLE_INDICATION_VALUE = {0x02, 0x00};
-
- /**
- * Value used to disable notifications or indicatinos
- */
- public static final byte[] DISABLE_NOTIFICATION_VALUE = {0x00, 0x00};
-
- /**
- * Descriptor read permission
- */
- public static final int PERMISSION_READ = 0x01;
-
- /**
- * Descriptor permission: Allow encrypted read operations
- */
- public static final int PERMISSION_READ_ENCRYPTED = 0x02;
-
- /**
- * Descriptor permission: Allow reading with person-in-the-middle protection
- */
- public static final int PERMISSION_READ_ENCRYPTED_MITM = 0x04;
-
- /**
- * Descriptor write permission
- */
- public static final int PERMISSION_WRITE = 0x10;
-
- /**
- * Descriptor permission: Allow encrypted writes
- */
- public static final int PERMISSION_WRITE_ENCRYPTED = 0x20;
-
- /**
- * Descriptor permission: Allow encrypted writes with person-in-the-middle
- * protection
- */
- public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 0x40;
-
- /**
- * Descriptor permission: Allow signed write operations
- */
- public static final int PERMISSION_WRITE_SIGNED = 0x80;
-
- /**
- * Descriptor permission: Allow signed write operations with
- * person-in-the-middle protection
- */
- public static final int PERMISSION_WRITE_SIGNED_MITM = 0x100;
-
- /**
- * The UUID of this descriptor.
- *
- * @hide
- */
- protected UUID mUuid;
-
- /**
- * Instance ID for this descriptor.
- *
- * @hide
- */
- @UnsupportedAppUsage
- protected int mInstance;
-
- /**
- * Permissions for this descriptor
- *
- * @hide
- */
- protected int mPermissions;
-
- /**
- * Back-reference to the characteristic this descriptor belongs to.
- *
- * @hide
- */
- @UnsupportedAppUsage
- protected BluetoothGattCharacteristic mCharacteristic;
-
- /**
- * The value for this descriptor.
- *
- * @hide
- */
- protected byte[] mValue;
-
- /**
- * Create a new BluetoothGattDescriptor.
- *
- * @param uuid The UUID for this descriptor
- * @param permissions Permissions for this descriptor
- */
- public BluetoothGattDescriptor(UUID uuid, int permissions) {
- initDescriptor(null, uuid, 0, permissions);
- }
-
- /**
- * Create a new BluetoothGattDescriptor.
- *
- * @param characteristic The characteristic this descriptor belongs to
- * @param uuid The UUID for this descriptor
- * @param permissions Permissions for this descriptor
- */
- /*package*/ BluetoothGattDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
- int instance, int permissions) {
- initDescriptor(characteristic, uuid, instance, permissions);
- }
-
- /**
- * @hide
- */
- public BluetoothGattDescriptor(UUID uuid, int instance, int permissions) {
- initDescriptor(null, uuid, instance, permissions);
- }
-
- private void initDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
- int instance, int permissions) {
- mCharacteristic = characteristic;
- mUuid = uuid;
- mInstance = instance;
- mPermissions = permissions;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(new ParcelUuid(mUuid), 0);
- out.writeInt(mInstance);
- out.writeInt(mPermissions);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothGattDescriptor> CREATOR =
- new Parcelable.Creator<BluetoothGattDescriptor>() {
- public BluetoothGattDescriptor createFromParcel(Parcel in) {
- return new BluetoothGattDescriptor(in);
- }
-
- public BluetoothGattDescriptor[] newArray(int size) {
- return new BluetoothGattDescriptor[size];
- }
- };
-
- private BluetoothGattDescriptor(Parcel in) {
- mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
- mInstance = in.readInt();
- mPermissions = in.readInt();
- }
-
- /**
- * Returns the characteristic this descriptor belongs to.
- *
- * @return The characteristic.
- */
- public BluetoothGattCharacteristic getCharacteristic() {
- return mCharacteristic;
- }
-
- /**
- * Set the back-reference to the associated characteristic
- *
- * @hide
- */
- @UnsupportedAppUsage
- /*package*/ void setCharacteristic(BluetoothGattCharacteristic characteristic) {
- mCharacteristic = characteristic;
- }
-
- /**
- * Returns the UUID of this descriptor.
- *
- * @return UUID of this descriptor
- */
- public UUID getUuid() {
- return mUuid;
- }
-
- /**
- * Returns the instance ID for this descriptor.
- *
- * <p>If a remote device offers multiple descriptors with the same UUID,
- * the instance ID is used to distuinguish between descriptors.
- *
- * @return Instance ID of this descriptor
- * @hide
- */
- public int getInstanceId() {
- return mInstance;
- }
-
- /**
- * Force the instance ID.
- *
- * @hide
- */
- public void setInstanceId(int instanceId) {
- mInstance = instanceId;
- }
-
- /**
- * Returns the permissions for this descriptor.
- *
- * @return Permissions of this descriptor
- */
- public int getPermissions() {
- return mPermissions;
- }
-
- /**
- * Returns the stored value for this descriptor
- *
- * <p>This function returns the stored value for this descriptor as
- * retrieved by calling {@link BluetoothGatt#readDescriptor}. The cached
- * value of the descriptor is updated as a result of a descriptor read
- * operation.
- *
- * @return Cached value of the descriptor
- *
- * @deprecated Use {@link BluetoothGatt#readDescriptor(BluetoothGattDescriptor)} instead
- */
- @Deprecated
- public byte[] getValue() {
- return mValue;
- }
-
- /**
- * Updates the locally stored value of this descriptor.
- *
- * <p>This function modifies the locally stored cached value of this
- * descriptor. To send the value to the remote device, call
- * {@link BluetoothGatt#writeDescriptor} to send the value to the
- * remote device.
- *
- * @param value New value for this descriptor
- * @return true if the locally stored value has been set, false if the requested value could not
- * be stored locally.
- *
- * @deprecated Pass the descriptor value directly into
- * {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])}
- */
- @Deprecated
- public boolean setValue(byte[] value) {
- mValue = value;
- return true;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattIncludedService.java b/core/java/android/bluetooth/BluetoothGattIncludedService.java
deleted file mode 100644
index 5580619..0000000
--- a/core/java/android/bluetooth/BluetoothGattIncludedService.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.bluetooth;
-
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-
-import java.util.UUID;
-
-/**
- * Represents a Bluetooth GATT Included Service
- *
- * @hide
- */
-public class BluetoothGattIncludedService implements Parcelable {
-
- /**
- * The UUID of this service.
- */
- protected UUID mUuid;
-
- /**
- * Instance ID for this service.
- */
- protected int mInstanceId;
-
- /**
- * Service type (Primary/Secondary).
- */
- protected int mServiceType;
-
- /**
- * Create a new BluetoothGattIncludedService
- */
- public BluetoothGattIncludedService(UUID uuid, int instanceId, int serviceType) {
- mUuid = uuid;
- mInstanceId = instanceId;
- mServiceType = serviceType;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(new ParcelUuid(mUuid), 0);
- out.writeInt(mInstanceId);
- out.writeInt(mServiceType);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothGattIncludedService> CREATOR =
- new Parcelable.Creator<BluetoothGattIncludedService>() {
- public BluetoothGattIncludedService createFromParcel(Parcel in) {
- return new BluetoothGattIncludedService(in);
- }
-
- public BluetoothGattIncludedService[] newArray(int size) {
- return new BluetoothGattIncludedService[size];
- }
- };
-
- private BluetoothGattIncludedService(Parcel in) {
- mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
- mInstanceId = in.readInt();
- mServiceType = in.readInt();
- }
-
- /**
- * Returns the UUID of this service
- *
- * @return UUID of this service
- */
- public UUID getUuid() {
- return mUuid;
- }
-
- /**
- * Returns the instance ID for this service
- *
- * <p>If a remote device offers multiple services with the same UUID
- * (ex. multiple battery services for different batteries), the instance
- * ID is used to distuinguish services.
- *
- * @return Instance ID of this service
- */
- public int getInstanceId() {
- return mInstanceId;
- }
-
- /**
- * Get the type of this service (primary/secondary)
- */
- public int getType() {
- return mServiceType;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
deleted file mode 100644
index 08e0178..0000000
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ /dev/null
@@ -1,954 +0,0 @@
-/*
- * Copyright (C) 2013 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Public API for the Bluetooth GATT Profile server role.
- *
- * <p>This class provides Bluetooth GATT server role functionality,
- * allowing applications to create Bluetooth Smart services and
- * characteristics.
- *
- * <p>BluetoothGattServer is a proxy object for controlling the Bluetooth Service
- * via IPC. Use {@link BluetoothManager#openGattServer} to get an instance
- * of this class.
- */
-public final class BluetoothGattServer implements BluetoothProfile {
- private static final String TAG = "BluetoothGattServer";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- private final IBluetoothGatt mService;
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
-
- private BluetoothGattServerCallback mCallback;
-
- private Object mServerIfLock = new Object();
- private int mServerIf;
- private int mTransport;
- private BluetoothGattService mPendingService;
- private List<BluetoothGattService> mServices;
-
- private static final int CALLBACK_REG_TIMEOUT = 10000;
-
- /**
- * Bluetooth GATT interface callbacks
- */
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private final IBluetoothGattServerCallback mBluetoothGattServerCallback =
- new IBluetoothGattServerCallback.Stub() {
- /**
- * Application interface registered - app is ready to go
- * @hide
- */
- @Override
- public void onServerRegistered(int status, int serverIf) {
- if (DBG) {
- Log.d(TAG, "onServerRegistered() - status=" + status
- + " serverIf=" + serverIf);
- }
- synchronized (mServerIfLock) {
- if (mCallback != null) {
- mServerIf = serverIf;
- mServerIfLock.notify();
- } else {
- // registration timeout
- Log.e(TAG, "onServerRegistered: mCallback is null");
- }
- }
- }
-
- /**
- * Server connection state changed
- * @hide
- */
- @Override
- public void onServerConnectionState(int status, int serverIf,
- boolean connected, String address) {
- if (DBG) {
- Log.d(TAG, "onServerConnectionState() - status=" + status
- + " serverIf=" + serverIf + " device=" + address);
- }
- try {
- mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status,
- connected ? BluetoothProfile.STATE_CONNECTED :
- BluetoothProfile.STATE_DISCONNECTED);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
- }
-
- /**
- * Service has been added
- * @hide
- */
- @Override
- public void onServiceAdded(int status, BluetoothGattService service) {
- if (DBG) {
- Log.d(TAG, "onServiceAdded() - handle=" + service.getInstanceId()
- + " uuid=" + service.getUuid() + " status=" + status);
- }
-
- if (mPendingService == null) {
- return;
- }
-
- BluetoothGattService tmp = mPendingService;
- mPendingService = null;
-
- // Rewrite newly assigned handles to existing service.
- tmp.setInstanceId(service.getInstanceId());
- List<BluetoothGattCharacteristic> temp_chars = tmp.getCharacteristics();
- List<BluetoothGattCharacteristic> svc_chars = service.getCharacteristics();
- for (int i = 0; i < svc_chars.size(); i++) {
- BluetoothGattCharacteristic temp_char = temp_chars.get(i);
- BluetoothGattCharacteristic svc_char = svc_chars.get(i);
-
- temp_char.setInstanceId(svc_char.getInstanceId());
-
- List<BluetoothGattDescriptor> temp_descs = temp_char.getDescriptors();
- List<BluetoothGattDescriptor> svc_descs = svc_char.getDescriptors();
- for (int j = 0; j < svc_descs.size(); j++) {
- temp_descs.get(j).setInstanceId(svc_descs.get(j).getInstanceId());
- }
- }
-
- mServices.add(tmp);
-
- try {
- mCallback.onServiceAdded((int) status, tmp);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
- }
-
- /**
- * Remote client characteristic read request.
- * @hide
- */
- @Override
- public void onCharacteristicReadRequest(String address, int transId,
- int offset, boolean isLong, int handle) {
- if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);
-
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle);
- if (characteristic == null) {
- Log.w(TAG, "onCharacteristicReadRequest() no char for handle " + handle);
- return;
- }
-
- try {
- mCallback.onCharacteristicReadRequest(device, transId, offset,
- characteristic);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
- }
-
- /**
- * Remote client descriptor read request.
- * @hide
- */
- @Override
- public void onDescriptorReadRequest(String address, int transId,
- int offset, boolean isLong, int handle) {
- if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);
-
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle);
- if (descriptor == null) {
- Log.w(TAG, "onDescriptorReadRequest() no desc for handle " + handle);
- return;
- }
-
- try {
- mCallback.onDescriptorReadRequest(device, transId, offset, descriptor);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
- }
-
- /**
- * Remote client characteristic write request.
- * @hide
- */
- @Override
- public void onCharacteristicWriteRequest(String address, int transId,
- int offset, int length, boolean isPrep, boolean needRsp,
- int handle, byte[] value) {
- if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - handle=" + handle);
-
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle);
- if (characteristic == null) {
- Log.w(TAG, "onCharacteristicWriteRequest() no char for handle " + handle);
- return;
- }
-
- try {
- mCallback.onCharacteristicWriteRequest(device, transId, characteristic,
- isPrep, needRsp, offset, value);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
-
- }
-
- /**
- * Remote client descriptor write request.
- * @hide
- */
- @Override
- public void onDescriptorWriteRequest(String address, int transId, int offset,
- int length, boolean isPrep, boolean needRsp, int handle, byte[] value) {
- if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - handle=" + handle);
-
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle);
- if (descriptor == null) {
- Log.w(TAG, "onDescriptorWriteRequest() no desc for handle " + handle);
- return;
- }
-
- try {
- mCallback.onDescriptorWriteRequest(device, transId, descriptor,
- isPrep, needRsp, offset, value);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
- }
-
- /**
- * Execute pending writes.
- * @hide
- */
- @Override
- public void onExecuteWrite(String address, int transId,
- boolean execWrite) {
- if (DBG) {
- Log.d(TAG, "onExecuteWrite() - "
- + "device=" + address + ", transId=" + transId
- + "execWrite=" + execWrite);
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- if (device == null) return;
-
- try {
- mCallback.onExecuteWrite(device, transId, execWrite);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
- }
-
- /**
- * A notification/indication has been sent.
- * @hide
- */
- @Override
- public void onNotificationSent(String address, int status) {
- if (VDBG) {
- Log.d(TAG, "onNotificationSent() - "
- + "device=" + address + ", status=" + status);
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- if (device == null) return;
-
- try {
- mCallback.onNotificationSent(device, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
- }
- }
-
- /**
- * The MTU for a connection has changed
- * @hide
- */
- @Override
- public void onMtuChanged(String address, int mtu) {
- if (DBG) {
- Log.d(TAG, "onMtuChanged() - "
- + "device=" + address + ", mtu=" + mtu);
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- if (device == null) return;
-
- try {
- mCallback.onMtuChanged(device, mtu);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
- }
- }
-
- /**
- * The PHY for a connection was updated
- * @hide
- */
- @Override
- public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) {
- if (DBG) {
- Log.d(TAG,
- "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
- + ", rxPHy=" + rxPhy);
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- if (device == null) return;
-
- try {
- mCallback.onPhyUpdate(device, txPhy, rxPhy, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
- }
- }
-
- /**
- * The PHY for a connection was read
- * @hide
- */
- @Override
- public void onPhyRead(String address, int txPhy, int rxPhy, int status) {
- if (DBG) {
- Log.d(TAG,
- "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
- + ", rxPHy=" + rxPhy);
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- if (device == null) return;
-
- try {
- mCallback.onPhyRead(device, txPhy, rxPhy, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
- }
- }
-
- /**
- * Callback invoked when the given connection is updated
- * @hide
- */
- @Override
- public void onConnectionUpdated(String address, int interval, int latency,
- int timeout, int status) {
- if (DBG) {
- Log.d(TAG, "onConnectionUpdated() - Device=" + address
- + " interval=" + interval + " latency=" + latency
- + " timeout=" + timeout + " status=" + status);
- }
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- if (device == null) return;
-
- try {
- mCallback.onConnectionUpdated(device, interval, latency,
- timeout, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
- }
- }
-
- };
-
- /**
- * Create a BluetoothGattServer proxy object.
- */
- /* package */ BluetoothGattServer(IBluetoothGatt iGatt, int transport,
- BluetoothAdapter adapter) {
- mService = iGatt;
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mCallback = null;
- mServerIf = 0;
- mTransport = transport;
- mServices = new ArrayList<BluetoothGattService>();
- }
-
- /**
- * Returns a characteristic with given handle.
- *
- * @hide
- */
- /*package*/ BluetoothGattCharacteristic getCharacteristicByHandle(int handle) {
- for (BluetoothGattService svc : mServices) {
- for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
- if (charac.getInstanceId() == handle) {
- return charac;
- }
- }
- }
- return null;
- }
-
- /**
- * Returns a descriptor with given handle.
- *
- * @hide
- */
- /*package*/ BluetoothGattDescriptor getDescriptorByHandle(int handle) {
- for (BluetoothGattService svc : mServices) {
- for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
- for (BluetoothGattDescriptor desc : charac.getDescriptors()) {
- if (desc.getInstanceId() == handle) {
- return desc;
- }
- }
- }
- }
- return null;
- }
-
- /**
- * Close this GATT server instance.
- *
- * Application should call this method as early as possible after it is done with
- * this GATT server.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void close() {
- if (DBG) Log.d(TAG, "close()");
- unregisterCallback();
- }
-
- /**
- * Register an application callback to start using GattServer.
- *
- * <p>This is an asynchronous call. The callback is used to notify
- * success or failure if the function returns true.
- *
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @return true, the callback will be called to notify success or failure, false on immediate
- * error
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
- return registerCallback(callback, false);
- }
-
- /**
- * Register an application callback to start using GattServer.
- *
- * <p>This is an asynchronous call. The callback is used to notify
- * success or failure if the function returns true.
- *
- * @param callback GATT callback handler that will receive asynchronous callbacks.
- * @param eatt_support indicates if server can use eatt
- * @return true, the callback will be called to notify success or failure, false on immediate
- * error
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- /*package*/ boolean registerCallback(BluetoothGattServerCallback callback,
- boolean eatt_support) {
- if (DBG) Log.d(TAG, "registerCallback()");
- if (mService == null) {
- Log.e(TAG, "GATT service not available");
- return false;
- }
- UUID uuid = UUID.randomUUID();
- if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid);
-
- synchronized (mServerIfLock) {
- if (mCallback != null) {
- Log.e(TAG, "App can register callback only once");
- return false;
- }
-
- mCallback = callback;
- try {
- mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback,
- eatt_support, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- mCallback = null;
- return false;
- }
-
- try {
- mServerIfLock.wait(CALLBACK_REG_TIMEOUT);
- } catch (InterruptedException e) {
- Log.e(TAG, "" + e);
- mCallback = null;
- }
-
- if (mServerIf == 0) {
- mCallback = null;
- return false;
- } else {
- return true;
- }
- }
- }
-
- /**
- * Unregister the current application and callbacks.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private void unregisterCallback() {
- if (DBG) Log.d(TAG, "unregisterCallback() - mServerIf=" + mServerIf);
- if (mService == null || mServerIf == 0) return;
-
- try {
- mCallback = null;
- mService.unregisterServer(mServerIf, mAttributionSource);
- mServerIf = 0;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * Returns a service by UUID, instance and type.
- *
- * @hide
- */
- /*package*/ BluetoothGattService getService(UUID uuid, int instanceId, int type) {
- for (BluetoothGattService svc : mServices) {
- if (svc.getType() == type
- && svc.getInstanceId() == instanceId
- && svc.getUuid().equals(uuid)) {
- return svc;
- }
- }
- return null;
- }
-
- /**
- * Initiate a connection to a Bluetooth GATT capable device.
- *
- * <p>The connection may not be established right away, but will be
- * completed when the remote device is available. A
- * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be
- * invoked when the connection state changes as a result of this function.
- *
- * <p>The autoConnect parameter determines whether to actively connect to
- * the remote device, or rather passively scan and finalize the connection
- * when the remote device is in range/available. Generally, the first ever
- * connection to a device should be direct (autoConnect set to false) and
- * subsequent connections to known devices should be invoked with the
- * autoConnect parameter set to true.
- *
- * @param autoConnect Whether to directly connect to the remote device (false) or to
- * automatically connect as soon as the remote device becomes available (true).
- * @return true, if the connection attempt was initiated successfully
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean connect(BluetoothDevice device, boolean autoConnect) {
- if (DBG) {
- Log.d(TAG,
- "connect() - device: " + device.getAddress() + ", auto: " + autoConnect);
- }
- if (mService == null || mServerIf == 0) return false;
-
- try {
- // autoConnect is inverse of "isDirect"
- mService.serverConnect(
- mServerIf, device.getAddress(), !autoConnect, mTransport, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Disconnects an established connection, or cancels a connection attempt
- * currently in progress.
- *
- * @param device Remote device
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void cancelConnection(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "cancelConnection() - device: " + device.getAddress());
- if (mService == null || mServerIf == 0) return;
-
- try {
- mService.serverDisconnect(mServerIf, device.getAddress(), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * Set the preferred connection PHY for this app. Please note that this is just a
- * recommendation, whether the PHY change will happen depends on other applications peferences,
- * local and remote controller capabilities. Controller can override these settings. <p> {@link
- * BluetoothGattServerCallback#onPhyUpdate} will be triggered as a result of this call, even if
- * no PHY change happens. It is also triggered when remote device updates the PHY.
- *
- * @param device The remote device to send this response to
- * @param txPhy preferred transmitter PHY. Bitwise OR of any of {@link
- * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
- * BluetoothDevice#PHY_LE_CODED_MASK}.
- * @param rxPhy preferred receiver PHY. Bitwise OR of any of {@link
- * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
- * BluetoothDevice#PHY_LE_CODED_MASK}.
- * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
- * of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, {@link BluetoothDevice#PHY_OPTION_S2} or
- * {@link BluetoothDevice#PHY_OPTION_S8}
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void setPreferredPhy(BluetoothDevice device, int txPhy, int rxPhy, int phyOptions) {
- try {
- mService.serverSetPreferredPhy(mServerIf, device.getAddress(), txPhy, rxPhy,
- phyOptions, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * Read the current transmitter PHY and receiver PHY of the connection. The values are returned
- * in {@link BluetoothGattServerCallback#onPhyRead}
- *
- * @param device The remote device to send this response to
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void readPhy(BluetoothDevice device) {
- try {
- mService.serverReadPhy(mServerIf, device.getAddress(), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * Send a response to a read or write request to a remote device.
- *
- * <p>This function must be invoked in when a remote read/write request
- * is received by one of these callback methods:
- *
- * <ul>
- * <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest}
- * <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest}
- * <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest}
- * <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest}
- * </ul>
- *
- * @param device The remote device to send this response to
- * @param requestId The ID of the request that was received with the callback
- * @param status The status of the request to be sent to the remote devices
- * @param offset Value offset for partial read/write response
- * @param value The value of the attribute that was read/written (optional)
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean sendResponse(BluetoothDevice device, int requestId,
- int status, int offset, byte[] value) {
- if (VDBG) Log.d(TAG, "sendResponse() - device: " + device.getAddress());
- if (mService == null || mServerIf == 0) return false;
-
- try {
- mService.sendResponse(mServerIf, device.getAddress(), requestId,
- status, offset, value, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
- return true;
- }
-
- /**
- * Send a notification or indication that a local characteristic has been
- * updated.
- *
- * <p>A notification or indication is sent to the remote device to signal
- * that the characteristic has been updated. This function should be invoked
- * for every client that requests notifications/indications by writing
- * to the "Client Configuration" descriptor for the given characteristic.
- *
- * @param device The remote device to receive the notification/indication
- * @param characteristic The local characteristic that has been updated
- * @param confirm true to request confirmation from the client (indication), false to send a
- * notification
- * @return true, if the notification has been triggered successfully
- * @throws IllegalArgumentException
- *
- * @deprecated Use {@link BluetoothGattServer#notifyCharacteristicChanged(BluetoothDevice,
- * BluetoothGattCharacteristic, boolean, byte[])} as this is not memory safe.
- */
- @Deprecated
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean notifyCharacteristicChanged(BluetoothDevice device,
- BluetoothGattCharacteristic characteristic, boolean confirm) {
- return notifyCharacteristicChanged(device, characteristic, confirm,
- characteristic.getValue()) == BluetoothStatusCodes.SUCCESS;
- }
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- BluetoothStatusCodes.SUCCESS,
- BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
- BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION,
- BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED,
- BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
- BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED,
- BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY,
- BluetoothStatusCodes.ERROR_UNKNOWN
- })
- public @interface NotifyCharacteristicReturnValues{}
-
- /**
- * Send a notification or indication that a local characteristic has been
- * updated.
- *
- * <p>A notification or indication is sent to the remote device to signal
- * that the characteristic has been updated. This function should be invoked
- * for every client that requests notifications/indications by writing
- * to the "Client Configuration" descriptor for the given characteristic.
- *
- * @param device the remote device to receive the notification/indication
- * @param characteristic the local characteristic that has been updated
- * @param confirm {@code true} to request confirmation from the client (indication) or
- * {@code false} to send a notification
- * @param value the characteristic value
- * @return whether the notification has been triggered successfully
- * @throws IllegalArgumentException if the characteristic value or service is null
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @NotifyCharacteristicReturnValues
- public int notifyCharacteristicChanged(@NonNull BluetoothDevice device,
- @NonNull BluetoothGattCharacteristic characteristic, boolean confirm,
- @NonNull byte[] value) {
- if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress());
- if (mService == null || mServerIf == 0) {
- return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
- }
-
- if (characteristic == null) {
- throw new IllegalArgumentException("characteristic must not be null");
- }
- if (device == null) {
- throw new IllegalArgumentException("device must not be null");
- }
- BluetoothGattService service = characteristic.getService();
- if (service == null) {
- throw new IllegalArgumentException("Characteristic must have a non-null service");
- }
- if (value == null) {
- throw new IllegalArgumentException("Characteristic value must not be null");
- }
-
- try {
- return mService.sendNotification(mServerIf, device.getAddress(),
- characteristic.getInstanceId(), confirm,
- value, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Add a service to the list of services to be hosted.
- *
- * <p>Once a service has been addded to the list, the service and its
- * included characteristics will be provided by the local device.
- *
- * <p>If the local device has already exposed services when this function
- * is called, a service update notification will be sent to all clients.
- *
- * <p>The {@link BluetoothGattServerCallback#onServiceAdded} callback will indicate
- * whether this service has been added successfully. Do not add another service
- * before this callback.
- *
- * @param service Service to be added to the list of services provided by this device.
- * @return true, if the request to add service has been initiated
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean addService(BluetoothGattService service) {
- if (DBG) Log.d(TAG, "addService() - service: " + service.getUuid());
- if (mService == null || mServerIf == 0) return false;
-
- mPendingService = service;
-
- try {
- mService.addService(mServerIf, service, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Removes a service from the list of services to be provided.
- *
- * @param service Service to be removed.
- * @return true, if the service has been removed
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean removeService(BluetoothGattService service) {
- if (DBG) Log.d(TAG, "removeService() - service: " + service.getUuid());
- if (mService == null || mServerIf == 0) return false;
-
- BluetoothGattService intService = getService(service.getUuid(),
- service.getInstanceId(), service.getType());
- if (intService == null) return false;
-
- try {
- mService.removeService(mServerIf, service.getInstanceId(), mAttributionSource);
- mServices.remove(intService);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Remove all services from the list of provided services.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void clearServices() {
- if (DBG) Log.d(TAG, "clearServices()");
- if (mService == null || mServerIf == 0) return;
-
- try {
- mService.clearServices(mServerIf, mAttributionSource);
- mServices.clear();
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- /**
- * Returns a list of GATT services offered by this device.
- *
- * <p>An application must call {@link #addService} to add a serice to the
- * list of services offered by this device.
- *
- * @return List of services. Returns an empty list if no services have been added yet.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public List<BluetoothGattService> getServices() {
- return mServices;
- }
-
- /**
- * Returns a {@link BluetoothGattService} from the list of services offered
- * by this device.
- *
- * <p>If multiple instances of the same service (as identified by UUID)
- * exist, the first instance of the service is returned.
- *
- * @param uuid UUID of the requested service
- * @return BluetoothGattService if supported, or null if the requested service is not offered by
- * this device.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresNoPermission
- public BluetoothGattService getService(UUID uuid) {
- for (BluetoothGattService service : mServices) {
- if (service.getUuid().equals(uuid)) {
- return service;
- }
- }
-
- return null;
- }
-
-
- /**
- * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
- * with {@link BluetoothProfile#GATT} as argument
- *
- * @throws UnsupportedOperationException
- */
- @Override
- @RequiresNoPermission
- public int getConnectionState(BluetoothDevice device) {
- throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
- }
-
- /**
- * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
- * with {@link BluetoothProfile#GATT} as argument
- *
- * @throws UnsupportedOperationException
- */
- @Override
- @RequiresNoPermission
- public List<BluetoothDevice> getConnectedDevices() {
- throw new UnsupportedOperationException(
- "Use BluetoothManager#getConnectedDevices instead.");
- }
-
- /**
- * Not supported - please use
- * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
- * with {@link BluetoothProfile#GATT} as first argument
- *
- * @throws UnsupportedOperationException
- */
- @Override
- @RequiresNoPermission
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- throw new UnsupportedOperationException(
- "Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java
deleted file mode 100644
index 0ead5f5..0000000
--- a/core/java/android/bluetooth/BluetoothGattServerCallback.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * This abstract class is used to implement {@link BluetoothGattServer} callbacks.
- */
-public abstract class BluetoothGattServerCallback {
-
- /**
- * Callback indicating when a remote device has been connected or disconnected.
- *
- * @param device Remote device that has been connected or disconnected.
- * @param status Status of the connect or disconnect operation.
- * @param newState Returns the new connection state. Can be one of {@link
- * BluetoothProfile#STATE_DISCONNECTED} or {@link BluetoothProfile#STATE_CONNECTED}
- */
- public void onConnectionStateChange(BluetoothDevice device, int status,
- int newState) {
- }
-
- /**
- * Indicates whether a local service has been added successfully.
- *
- * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the service was added
- * successfully.
- * @param service The service that has been added
- */
- public void onServiceAdded(int status, BluetoothGattService service) {
- }
-
- /**
- * A remote client has requested to read a local characteristic.
- *
- * <p>An application must call {@link BluetoothGattServer#sendResponse}
- * to complete the request.
- *
- * @param device The remote device that has requested the read operation
- * @param requestId The Id of the request
- * @param offset Offset into the value of the characteristic
- * @param characteristic Characteristic to be read
- */
- public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
- int offset, BluetoothGattCharacteristic characteristic) {
- }
-
- /**
- * A remote client has requested to write to a local characteristic.
- *
- * <p>An application must call {@link BluetoothGattServer#sendResponse}
- * to complete the request.
- *
- * @param device The remote device that has requested the write operation
- * @param requestId The Id of the request
- * @param characteristic Characteristic to be written to.
- * @param preparedWrite true, if this write operation should be queued for later execution.
- * @param responseNeeded true, if the remote device requires a response
- * @param offset The offset given for the value
- * @param value The value the client wants to assign to the characteristic
- */
- public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
- BluetoothGattCharacteristic characteristic,
- boolean preparedWrite, boolean responseNeeded,
- int offset, byte[] value) {
- }
-
- /**
- * A remote client has requested to read a local descriptor.
- *
- * <p>An application must call {@link BluetoothGattServer#sendResponse}
- * to complete the request.
- *
- * @param device The remote device that has requested the read operation
- * @param requestId The Id of the request
- * @param offset Offset into the value of the characteristic
- * @param descriptor Descriptor to be read
- */
- public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
- int offset, BluetoothGattDescriptor descriptor) {
- }
-
- /**
- * A remote client has requested to write to a local descriptor.
- *
- * <p>An application must call {@link BluetoothGattServer#sendResponse}
- * to complete the request.
- *
- * @param device The remote device that has requested the write operation
- * @param requestId The Id of the request
- * @param descriptor Descriptor to be written to.
- * @param preparedWrite true, if this write operation should be queued for later execution.
- * @param responseNeeded true, if the remote device requires a response
- * @param offset The offset given for the value
- * @param value The value the client wants to assign to the descriptor
- */
- public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
- BluetoothGattDescriptor descriptor,
- boolean preparedWrite, boolean responseNeeded,
- int offset, byte[] value) {
- }
-
- /**
- * Execute all pending write operations for this device.
- *
- * <p>An application must call {@link BluetoothGattServer#sendResponse}
- * to complete the request.
- *
- * @param device The remote device that has requested the write operations
- * @param requestId The Id of the request
- * @param execute Whether the pending writes should be executed (true) or cancelled (false)
- */
- public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
- }
-
- /**
- * Callback invoked when a notification or indication has been sent to
- * a remote device.
- *
- * <p>When multiple notifications are to be sent, an application must
- * wait for this callback to be received before sending additional
- * notifications.
- *
- * @param device The remote device the notification has been sent to
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the operation was successful
- */
- public void onNotificationSent(BluetoothDevice device, int status) {
- }
-
- /**
- * Callback indicating the MTU for a given device connection has changed.
- *
- * <p>This callback will be invoked if a remote client has requested to change
- * the MTU for a given connection.
- *
- * @param device The remote device that requested the MTU change
- * @param mtu The new MTU size
- */
- public void onMtuChanged(BluetoothDevice device, int mtu) {
- }
-
- /**
- * Callback triggered as result of {@link BluetoothGattServer#setPreferredPhy}, or as a result
- * of remote device changing the PHY.
- *
- * @param device The remote device
- * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
- * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
- * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
- * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
- * @param status Status of the PHY update operation. {@link BluetoothGatt#GATT_SUCCESS} if the
- * operation succeeds.
- */
- public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
- }
-
- /**
- * Callback triggered as result of {@link BluetoothGattServer#readPhy}
- *
- * @param device The remote device that requested the PHY read
- * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
- * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
- * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
- * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
- * @param status Status of the PHY read operation. {@link BluetoothGatt#GATT_SUCCESS} if the
- * operation succeeds.
- */
- public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
- }
-
- /**
- * Callback indicating the connection parameters were updated.
- *
- * @param device The remote device involved
- * @param interval Connection interval used on this connection, 1.25ms unit. Valid range is from
- * 6 (7.5ms) to 3200 (4000ms).
- * @param latency Worker latency for the connection in number of connection events. Valid range
- * is from 0 to 499
- * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is from 10
- * (0.1s) to 3200 (32s)
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated
- * successfully
- * @hide
- */
- public void onConnectionUpdated(BluetoothDevice device, int interval, int latency, int timeout,
- int status) {
- }
-
-}
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
deleted file mode 100644
index f64d09f..0000000
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (C) 2013 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.bluetooth;
-
-import android.annotation.RequiresPermission;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Represents a Bluetooth GATT Service
- *
- * <p> Gatt Service contains a collection of {@link BluetoothGattCharacteristic},
- * as well as referenced services.
- */
-public class BluetoothGattService implements Parcelable {
-
- /**
- * Primary service
- */
- public static final int SERVICE_TYPE_PRIMARY = 0;
-
- /**
- * Secondary service (included by primary services)
- */
- public static final int SERVICE_TYPE_SECONDARY = 1;
-
-
- /**
- * The remote device this service is associated with.
- * This applies to client applications only.
- *
- * @hide
- */
- @UnsupportedAppUsage
- protected BluetoothDevice mDevice;
-
- /**
- * The UUID of this service.
- *
- * @hide
- */
- protected UUID mUuid;
-
- /**
- * Instance ID for this service.
- *
- * @hide
- */
- protected int mInstanceId;
-
- /**
- * Handle counter override (for conformance testing).
- *
- * @hide
- */
- protected int mHandles = 0;
-
- /**
- * Service type (Primary/Secondary).
- *
- * @hide
- */
- protected int mServiceType;
-
- /**
- * List of characteristics included in this service.
- */
- protected List<BluetoothGattCharacteristic> mCharacteristics;
-
- /**
- * List of included services for this service.
- */
- protected List<BluetoothGattService> mIncludedServices;
-
- /**
- * Whether the service uuid should be advertised.
- */
- private boolean mAdvertisePreferred;
-
- /**
- * Create a new BluetoothGattService.
- *
- * @param uuid The UUID for this service
- * @param serviceType The type of this service,
- * {@link BluetoothGattService#SERVICE_TYPE_PRIMARY}
- * or {@link BluetoothGattService#SERVICE_TYPE_SECONDARY}
- */
- public BluetoothGattService(UUID uuid, int serviceType) {
- mDevice = null;
- mUuid = uuid;
- mInstanceId = 0;
- mServiceType = serviceType;
- mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
- mIncludedServices = new ArrayList<BluetoothGattService>();
- }
-
- /**
- * Create a new BluetoothGattService
- *
- * @hide
- */
- /*package*/ BluetoothGattService(BluetoothDevice device, UUID uuid,
- int instanceId, int serviceType) {
- mDevice = device;
- mUuid = uuid;
- mInstanceId = instanceId;
- mServiceType = serviceType;
- mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
- mIncludedServices = new ArrayList<BluetoothGattService>();
- }
-
- /**
- * Create a new BluetoothGattService
- *
- * @hide
- */
- public BluetoothGattService(UUID uuid, int instanceId, int serviceType) {
- mDevice = null;
- mUuid = uuid;
- mInstanceId = instanceId;
- mServiceType = serviceType;
- mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
- mIncludedServices = new ArrayList<BluetoothGattService>();
- }
-
- /**
- * @hide
- */
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(new ParcelUuid(mUuid), 0);
- out.writeInt(mInstanceId);
- out.writeInt(mServiceType);
- out.writeTypedList(mCharacteristics);
-
- ArrayList<BluetoothGattIncludedService> includedServices =
- new ArrayList<BluetoothGattIncludedService>(mIncludedServices.size());
- for (BluetoothGattService s : mIncludedServices) {
- includedServices.add(new BluetoothGattIncludedService(s.getUuid(),
- s.getInstanceId(), s.getType()));
- }
- out.writeTypedList(includedServices);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothGattService> CREATOR =
- new Parcelable.Creator<BluetoothGattService>() {
- public BluetoothGattService createFromParcel(Parcel in) {
- return new BluetoothGattService(in);
- }
-
- public BluetoothGattService[] newArray(int size) {
- return new BluetoothGattService[size];
- }
- };
-
- private BluetoothGattService(Parcel in) {
- mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
- mInstanceId = in.readInt();
- mServiceType = in.readInt();
-
- mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
-
- ArrayList<BluetoothGattCharacteristic> chrcs =
- in.createTypedArrayList(BluetoothGattCharacteristic.CREATOR);
- if (chrcs != null) {
- for (BluetoothGattCharacteristic chrc : chrcs) {
- chrc.setService(this);
- mCharacteristics.add(chrc);
- }
- }
-
- mIncludedServices = new ArrayList<BluetoothGattService>();
-
- ArrayList<BluetoothGattIncludedService> inclSvcs =
- in.createTypedArrayList(BluetoothGattIncludedService.CREATOR);
- if (chrcs != null) {
- for (BluetoothGattIncludedService isvc : inclSvcs) {
- mIncludedServices.add(new BluetoothGattService(null, isvc.getUuid(),
- isvc.getInstanceId(), isvc.getType()));
- }
- }
- }
-
- /**
- * Returns the device associated with this service.
- *
- * @hide
- */
- /*package*/ BluetoothDevice getDevice() {
- return mDevice;
- }
-
- /**
- * Returns the device associated with this service.
- *
- * @hide
- */
- /*package*/ void setDevice(BluetoothDevice device) {
- mDevice = device;
- }
-
- /**
- * Add an included service to this service.
- *
- * @param service The service to be added
- * @return true, if the included service was added to the service
- */
- @RequiresLegacyBluetoothPermission
- public boolean addService(BluetoothGattService service) {
- mIncludedServices.add(service);
- return true;
- }
-
- /**
- * Add a characteristic to this service.
- *
- * @param characteristic The characteristics to be added
- * @return true, if the characteristic was added to the service
- */
- @RequiresLegacyBluetoothPermission
- public boolean addCharacteristic(BluetoothGattCharacteristic characteristic) {
- mCharacteristics.add(characteristic);
- characteristic.setService(this);
- return true;
- }
-
- /**
- * Get characteristic by UUID and instanceId.
- *
- * @hide
- */
- /*package*/ BluetoothGattCharacteristic getCharacteristic(UUID uuid, int instanceId) {
- for (BluetoothGattCharacteristic characteristic : mCharacteristics) {
- if (uuid.equals(characteristic.getUuid())
- && characteristic.getInstanceId() == instanceId) {
- return characteristic;
- }
- }
- return null;
- }
-
- /**
- * Force the instance ID.
- *
- * @hide
- */
- @UnsupportedAppUsage
- public void setInstanceId(int instanceId) {
- mInstanceId = instanceId;
- }
-
- /**
- * Get the handle count override (conformance testing.
- *
- * @hide
- */
- /*package*/ int getHandles() {
- return mHandles;
- }
-
- /**
- * Force the number of handles to reserve for this service.
- * This is needed for conformance testing only.
- *
- * @hide
- */
- public void setHandles(int handles) {
- mHandles = handles;
- }
-
- /**
- * Add an included service to the internal map.
- *
- * @hide
- */
- public void addIncludedService(BluetoothGattService includedService) {
- mIncludedServices.add(includedService);
- }
-
- /**
- * Returns the UUID of this service
- *
- * @return UUID of this service
- */
- public UUID getUuid() {
- return mUuid;
- }
-
- /**
- * Returns the instance ID for this service
- *
- * <p>If a remote device offers multiple services with the same UUID
- * (ex. multiple battery services for different batteries), the instance
- * ID is used to distuinguish services.
- *
- * @return Instance ID of this service
- */
- public int getInstanceId() {
- return mInstanceId;
- }
-
- /**
- * Get the type of this service (primary/secondary)
- */
- public int getType() {
- return mServiceType;
- }
-
- /**
- * Get the list of included GATT services for this service.
- *
- * @return List of included services or empty list if no included services were discovered.
- */
- public List<BluetoothGattService> getIncludedServices() {
- return mIncludedServices;
- }
-
- /**
- * Returns a list of characteristics included in this service.
- *
- * @return Characteristics included in this service
- */
- public List<BluetoothGattCharacteristic> getCharacteristics() {
- return mCharacteristics;
- }
-
- /**
- * Returns a characteristic with a given UUID out of the list of
- * characteristics offered by this service.
- *
- * <p>This is a convenience function to allow access to a given characteristic
- * without enumerating over the list returned by {@link #getCharacteristics}
- * manually.
- *
- * <p>If a remote service offers multiple characteristics with the same
- * UUID, the first instance of a characteristic with the given UUID
- * is returned.
- *
- * @return GATT characteristic object or null if no characteristic with the given UUID was
- * found.
- */
- public BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
- for (BluetoothGattCharacteristic characteristic : mCharacteristics) {
- if (uuid.equals(characteristic.getUuid())) {
- return characteristic;
- }
- }
- return null;
- }
-
- /**
- * Returns whether the uuid of the service should be advertised.
- *
- * @hide
- */
- public boolean isAdvertisePreferred() {
- return mAdvertisePreferred;
- }
-
- /**
- * Set whether the service uuid should be advertised.
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void setAdvertisePreferred(boolean advertisePreferred) {
- mAdvertisePreferred = advertisePreferred;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
deleted file mode 100644
index 1b141c9..0000000
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ /dev/null
@@ -1,1505 +0,0 @@
-/*
- * Copyright (C) 2008 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.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Public API for controlling the Bluetooth Headset Service. This includes both
- * Bluetooth Headset and Handsfree (v1.5) profiles.
- *
- * <p>BluetoothHeadset is a proxy object for controlling the Bluetooth Headset
- * Service via IPC.
- *
- * <p> Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothHeadset proxy object. Use
- * {@link BluetoothAdapter#closeProfileProxy} to close the service connection.
- *
- * <p> Android only supports one connected Bluetooth Headset at a time.
- * Each method is protected with its appropriate permission.
- */
-public final class BluetoothHeadset implements BluetoothProfile {
- private static final String TAG = "BluetoothHeadset";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Intent used to broadcast the change in connection state of the Headset
- * profile.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED";
-
- /**
- * Intent used to broadcast the change in the Audio Connection state of the
- * HFP profile.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_AUDIO_CONNECTED}, {@link #STATE_AUDIO_DISCONNECTED},
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_AUDIO_STATE_CHANGED =
- "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
-
- /**
- * Intent used to broadcast the selection of a connected device as active.
- *
- * <p>This intent will have one extra:
- * <ul>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
- * be null if no device is active. </li>
- * </ul>
- *
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @UnsupportedAppUsage(trackingBug = 171933273)
- public static final String ACTION_ACTIVE_DEVICE_CHANGED =
- "android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED";
-
- /**
- * Intent used to broadcast that the headset has posted a
- * vendor-specific event.
- *
- * <p>This intent will have 4 extras and 1 category.
- * <ul>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote Bluetooth Device
- * </li>
- * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD} - The vendor
- * specific command </li>
- * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} - The AT
- * command type which can be one of {@link #AT_CMD_TYPE_READ},
- * {@link #AT_CMD_TYPE_TEST}, or {@link #AT_CMD_TYPE_SET},
- * {@link #AT_CMD_TYPE_BASIC},{@link #AT_CMD_TYPE_ACTION}. </li>
- * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS} - Command
- * arguments. </li>
- * </ul>
- *
- * <p> The category is the Company ID of the vendor defining the
- * vendor-specific command. {@link BluetoothAssignedNumbers}
- *
- * For example, for Plantronics specific events
- * Category will be {@link #VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY}.55
- *
- * <p> For example, an AT+XEVENT=foo,3 will get translated into
- * <ul>
- * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = +XEVENT </li>
- * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = AT_CMD_TYPE_SET </li>
- * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = foo, 3 </li>
- * </ul>
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT =
- "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
-
- /**
- * A String extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
- * intents that contains the name of the vendor-specific command.
- */
- public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD =
- "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD";
-
- /**
- * An int extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
- * intents that contains the AT command type of the vendor-specific command.
- */
- public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE =
- "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE";
-
- /**
- * AT command type READ used with
- * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
- * For example, AT+VGM?. There are no arguments for this command type.
- */
- public static final int AT_CMD_TYPE_READ = 0;
-
- /**
- * AT command type TEST used with
- * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
- * For example, AT+VGM=?. There are no arguments for this command type.
- */
- public static final int AT_CMD_TYPE_TEST = 1;
-
- /**
- * AT command type SET used with
- * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
- * For example, AT+VGM=<args>.
- */
- public static final int AT_CMD_TYPE_SET = 2;
-
- /**
- * AT command type BASIC used with
- * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
- * For example, ATD. Single character commands and everything following the
- * character are arguments.
- */
- public static final int AT_CMD_TYPE_BASIC = 3;
-
- /**
- * AT command type ACTION used with
- * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
- * For example, AT+CHUP. There are no arguments for action commands.
- */
- public static final int AT_CMD_TYPE_ACTION = 4;
-
- /**
- * A Parcelable String array extra field in
- * {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} intents that contains
- * the arguments to the vendor-specific command.
- */
- public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS =
- "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS";
-
- /**
- * The intent category to be used with {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
- * for the companyId
- */
- public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY =
- "android.bluetooth.headset.intent.category.companyid";
-
- /**
- * A vendor-specific command for unsolicited result code.
- */
- public static final String VENDOR_RESULT_CODE_COMMAND_ANDROID = "+ANDROID";
-
- /**
- * A vendor-specific AT command
- *
- * @hide
- */
- public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XAPL = "+XAPL";
-
- /**
- * A vendor-specific AT command
- *
- * @hide
- */
- public static final String VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV = "+IPHONEACCEV";
-
- /**
- * Battery level indicator associated with
- * {@link #VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV}
- *
- * @hide
- */
- public static final int VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL = 1;
-
- /**
- * A vendor-specific AT command
- *
- * @hide
- */
- public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT = "+XEVENT";
-
- /**
- * Battery level indicator associated with {@link #VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT}
- *
- * @hide
- */
- public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT_BATTERY_LEVEL = "BATTERY";
-
- /**
- * Headset state when SCO audio is not connected.
- * This state can be one of
- * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
- * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
- */
- public static final int STATE_AUDIO_DISCONNECTED = 10;
-
- /**
- * Headset state when SCO audio is connecting.
- * This state can be one of
- * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
- * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
- */
- public static final int STATE_AUDIO_CONNECTING = 11;
-
- /**
- * Headset state when SCO audio is connected.
- * This state can be one of
- * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
- * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
- */
- public static final int STATE_AUDIO_CONNECTED = 12;
-
- /**
- * Intent used to broadcast the headset's indicator status
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_HF_INDICATORS_IND_ID} - The Assigned number of headset Indicator which
- * is supported by the headset ( as indicated by AT+BIND command in the SLC
- * sequence) or whose value is changed (indicated by AT+BIEV command) </li>
- * <li> {@link #EXTRA_HF_INDICATORS_IND_VALUE} - Updated value of headset indicator. </li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - Remote device. </li>
- * </ul>
- * <p>{@link #EXTRA_HF_INDICATORS_IND_ID} is defined by Bluetooth SIG and each of the indicators
- * are given an assigned number. Below shows the assigned number of Indicator added so far
- * - Enhanced Safety - 1, Valid Values: 0 - Disabled, 1 - Enabled
- * - Battery Level - 2, Valid Values: 0~100 - Remaining level of Battery
- *
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_HF_INDICATORS_VALUE_CHANGED =
- "android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED";
-
- /**
- * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED}
- * intents that contains the assigned number of the headset indicator as defined by
- * Bluetooth SIG that is being sent. Value range is 0-65535 as defined in HFP 1.7
- *
- * @hide
- */
- public static final String EXTRA_HF_INDICATORS_IND_ID =
- "android.bluetooth.headset.extra.HF_INDICATORS_IND_ID";
-
- /**
- * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED}
- * intents that contains the value of the Headset indicator that is being sent.
- *
- * @hide
- */
- public static final String EXTRA_HF_INDICATORS_IND_VALUE =
- "android.bluetooth.headset.extra.HF_INDICATORS_IND_VALUE";
-
- private static final int MESSAGE_HEADSET_SERVICE_CONNECTED = 100;
- private static final int MESSAGE_HEADSET_SERVICE_DISCONNECTED = 101;
-
- private final CloseGuard mCloseGuard = new CloseGuard();
-
- private Context mContext;
- private ServiceListener mServiceListener;
- private volatile IBluetoothHeadset mService;
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- doUnbind();
- } else {
- doBind();
- }
- }
- };
-
- /**
- * Create a BluetoothHeadset proxy object.
- */
- /* package */ BluetoothHeadset(Context context, ServiceListener l, BluetoothAdapter adapter) {
- mContext = context;
- mServiceListener = l;
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
-
- // Preserve legacy compatibility where apps were depending on
- // registerStateChangeCallback() performing a permissions check which
- // has been relaxed in modern platform versions
- if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.R
- && context.checkSelfPermission(android.Manifest.permission.BLUETOOTH)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Need BLUETOOTH permission");
- }
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- mCloseGuard.open("close");
- }
-
- private boolean doBind() {
- synchronized (mConnection) {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- try {
- return mAdapter.getBluetoothManager().bindBluetoothProfileService(
- BluetoothProfile.HEADSET, mConnection);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to bind HeadsetService", e);
- }
- }
- }
- return false;
- }
-
- private void doUnbind() {
- synchronized (mConnection) {
- if (mService != null) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- try {
- mAdapter.getBluetoothManager().unbindBluetoothProfileService(
- BluetoothProfile.HEADSET, mConnection);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to unbind HeadsetService", e);
- } finally {
- mService = null;
- }
- }
- }
- }
-
- /**
- * Close the connection to the backing service.
- * Other public functions of BluetoothHeadset will return default error
- * results once close() has been called. Multiple invocations of close()
- * are ok.
- */
- @UnsupportedAppUsage
- /*package*/ void close() {
- if (VDBG) log("close()");
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "", re);
- }
- }
- mServiceListener = null;
- doUnbind();
- mCloseGuard.close();
- }
-
- /** {@hide} */
- @Override
- protected void finalize() throws Throwable {
- mCloseGuard.warnIfOpen();
- close();
- }
-
- /**
- * Initiate connection to a profile of the remote bluetooth device.
- *
- * <p> Currently, the system supports only 1 connection to the
- * headset/handsfree profile. The API will automatically disconnect connected
- * devices before connecting.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is already connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that
- * connection state intent for the profile will be broadcasted with
- * the state. Users can get the connection state of the profile
- * from this intent.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public boolean connect(BluetoothDevice device) {
- if (DBG) log("connect(" + device + ")");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connectWithAttribution(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate disconnection from a profile
- *
- * <p> This API will return false in scenarios like the profile on the
- * Bluetooth device is not in connected state etc. When this API returns,
- * true, it is guaranteed that the connection state change
- * intent will be broadcasted with the state. Users can get the
- * disconnection state of the profile from this intent.
- *
- * <p> If the disconnection is initiated by a remote device, the state
- * will transition from {@link #STATE_CONNECTED} to
- * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
- * host (local) device the state will transition from
- * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
- * state {@link #STATE_DISCONNECTED}. The transition to
- * {@link #STATE_DISCONNECTING} can be used to distinguish between the
- * two scenarios.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) log("disconnect(" + device + ")");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnectWithAttribution(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
- if (VDBG) log("getConnectedDevices()");
- final IBluetoothHeadset service = mService;
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevicesWithAttribution(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothHeadset service = mService;
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
- if (VDBG) log("getConnectionState(" + device + ")");
- final IBluetoothHeadset service = mService;
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionStateWithAttribution(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set priority of the profile
- *
- * <p> The device should already be paired.
- * Priority can be one of {@link BluetoothProfile#PRIORITY_ON} or
- * {@link BluetoothProfile#PRIORITY_OFF}
- *
- * @param device Paired bluetooth device
- * @param priority
- * @return true if priority is set, false on error
- * @hide
- * @deprecated Replaced with {@link #setConnectionPolicy(BluetoothDevice, int)}
- * @removed
- */
- @Deprecated
- @SystemApi
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public boolean setPriority(BluetoothDevice device, int priority) {
- if (DBG) log("setPriority(" + device + ", " + priority + ")");
- return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the priority of the profile.
- *
- * <p> The priority can be any of:
- * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
- * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * @param device Bluetooth device
- * @return priority of the device
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getPriority(BluetoothDevice device) {
- if (VDBG) log("getPriority(" + device + ")");
- return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- final IBluetoothHeadset service = mService;
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Checks whether the headset supports some form of noise reduction
- *
- * @param device Bluetooth device
- * @return true if echo cancellation and/or noise reduction is supported, false otherwise
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isNoiseReductionSupported(@NonNull BluetoothDevice device) {
- if (DBG) log("isNoiseReductionSupported()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isNoiseReductionSupported(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Checks whether the headset supports voice recognition
- *
- * @param device Bluetooth device
- * @return true if voice recognition is supported, false otherwise
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isVoiceRecognitionSupported(@NonNull BluetoothDevice device) {
- if (DBG) log("isVoiceRecognitionSupported()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isVoiceRecognitionSupported(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Start Bluetooth voice recognition. This methods sends the voice
- * recognition AT command to the headset and establishes the
- * audio connection.
- *
- * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
- * If this function returns true, this intent will be broadcasted with
- * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}.
- *
- * <p> {@link #EXTRA_STATE} will transition from
- * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when
- * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
- * in case of failure to establish the audio connection.
- *
- * @param device Bluetooth headset
- * @return false if there is no headset connected, or the connected headset doesn't support
- * voice recognition, or voice recognition is already started, or audio channel is occupied,
- * or on error, true otherwise
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public boolean startVoiceRecognition(BluetoothDevice device) {
- if (DBG) log("startVoiceRecognition()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.startVoiceRecognition(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Stop Bluetooth Voice Recognition mode, and shut down the
- * Bluetooth audio path.
- *
- * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
- * If this function returns true, this intent will be broadcasted with
- * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}.
- *
- * @param device Bluetooth headset
- * @return false if there is no headset connected, or voice recognition has not started,
- * or voice recognition has ended on this headset, or on error, true otherwise
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean stopVoiceRecognition(BluetoothDevice device) {
- if (DBG) log("stopVoiceRecognition()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.stopVoiceRecognition(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Check if Bluetooth SCO audio is connected.
- *
- * @param device Bluetooth headset
- * @return true if SCO is connected, false otherwise or on error
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isAudioConnected(BluetoothDevice device) {
- if (VDBG) log("isAudioConnected()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isAudioConnected(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Indicates if current platform supports voice dialing over bluetooth SCO.
- *
- * @return true if voice dialing over bluetooth is supported, false otherwise.
- * @hide
- */
- public static boolean isBluetoothVoiceDialingEnabled(Context context) {
- return context.getResources().getBoolean(
- com.android.internal.R.bool.config_bluetooth_sco_off_call);
- }
-
- /**
- * Get the current audio state of the Headset.
- * Note: This is an internal function and shouldn't be exposed
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getAudioState(BluetoothDevice device) {
- if (VDBG) log("getAudioState");
- final IBluetoothHeadset service = mService;
- final int defaultValue = BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (!isDisabled()) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getAudioState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Sets whether audio routing is allowed. When set to {@code false}, the AG will not route any
- * audio to the HF unless explicitly told to.
- * This method should be used in cases where the SCO channel is shared between multiple profiles
- * and must be delegated by a source knowledgeable
- * Note: This is an internal function and shouldn't be exposed
- *
- * @param allowed {@code true} if the profile can reroute audio, {@code false} otherwise.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void setAudioRouteAllowed(boolean allowed) {
- if (VDBG) log("setAudioRouteAllowed");
- final IBluetoothHeadset service = mService;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.setAudioRouteAllowed(allowed, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Returns whether audio routing is allowed. see {@link #setAudioRouteAllowed(boolean)}.
- * Note: This is an internal function and shouldn't be exposed
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean getAudioRouteAllowed() {
- if (VDBG) log("getAudioRouteAllowed");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.getAudioRouteAllowed(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Force SCO audio to be opened regardless any other restrictions
- *
- * @param forced Whether or not SCO audio connection should be forced: True to force SCO audio
- * False to use SCO audio in normal manner
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void setForceScoAudio(boolean forced) {
- if (VDBG) log("setForceScoAudio " + String.valueOf(forced));
- final IBluetoothHeadset service = mService;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.setForceScoAudio(forced, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Check if at least one headset's SCO audio is connected or connecting
- *
- * @return true if at least one device's SCO audio is connected or connecting, false otherwise
- * or on error
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isAudioOn() {
- if (VDBG) log("isAudioOn()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isAudioOn(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiates a connection of headset audio to the current active device
- *
- * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
- * If this function returns true, this intent will be broadcasted with
- * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}.
- *
- * <p> {@link #EXTRA_STATE} will transition from
- * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when
- * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
- * in case of failure to establish the audio connection.
- *
- * Note that this intent will not be sent if {@link BluetoothHeadset#isAudioOn()} is true
- * before calling this method
- *
- * @return false if there was some error such as there is no active headset
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean connectAudio() {
- if (VDBG) log("connectAudio()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connectAudio(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiates a disconnection of HFP SCO audio.
- * Tear down voice recognition or virtual voice call if any.
- *
- * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
- * If this function returns true, this intent will be broadcasted with
- * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}.
- *
- * @return false if audio is not connected, or on error, true otherwise
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnectAudio() {
- if (VDBG) log("disconnectAudio()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnectAudio(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiates a SCO channel connection as a virtual voice call to the current active device
- * Active handsfree device will be notified of incoming call and connected call.
- *
- * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
- * If this function returns true, this intent will be broadcasted with
- * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}.
- *
- * <p> {@link #EXTRA_STATE} will transition from
- * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when
- * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
- * in case of failure to establish the audio connection.
- *
- * @return true if successful, false if one of the following case applies
- * - SCO audio is not idle (connecting or connected)
- * - virtual call has already started
- * - there is no active device
- * - a Telecom managed call is going on
- * - binder is dead or Bluetooth is disabled or other error
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public boolean startScoUsingVirtualVoiceCall() {
- if (DBG) log("startScoUsingVirtualVoiceCall()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.startScoUsingVirtualVoiceCall(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Terminates an ongoing SCO connection and the associated virtual call.
- *
- * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
- * If this function returns true, this intent will be broadcasted with
- * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}.
- *
- * @return true if successful, false if one of the following case applies
- * - virtual voice call is not started or has ended
- * - binder is dead or Bluetooth is disabled or other error
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public boolean stopScoUsingVirtualVoiceCall() {
- if (DBG) log("stopScoUsingVirtualVoiceCall()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.stopScoUsingVirtualVoiceCall(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Notify Headset of phone state change.
- * This is a backdoor for phone app to call BluetoothHeadset since
- * there is currently not a good way to get precise call state change outside
- * of phone app.
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
- int type, String name) {
- final IBluetoothHeadset service = mService;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- service.phoneStateChanged(numActive, numHeld, callState, number, type, name,
- mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Send Headset of CLCC response
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
- String number, int type) {
- final IBluetoothHeadset service = mService;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.clccResponse(index, direction, status, mode, mpty, number, type,
- mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Sends a vendor-specific unsolicited result code to the headset.
- *
- * <p>The actual string to be sent is <code>command + ": " + arg</code>. For example, if {@code
- * command} is {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} and {@code arg} is {@code "0"}, the
- * string <code>"+ANDROID: 0"</code> will be sent.
- *
- * <p>Currently only {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} is allowed as {@code command}.
- *
- * @param device Bluetooth headset.
- * @param command A vendor-specific command.
- * @param arg The argument that will be attached to the command.
- * @return {@code false} if there is no headset connected, or if the command is not an allowed
- * vendor-specific unsolicited result code, or on error. {@code true} otherwise.
- * @throws IllegalArgumentException if {@code command} is {@code null}.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean sendVendorSpecificResultCode(BluetoothDevice device, String command,
- String arg) {
- if (DBG) {
- log("sendVendorSpecificResultCode()");
- }
- if (command == null) {
- throw new IllegalArgumentException("command is null");
- }
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.sendVendorSpecificResultCode(device, command, arg,
- mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Select a connected device as active.
- *
- * The active device selection is per profile. An active device's
- * purpose is profile-specific. For example, in HFP and HSP profiles,
- * it is the device used for phone call audio. If a remote device is not
- * connected, it cannot be selected as active.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is not connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that the
- * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
- * with the active device.
- *
- * @param device Remote Bluetooth Device, could be null if phone call audio should not be
- * streamed to a headset
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- @UnsupportedAppUsage(trackingBug = 171933273)
- public boolean setActiveDevice(@Nullable BluetoothDevice device) {
- if (DBG) {
- Log.d(TAG, "setActiveDevice: " + device);
- }
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && (device == null || isValidDevice(device))) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setActiveDevice(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the connected device that is active.
- *
- * @return the connected device that is active or null if no device
- * is active.
- * @hide
- */
- @UnsupportedAppUsage(trackingBug = 171933273)
- @Nullable
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothDevice getActiveDevice() {
- if (VDBG) Log.d(TAG, "getActiveDevice");
- final IBluetoothHeadset service = mService;
- final BluetoothDevice defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<BluetoothDevice> recv =
- new SynchronousResultReceiver();
- service.getActiveDevice(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Check if in-band ringing is currently enabled. In-band ringing could be disabled during an
- * active connection.
- *
- * @return true if in-band ringing is enabled, false if in-band ringing is disabled
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public boolean isInbandRingingEnabled() {
- if (DBG) log("isInbandRingingEnabled()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isInbandRingingEnabled(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Check if in-band ringing is supported for this platform.
- *
- * @return true if in-band ringing is supported, false if in-band ringing is not supported
- * @hide
- */
- public static boolean isInbandRingingSupported(Context context) {
- return context.getResources().getBoolean(
- com.android.internal.R.bool.config_bluetooth_hfp_inband_ringing_support);
- }
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private final IBluetoothProfileServiceConnection mConnection =
- new IBluetoothProfileServiceConnection.Stub() {
- @Override
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothHeadset.Stub.asInterface(service);
- mHandler.sendMessage(mHandler.obtainMessage(
- MESSAGE_HEADSET_SERVICE_CONNECTED));
- }
-
- @Override
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- doUnbind();
- mHandler.sendMessage(mHandler.obtainMessage(
- MESSAGE_HEADSET_SERVICE_DISCONNECTED));
- }
- };
-
- @UnsupportedAppUsage
- private boolean isEnabled() {
- return mAdapter.getState() == BluetoothAdapter.STATE_ON;
- }
-
- private boolean isDisabled() {
- return mAdapter.getState() == BluetoothAdapter.STATE_OFF;
- }
-
- private static boolean isValidDevice(BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private final Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_HEADSET_SERVICE_CONNECTED: {
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.HEADSET,
- BluetoothHeadset.this);
- }
- break;
- }
- case MESSAGE_HEADSET_SERVICE_DISCONNECTED: {
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET);
- }
- break;
- }
- }
- }
- };
-}
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
deleted file mode 100644
index 7d7a7f7..0000000
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ /dev/null
@@ -1,1356 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Public API to control Hands Free Profile (HFP role only).
- * <p>
- * This class defines methods that shall be used by application to manage profile
- * connection, calls states and calls actions.
- * <p>
- *
- * @hide
- */
-public final class BluetoothHeadsetClient implements BluetoothProfile {
- private static final String TAG = "BluetoothHeadsetClient";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Intent sent whenever connection to remote changes.
- *
- * <p>It includes two extras:
- * <code>BluetoothProfile.EXTRA_PREVIOUS_STATE</code>
- * and <code>BluetoothProfile.EXTRA_STATE</code>, which
- * are mandatory.
- * <p>There are also non mandatory feature extras:
- * {@link #EXTRA_AG_FEATURE_3WAY_CALLING},
- * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION},
- * {@link #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT},
- * {@link #EXTRA_AG_FEATURE_REJECT_CALL},
- * {@link #EXTRA_AG_FEATURE_ECC},
- * {@link #EXTRA_AG_FEATURE_RESPONSE_AND_HOLD},
- * {@link #EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL},
- * {@link #EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL},
- * {@link #EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT},
- * {@link #EXTRA_AG_FEATURE_MERGE},
- * {@link #EXTRA_AG_FEATURE_MERGE_AND_DETACH},
- * sent as boolean values only when <code>EXTRA_STATE</code>
- * is set to <code>STATE_CONNECTED</code>.</p>
- *
- * <p>Note that features supported by AG are being sent as
- * booleans with value <code>true</code>,
- * and not supported ones are <strong>not</strong> being sent at all.</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED";
-
- /**
- * Intent sent whenever audio state changes.
- *
- * <p>It includes two mandatory extras:
- * {@link BluetoothProfile#EXTRA_STATE},
- * {@link BluetoothProfile#EXTRA_PREVIOUS_STATE},
- * with possible values:
- * {@link #STATE_AUDIO_CONNECTING},
- * {@link #STATE_AUDIO_CONNECTED},
- * {@link #STATE_AUDIO_DISCONNECTED}</p>
- * <p>When <code>EXTRA_STATE</code> is set
- * to </code>STATE_AUDIO_CONNECTED</code>,
- * it also includes {@link #EXTRA_AUDIO_WBS}
- * indicating wide band speech support.</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_AUDIO_STATE_CHANGED =
- "android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED";
-
- /**
- * Intent sending updates of the Audio Gateway state.
- * Each extra is being sent only when value it
- * represents has been changed recently on AG.
- * <p>It can contain one or more of the following extras:
- * {@link #EXTRA_NETWORK_STATUS},
- * {@link #EXTRA_NETWORK_SIGNAL_STRENGTH},
- * {@link #EXTRA_NETWORK_ROAMING},
- * {@link #EXTRA_BATTERY_LEVEL},
- * {@link #EXTRA_OPERATOR_NAME},
- * {@link #EXTRA_VOICE_RECOGNITION},
- * {@link #EXTRA_IN_BAND_RING}</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_AG_EVENT =
- "android.bluetooth.headsetclient.profile.action.AG_EVENT";
-
- /**
- * Intent sent whenever state of a call changes.
- *
- * <p>It includes:
- * {@link #EXTRA_CALL},
- * with value of {@link BluetoothHeadsetClientCall} instance,
- * representing actual call state.</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CALL_CHANGED =
- "android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED";
-
- /**
- * Intent that notifies about the result of the last issued action.
- * Please note that not every action results in explicit action result code being sent.
- * Instead other notifications about new Audio Gateway state might be sent,
- * like <code>ACTION_AG_EVENT</code> with <code>EXTRA_VOICE_RECOGNITION</code> value
- * when for example user started voice recognition from HF unit.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_RESULT =
- "android.bluetooth.headsetclient.profile.action.RESULT";
-
- /**
- * Intent that notifies about vendor specific event arrival. Events not defined in
- * HFP spec will be matched with supported vendor event list and this intent will
- * be broadcasted upon a match. Supported vendor events are of format of
- * of "+eventCode" or "+eventCode=xxxx" or "+eventCode:=xxxx".
- * Vendor event can be a response to an vendor specific command or unsolicited.
- *
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_VENDOR_SPECIFIC_HEADSETCLIENT_EVENT =
- "android.bluetooth.headsetclient.profile.action.VENDOR_SPECIFIC_EVENT";
-
- /**
- * Intent that notifies about the number attached to the last voice tag
- * recorded on AG.
- *
- * <p>It contains:
- * {@link #EXTRA_NUMBER},
- * with a <code>String</code> value representing phone number.</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_LAST_VTAG =
- "android.bluetooth.headsetclient.profile.action.LAST_VTAG";
-
- public static final int STATE_AUDIO_DISCONNECTED = 0;
- public static final int STATE_AUDIO_CONNECTING = 1;
- public static final int STATE_AUDIO_CONNECTED = 2;
-
- /**
- * Extra with information if connected audio is WBS.
- * <p>Possible values: <code>true</code>,
- * <code>false</code>.</p>
- */
- public static final String EXTRA_AUDIO_WBS =
- "android.bluetooth.headsetclient.extra.AUDIO_WBS";
-
- /**
- * Extra for AG_EVENT indicates network status.
- * <p>Value: 0 - network unavailable,
- * 1 - network available </p>
- */
- public static final String EXTRA_NETWORK_STATUS =
- "android.bluetooth.headsetclient.extra.NETWORK_STATUS";
- /**
- * Extra for AG_EVENT intent indicates network signal strength.
- * <p>Value: <code>Integer</code> representing signal strength.</p>
- */
- public static final String EXTRA_NETWORK_SIGNAL_STRENGTH =
- "android.bluetooth.headsetclient.extra.NETWORK_SIGNAL_STRENGTH";
- /**
- * Extra for AG_EVENT intent indicates roaming state.
- * <p>Value: 0 - no roaming
- * 1 - active roaming</p>
- */
- public static final String EXTRA_NETWORK_ROAMING =
- "android.bluetooth.headsetclient.extra.NETWORK_ROAMING";
- /**
- * Extra for AG_EVENT intent indicates the battery level.
- * <p>Value: <code>Integer</code> representing signal strength.</p>
- */
- public static final String EXTRA_BATTERY_LEVEL =
- "android.bluetooth.headsetclient.extra.BATTERY_LEVEL";
- /**
- * Extra for AG_EVENT intent indicates operator name.
- * <p>Value: <code>String</code> representing operator name.</p>
- */
- public static final String EXTRA_OPERATOR_NAME =
- "android.bluetooth.headsetclient.extra.OPERATOR_NAME";
- /**
- * Extra for AG_EVENT intent indicates voice recognition state.
- * <p>Value:
- * 0 - voice recognition stopped,
- * 1 - voice recognition started.</p>
- */
- public static final String EXTRA_VOICE_RECOGNITION =
- "android.bluetooth.headsetclient.extra.VOICE_RECOGNITION";
- /**
- * Extra for AG_EVENT intent indicates in band ring state.
- * <p>Value:
- * 0 - in band ring tone not supported, or
- * 1 - in band ring tone supported.</p>
- */
- public static final String EXTRA_IN_BAND_RING =
- "android.bluetooth.headsetclient.extra.IN_BAND_RING";
-
- /**
- * Extra for AG_EVENT intent indicates subscriber info.
- * <p>Value: <code>String</code> containing subscriber information.</p>
- */
- public static final String EXTRA_SUBSCRIBER_INFO =
- "android.bluetooth.headsetclient.extra.SUBSCRIBER_INFO";
-
- /**
- * Extra for AG_CALL_CHANGED intent indicates the
- * {@link BluetoothHeadsetClientCall} object that has changed.
- */
- public static final String EXTRA_CALL =
- "android.bluetooth.headsetclient.extra.CALL";
-
- /**
- * Extra for ACTION_LAST_VTAG intent.
- * <p>Value: <code>String</code> representing phone number
- * corresponding to last voice tag recorded on AG</p>
- */
- public static final String EXTRA_NUMBER =
- "android.bluetooth.headsetclient.extra.NUMBER";
-
- /**
- * Extra for ACTION_RESULT intent that shows the result code of
- * last issued action.
- * <p>Possible results:
- * {@link #ACTION_RESULT_OK},
- * {@link #ACTION_RESULT_ERROR},
- * {@link #ACTION_RESULT_ERROR_NO_CARRIER},
- * {@link #ACTION_RESULT_ERROR_BUSY},
- * {@link #ACTION_RESULT_ERROR_NO_ANSWER},
- * {@link #ACTION_RESULT_ERROR_DELAYED},
- * {@link #ACTION_RESULT_ERROR_BLACKLISTED},
- * {@link #ACTION_RESULT_ERROR_CME}</p>
- */
- public static final String EXTRA_RESULT_CODE =
- "android.bluetooth.headsetclient.extra.RESULT_CODE";
-
- /**
- * Extra for ACTION_RESULT intent that shows the extended result code of
- * last issued action.
- * <p>Value: <code>Integer</code> - error code.</p>
- */
- public static final String EXTRA_CME_CODE =
- "android.bluetooth.headsetclient.extra.CME_CODE";
-
- /**
- * Extra for VENDOR_SPECIFIC_HEADSETCLIENT_EVENT intent that
- * indicates vendor ID.
- */
- public static final String EXTRA_VENDOR_ID =
- "android.bluetooth.headsetclient.extra.VENDOR_ID";
-
- /**
- * Extra for VENDOR_SPECIFIC_HEADSETCLIENT_EVENT intent that
- * indicates vendor event code.
- */
- public static final String EXTRA_VENDOR_EVENT_CODE =
- "android.bluetooth.headsetclient.extra.VENDOR_EVENT_CODE";
-
- /**
- * Extra for VENDOR_SPECIFIC_HEADSETCLIENT_EVENT intent that
- * contains full vendor event including event code and full arguments.
- */
- public static final String EXTRA_VENDOR_EVENT_FULL_ARGS =
- "android.bluetooth.headsetclient.extra.VENDOR_EVENT_FULL_ARGS";
-
-
- /* Extras for AG_FEATURES, extras type is boolean */
- // TODO verify if all of those are actually useful
- /**
- * AG feature: three way calling.
- */
- public static final String EXTRA_AG_FEATURE_3WAY_CALLING =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_3WAY_CALLING";
- /**
- * AG feature: voice recognition.
- */
- public static final String EXTRA_AG_FEATURE_VOICE_RECOGNITION =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_VOICE_RECOGNITION";
- /**
- * AG feature: fetching phone number for voice tagging procedure.
- */
- public static final String EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT";
- /**
- * AG feature: ability to reject incoming call.
- */
- public static final String EXTRA_AG_FEATURE_REJECT_CALL =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_REJECT_CALL";
- /**
- * AG feature: enhanced call handling (terminate specific call, private consultation).
- */
- public static final String EXTRA_AG_FEATURE_ECC =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ECC";
- /**
- * AG feature: response and hold.
- */
- public static final String EXTRA_AG_FEATURE_RESPONSE_AND_HOLD =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RESPONSE_AND_HOLD";
- /**
- * AG call handling feature: accept held or waiting call in three way calling scenarios.
- */
- public static final String EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL";
- /**
- * AG call handling feature: release held or waiting call in three way calling scenarios.
- */
- public static final String EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL";
- /**
- * AG call handling feature: release active call and accept held or waiting call in three way
- * calling scenarios.
- */
- public static final String EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT";
- /**
- * AG call handling feature: merge two calls, held and active - multi party conference mode.
- */
- public static final String EXTRA_AG_FEATURE_MERGE =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_MERGE";
- /**
- * AG call handling feature: merge calls and disconnect from multi party
- * conversation leaving peers connected to each other.
- * Note that this feature needs to be supported by mobile network operator
- * as it requires connection and billing transfer.
- */
- public static final String EXTRA_AG_FEATURE_MERGE_AND_DETACH =
- "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_MERGE_AND_DETACH";
-
- /* Action result codes */
- public static final int ACTION_RESULT_OK = 0;
- public static final int ACTION_RESULT_ERROR = 1;
- public static final int ACTION_RESULT_ERROR_NO_CARRIER = 2;
- public static final int ACTION_RESULT_ERROR_BUSY = 3;
- public static final int ACTION_RESULT_ERROR_NO_ANSWER = 4;
- public static final int ACTION_RESULT_ERROR_DELAYED = 5;
- public static final int ACTION_RESULT_ERROR_BLACKLISTED = 6;
- public static final int ACTION_RESULT_ERROR_CME = 7;
-
- /* Detailed CME error codes */
- public static final int CME_PHONE_FAILURE = 0;
- public static final int CME_NO_CONNECTION_TO_PHONE = 1;
- public static final int CME_OPERATION_NOT_ALLOWED = 3;
- public static final int CME_OPERATION_NOT_SUPPORTED = 4;
- public static final int CME_PHSIM_PIN_REQUIRED = 5;
- public static final int CME_PHFSIM_PIN_REQUIRED = 6;
- public static final int CME_PHFSIM_PUK_REQUIRED = 7;
- public static final int CME_SIM_NOT_INSERTED = 10;
- public static final int CME_SIM_PIN_REQUIRED = 11;
- public static final int CME_SIM_PUK_REQUIRED = 12;
- public static final int CME_SIM_FAILURE = 13;
- public static final int CME_SIM_BUSY = 14;
- public static final int CME_SIM_WRONG = 15;
- public static final int CME_INCORRECT_PASSWORD = 16;
- public static final int CME_SIM_PIN2_REQUIRED = 17;
- public static final int CME_SIM_PUK2_REQUIRED = 18;
- public static final int CME_MEMORY_FULL = 20;
- public static final int CME_INVALID_INDEX = 21;
- public static final int CME_NOT_FOUND = 22;
- public static final int CME_MEMORY_FAILURE = 23;
- public static final int CME_TEXT_STRING_TOO_LONG = 24;
- public static final int CME_INVALID_CHARACTER_IN_TEXT_STRING = 25;
- public static final int CME_DIAL_STRING_TOO_LONG = 26;
- public static final int CME_INVALID_CHARACTER_IN_DIAL_STRING = 27;
- public static final int CME_NO_NETWORK_SERVICE = 30;
- public static final int CME_NETWORK_TIMEOUT = 31;
- public static final int CME_EMERGENCY_SERVICE_ONLY = 32;
- public static final int CME_NO_SIMULTANOUS_VOIP_CS_CALLS = 33;
- public static final int CME_NOT_SUPPORTED_FOR_VOIP = 34;
- public static final int CME_SIP_RESPONSE_CODE = 35;
- public static final int CME_NETWORK_PERSONALIZATION_PIN_REQUIRED = 40;
- public static final int CME_NETWORK_PERSONALIZATION_PUK_REQUIRED = 41;
- public static final int CME_NETWORK_SUBSET_PERSONALIZATION_PIN_REQUIRED = 42;
- public static final int CME_NETWORK_SUBSET_PERSONALIZATION_PUK_REQUIRED = 43;
- public static final int CME_SERVICE_PROVIDER_PERSONALIZATION_PIN_REQUIRED = 44;
- public static final int CME_SERVICE_PROVIDER_PERSONALIZATION_PUK_REQUIRED = 45;
- public static final int CME_CORPORATE_PERSONALIZATION_PIN_REQUIRED = 46;
- public static final int CME_CORPORATE_PERSONALIZATION_PUK_REQUIRED = 47;
- public static final int CME_HIDDEN_KEY_REQUIRED = 48;
- public static final int CME_EAP_NOT_SUPPORTED = 49;
- public static final int CME_INCORRECT_PARAMETERS = 50;
-
- /* Action policy for other calls when accepting call */
- public static final int CALL_ACCEPT_NONE = 0;
- public static final int CALL_ACCEPT_HOLD = 1;
- public static final int CALL_ACCEPT_TERMINATE = 2;
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothHeadsetClient> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.HEADSET_CLIENT,
- "BluetoothHeadsetClient", IBluetoothHeadsetClient.class.getName()) {
- @Override
- public IBluetoothHeadsetClient getServiceInterface(IBinder service) {
- return IBluetoothHeadsetClient.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothHeadsetClient proxy object.
- */
- /* package */ BluetoothHeadsetClient(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- /**
- * Close the connection to the backing service.
- * Other public functions of BluetoothHeadsetClient will return default error
- * results once close() has been called. Multiple invocations of close()
- * are ok.
- */
- /*package*/ void close() {
- if (VDBG) log("close()");
- mProfileConnector.disconnect();
- }
-
- private IBluetoothHeadsetClient getService() {
- return mProfileConnector.getService();
- }
-
- /**
- * Connects to remote device.
- *
- * Currently, the system supports only 1 connection. So, in case of the
- * second connection, this implementation will disconnect already connected
- * device automatically and will process the new one.
- *
- * @param device a remote device we want connect to
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} intent.
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean connect(BluetoothDevice device) {
- if (DBG) log("connect(" + device + ")");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Disconnects remote device
- *
- * @param device a remote device we want disconnect
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} intent.
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) log("disconnect(" + device + ")");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Return the list of connected remote devices
- *
- * @return list of connected devices; empty list if nothing is connected.
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
- if (VDBG) log("getConnectedDevices()");
- final IBluetoothHeadsetClient service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns list of remote devices in a particular state
- *
- * @param states collection of states
- * @return list of devices that state matches the states listed in <code>states</code>; empty
- * list if nothing matches the <code>states</code>
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothHeadsetClient service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns state of the <code>device</code>
- *
- * @param device a remote device
- * @return the state of connection of the device
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
- if (VDBG) log("getConnectionState(" + device + ")");
- final IBluetoothHeadsetClient service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set priority of the profile
- *
- * <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
- *
- * @param device Paired bluetooth device
- * @param priority
- * @return true if priority is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setPriority(BluetoothDevice device, int priority) {
- if (DBG) log("setPriority(" + device + ", " + priority + ")");
- return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the priority of the profile.
- *
- * <p> The priority can be any of:
- * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * @param device Bluetooth device
- * @return priority of the device
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getPriority(BluetoothDevice device) {
- if (VDBG) log("getPriority(" + device + ")");
- return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- final IBluetoothHeadsetClient service = getService();
- final @ConnectionPolicy int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Starts voice recognition.
- *
- * @param device remote device
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_AG_EVENT} intent.
- *
- * <p>Feature required for successful execution is being reported by: {@link
- * #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. This method invocation will fail silently when feature
- * is not supported.</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean startVoiceRecognition(BluetoothDevice device) {
- if (DBG) log("startVoiceRecognition()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.startVoiceRecognition(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Send vendor specific AT command.
- *
- * @param device remote device
- * @param vendorId vendor number by Bluetooth SIG
- * @param atCommand command to be sent. It start with + prefix and only one command at one time.
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean sendVendorAtCommand(BluetoothDevice device, int vendorId, String atCommand) {
- if (DBG) log("sendVendorSpecificCommand()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.sendVendorAtCommand(device, vendorId, atCommand, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Stops voice recognition.
- *
- * @param device remote device
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_AG_EVENT} intent.
- *
- * <p>Feature required for successful execution is being reported by: {@link
- * #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. This method invocation will fail silently when feature
- * is not supported.</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean stopVoiceRecognition(BluetoothDevice device) {
- if (DBG) log("stopVoiceRecognition()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.stopVoiceRecognition(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns list of all calls in any state.
- *
- * @param device remote device
- * @return list of calls; empty list if none call exists
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
- if (DBG) log("getCurrentCalls()");
- final IBluetoothHeadsetClient service = getService();
- final List<BluetoothHeadsetClientCall> defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<List<BluetoothHeadsetClientCall>> recv =
- new SynchronousResultReceiver();
- service.getCurrentCalls(device, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns list of current values of AG indicators.
- *
- * @param device remote device
- * @return bundle of AG indicators; null if device is not in CONNECTED state
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public Bundle getCurrentAgEvents(BluetoothDevice device) {
- if (DBG) log("getCurrentAgEvents()");
- final IBluetoothHeadsetClient service = getService();
- final Bundle defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Bundle> recv = new SynchronousResultReceiver();
- service.getCurrentAgEvents(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Accepts a call
- *
- * @param device remote device
- * @param flag action policy while accepting a call. Possible values {@link #CALL_ACCEPT_NONE},
- * {@link #CALL_ACCEPT_HOLD}, {@link #CALL_ACCEPT_TERMINATE}
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean acceptCall(BluetoothDevice device, int flag) {
- if (DBG) log("acceptCall()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.acceptCall(device, flag, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Holds a call.
- *
- * @param device remote device
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean holdCall(BluetoothDevice device) {
- if (DBG) log("holdCall()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.holdCall(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Rejects a call.
- *
- * @param device remote device
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
- *
- * <p>Feature required for successful execution is being reported by: {@link
- * #EXTRA_AG_FEATURE_REJECT_CALL}. This method invocation will fail silently when feature is not
- * supported.</p>
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean rejectCall(BluetoothDevice device) {
- if (DBG) log("rejectCall()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.rejectCall(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Terminates a specified call.
- *
- * Works only when Extended Call Control is supported by Audio Gateway.
- *
- * @param device remote device
- * @param call Handle of call obtained in {@link #dial(BluetoothDevice, String)} or obtained via
- * {@link #ACTION_CALL_CHANGED}. {@code call} may be null in which case we will hangup all active
- * calls.
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
- *
- * <p>Feature required for successful execution is being reported by: {@link
- * #EXTRA_AG_FEATURE_ECC}. This method invocation will fail silently when feature is not
- * supported.</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
- if (DBG) log("terminateCall()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.terminateCall(device, call, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Enters private mode with a specified call.
- *
- * Works only when Extended Call Control is supported by Audio Gateway.
- *
- * @param device remote device
- * @param index index of the call to connect in private mode
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
- *
- * <p>Feature required for successful execution is being reported by: {@link
- * #EXTRA_AG_FEATURE_ECC}. This method invocation will fail silently when feature is not
- * supported.</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean enterPrivateMode(BluetoothDevice device, int index) {
- if (DBG) log("enterPrivateMode()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.enterPrivateMode(device, index, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Performs explicit call transfer.
- *
- * That means connect other calls and disconnect.
- *
- * @param device remote device
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
- *
- * <p>Feature required for successful execution is being reported by: {@link
- * #EXTRA_AG_FEATURE_MERGE_AND_DETACH}. This method invocation will fail silently when feature
- * is not supported.</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean explicitCallTransfer(BluetoothDevice device) {
- if (DBG) log("explicitCallTransfer()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.explicitCallTransfer(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Places a call with specified number.
- *
- * @param device remote device
- * @param number valid phone number
- * @return <code>{@link BluetoothHeadsetClientCall} call</code> if command has been issued
- * successfully; <code>{@link null}</code> otherwise; upon completion HFP sends {@link
- * #ACTION_CALL_CHANGED} intent in case of success; {@link #ACTION_RESULT} is sent otherwise;
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
- if (DBG) log("dial()");
- final IBluetoothHeadsetClient service = getService();
- final BluetoothHeadsetClientCall defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<BluetoothHeadsetClientCall> recv =
- new SynchronousResultReceiver();
- service.dial(device, number, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Sends DTMF code.
- *
- * Possible code values : 0,1,2,3,4,5,6,7,8,9,A,B,C,D,*,#
- *
- * @param device remote device
- * @param code ASCII code
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_RESULT} intent;
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean sendDTMF(BluetoothDevice device, byte code) {
- if (DBG) log("sendDTMF()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.sendDTMF(device, code, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get a number corresponding to last voice tag recorded on AG.
- *
- * @param device remote device
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_LAST_VTAG} or {@link #ACTION_RESULT}
- * intent;
- *
- * <p>Feature required for successful execution is being reported by: {@link
- * #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT}. This method invocation will fail silently when
- * feature is not supported.</p>
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean getLastVoiceTagNumber(BluetoothDevice device) {
- if (DBG) log("getLastVoiceTagNumber()");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.getLastVoiceTagNumber(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns current audio state of Audio Gateway.
- *
- * Note: This is an internal function and shouldn't be exposed
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getAudioState(BluetoothDevice device) {
- if (VDBG) log("getAudioState");
- final IBluetoothHeadsetClient service = getService();
- final int defaultValue = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getAudioState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- } else {
- return defaultValue;
- }
- return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
- }
-
- /**
- * Sets whether audio routing is allowed.
- *
- * @param device remote device
- * @param allowed if routing is allowed to the device Note: This is an internal function and
- * shouldn't be exposed
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {
- if (VDBG) log("setAudioRouteAllowed");
- final IBluetoothHeadsetClient service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.setAudioRouteAllowed(device, allowed, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Returns whether audio routing is allowed.
- *
- * @param device remote device
- * @return whether the command succeeded Note: This is an internal function and shouldn't be
- * exposed
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean getAudioRouteAllowed(BluetoothDevice device) {
- if (VDBG) log("getAudioRouteAllowed");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.getAudioRouteAllowed(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiates a connection of audio channel.
- *
- * It setup SCO channel with remote connected Handsfree AG device.
- *
- * @param device remote device
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean connectAudio(BluetoothDevice device) {
- if (VDBG) log("connectAudio");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connectAudio(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Disconnects audio channel.
- *
- * It tears down the SCO channel from remote AG device.
- *
- * @param device remote device
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnectAudio(BluetoothDevice device) {
- if (VDBG) log("disconnectAudio");
- final IBluetoothHeadsetClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnectAudio(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get Audio Gateway features
- *
- * @param device remote device
- * @return bundle of AG features; null if no service or AG not connected
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public Bundle getCurrentAgFeatures(BluetoothDevice device) {
- if (VDBG) log("getCurrentAgFeatures");
- final IBluetoothHeadsetClient service = getService();
- final Bundle defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Bundle> recv = new SynchronousResultReceiver();
- service.getCurrentAgFeatures(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private boolean isEnabled() {
- return mAdapter.getState() == BluetoothAdapter.STATE_ON;
- }
-
- private static boolean isValidDevice(BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
deleted file mode 100644
index 032b507..0000000
--- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
-
-import java.util.UUID;
-
-/**
- * This class represents a single call, its state and properties.
- * It implements {@link Parcelable} for inter-process message passing.
- *
- * @hide
- */
-public final class BluetoothHeadsetClientCall implements Parcelable, Attributable {
-
- /* Call state */
- /**
- * Call is active.
- */
- public static final int CALL_STATE_ACTIVE = 0;
- /**
- * Call is in held state.
- */
- public static final int CALL_STATE_HELD = 1;
- /**
- * Outgoing call that is being dialed right now.
- */
- public static final int CALL_STATE_DIALING = 2;
- /**
- * Outgoing call that remote party has already been alerted about.
- */
- public static final int CALL_STATE_ALERTING = 3;
- /**
- * Incoming call that can be accepted or rejected.
- */
- public static final int CALL_STATE_INCOMING = 4;
- /**
- * Waiting call state when there is already an active call.
- */
- public static final int CALL_STATE_WAITING = 5;
- /**
- * Call that has been held by response and hold
- * (see Bluetooth specification for further references).
- */
- public static final int CALL_STATE_HELD_BY_RESPONSE_AND_HOLD = 6;
- /**
- * Call that has been already terminated and should not be referenced as a valid call.
- */
- public static final int CALL_STATE_TERMINATED = 7;
-
- private final BluetoothDevice mDevice;
- private final int mId;
- private int mState;
- private String mNumber;
- private boolean mMultiParty;
- private final boolean mOutgoing;
- private final UUID mUUID;
- private final long mCreationElapsedMilli;
- private final boolean mInBandRing;
-
- /**
- * Creates BluetoothHeadsetClientCall instance.
- */
- public BluetoothHeadsetClientCall(BluetoothDevice device, int id, int state, String number,
- boolean multiParty, boolean outgoing, boolean inBandRing) {
- this(device, id, UUID.randomUUID(), state, number, multiParty, outgoing, inBandRing);
- }
-
- public BluetoothHeadsetClientCall(BluetoothDevice device, int id, UUID uuid, int state,
- String number, boolean multiParty, boolean outgoing, boolean inBandRing) {
- mDevice = device;
- mId = id;
- mUUID = uuid;
- mState = state;
- mNumber = number != null ? number : "";
- mMultiParty = multiParty;
- mOutgoing = outgoing;
- mInBandRing = inBandRing;
- mCreationElapsedMilli = SystemClock.elapsedRealtime();
- }
-
- /** {@hide} */
- public void setAttributionSource(@NonNull AttributionSource attributionSource) {
- Attributable.setAttributionSource(mDevice, attributionSource);
- }
-
- /**
- * Sets call's state.
- *
- * <p>Note: This is an internal function and shouldn't be exposed</p>
- *
- * @param state new call state.
- */
- public void setState(int state) {
- mState = state;
- }
-
- /**
- * Sets call's number.
- *
- * <p>Note: This is an internal function and shouldn't be exposed</p>
- *
- * @param number String representing phone number.
- */
- public void setNumber(String number) {
- mNumber = number;
- }
-
- /**
- * Sets this call as multi party call.
- *
- * <p>Note: This is an internal function and shouldn't be exposed</p>
- *
- * @param multiParty if <code>true</code> sets this call as a part of multi party conference.
- */
- public void setMultiParty(boolean multiParty) {
- mMultiParty = multiParty;
- }
-
- /**
- * Gets call's device.
- *
- * @return call device.
- */
- public BluetoothDevice getDevice() {
- return mDevice;
- }
-
- /**
- * Gets call's Id.
- *
- * @return call id.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int getId() {
- return mId;
- }
-
- /**
- * Gets call's UUID.
- *
- * @return call uuid
- * @hide
- */
- public UUID getUUID() {
- return mUUID;
- }
-
- /**
- * Gets call's current state.
- *
- * @return state of this particular phone call.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int getState() {
- return mState;
- }
-
- /**
- * Gets call's number.
- *
- * @return string representing phone number.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public String getNumber() {
- return mNumber;
- }
-
- /**
- * Gets call's creation time in millis since epoch.
- *
- * @return long representing the creation time.
- */
- public long getCreationElapsedMilli() {
- return mCreationElapsedMilli;
- }
-
- /**
- * Checks if call is an active call in a conference mode (aka multi party).
- *
- * @return <code>true</code> if call is a multi party call, <code>false</code> otherwise.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public boolean isMultiParty() {
- return mMultiParty;
- }
-
- /**
- * Checks if this call is an outgoing call.
- *
- * @return <code>true</code> if its outgoing call, <code>false</code> otherwise.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public boolean isOutgoing() {
- return mOutgoing;
- }
-
- /**
- * Checks if the ringtone will be generated by the connected phone
- *
- * @return <code>true</code> if in band ring is enabled, <code>false</code> otherwise.
- */
- public boolean isInBandRing() {
- return mInBandRing;
- }
-
-
- @Override
- public String toString() {
- return toString(false);
- }
-
- /**
- * Generate a log string for this call
- * @param loggable whether device address should be logged
- * @return log string
- */
- public String toString(boolean loggable) {
- StringBuilder builder = new StringBuilder("BluetoothHeadsetClientCall{mDevice: ");
- builder.append(loggable ? mDevice : mDevice.hashCode());
- builder.append(", mId: ");
- builder.append(mId);
- builder.append(", mUUID: ");
- builder.append(mUUID);
- builder.append(", mState: ");
- switch (mState) {
- case CALL_STATE_ACTIVE:
- builder.append("ACTIVE");
- break;
- case CALL_STATE_HELD:
- builder.append("HELD");
- break;
- case CALL_STATE_DIALING:
- builder.append("DIALING");
- break;
- case CALL_STATE_ALERTING:
- builder.append("ALERTING");
- break;
- case CALL_STATE_INCOMING:
- builder.append("INCOMING");
- break;
- case CALL_STATE_WAITING:
- builder.append("WAITING");
- break;
- case CALL_STATE_HELD_BY_RESPONSE_AND_HOLD:
- builder.append("HELD_BY_RESPONSE_AND_HOLD");
- break;
- case CALL_STATE_TERMINATED:
- builder.append("TERMINATED");
- break;
- default:
- builder.append(mState);
- break;
- }
- builder.append(", mNumber: ");
- builder.append(loggable ? mNumber : mNumber.hashCode());
- builder.append(", mMultiParty: ");
- builder.append(mMultiParty);
- builder.append(", mOutgoing: ");
- builder.append(mOutgoing);
- builder.append(", mInBandRing: ");
- builder.append(mInBandRing);
- builder.append("}");
- return builder.toString();
- }
-
- /**
- * {@link Parcelable.Creator} interface implementation.
- */
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothHeadsetClientCall> CREATOR =
- new Parcelable.Creator<BluetoothHeadsetClientCall>() {
- @Override
- public BluetoothHeadsetClientCall createFromParcel(Parcel in) {
- return new BluetoothHeadsetClientCall((BluetoothDevice) in.readParcelable(null),
- in.readInt(), UUID.fromString(in.readString()), in.readInt(),
- in.readString(), in.readInt() == 1, in.readInt() == 1,
- in.readInt() == 1);
- }
-
- @Override
- public BluetoothHeadsetClientCall[] newArray(int size) {
- return new BluetoothHeadsetClientCall[size];
- }
- };
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(mDevice, 0);
- out.writeInt(mId);
- out.writeString(mUUID.toString());
- out.writeInt(mState);
- out.writeString(mNumber);
- out.writeInt(mMultiParty ? 1 : 0);
- out.writeInt(mOutgoing ? 1 : 0);
- out.writeInt(mInBandRing ? 1 : 0);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
deleted file mode 100644
index 65f68a9..0000000
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ /dev/null
@@ -1,386 +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 android.bluetooth;
-
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Public API for Bluetooth Health Profile.
- *
- * <p>BluetoothHealth is a proxy object for controlling the Bluetooth
- * Service via IPC.
- *
- * <p> How to connect to a health device which is acting in the source role.
- * <li> Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothHealth proxy object. </li>
- * <li> Create an {@link BluetoothHealth} callback and call
- * {@link #registerSinkAppConfiguration} to register an application
- * configuration </li>
- * <li> Pair with the remote device. This currently needs to be done manually
- * from Bluetooth Settings </li>
- * <li> Connect to a health device using {@link #connectChannelToSource}. Some
- * devices will connect the channel automatically. The {@link BluetoothHealth}
- * callback will inform the application of channel state change. </li>
- * <li> Use the file descriptor provided with a connected channel to read and
- * write data to the health channel. </li>
- * <li> The received data needs to be interpreted using a health manager which
- * implements the IEEE 11073-xxxxx specifications.
- * <li> When done, close the health channel by calling {@link #disconnectChannel}
- * and unregister the application configuration calling
- * {@link #unregisterAppConfiguration}
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New apps
- * should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
-@Deprecated
-public final class BluetoothHealth implements BluetoothProfile {
- private static final String TAG = "BluetoothHealth";
- /**
- * Health Profile Source Role - the health device.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int SOURCE_ROLE = 1 << 0;
-
- /**
- * Health Profile Sink Role the device talking to the health device.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int SINK_ROLE = 1 << 1;
-
- /**
- * Health Profile - Channel Type used - Reliable
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int CHANNEL_TYPE_RELIABLE = 10;
-
- /**
- * Health Profile - Channel Type used - Streaming
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int CHANNEL_TYPE_STREAMING = 11;
-
- /**
- * Hide auto-created default constructor
- * @hide
- */
- BluetoothHealth() {}
-
- /**
- * Register an application configuration that acts as a Health SINK.
- * This is the configuration that will be used to communicate with health devices
- * which will act as the {@link #SOURCE_ROLE}. This is an asynchronous call and so
- * the callback is used to notify success or failure if the function returns true.
- *
- * @param name The friendly name associated with the application or configuration.
- * @param dataType The dataType of the Source role of Health Profile to which the sink wants to
- * connect to.
- * @param callback A callback to indicate success or failure of the registration and all
- * operations done on this application configuration.
- * @return If true, callback will be called.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public boolean registerSinkAppConfiguration(String name, int dataType,
- BluetoothHealthCallback callback) {
- Log.e(TAG, "registerSinkAppConfiguration(): BluetoothHealth is deprecated");
- return false;
- }
-
- /**
- * Unregister an application configuration that has been registered using
- * {@link #registerSinkAppConfiguration}
- *
- * @param config The health app configuration
- * @return Success or failure.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
- Log.e(TAG, "unregisterAppConfiguration(): BluetoothHealth is deprecated");
- return false;
- }
-
- /**
- * Connect to a health device which has the {@link #SOURCE_ROLE}.
- * This is an asynchronous call. If this function returns true, the callback
- * associated with the application configuration will be called.
- *
- * @param device The remote Bluetooth device.
- * @param config The application configuration which has been registered using {@link
- * #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) }
- * @return If true, the callback associated with the application config will be called.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public boolean connectChannelToSource(BluetoothDevice device,
- BluetoothHealthAppConfiguration config) {
- Log.e(TAG, "connectChannelToSource(): BluetoothHealth is deprecated");
- return false;
- }
-
- /**
- * Disconnect a connected health channel.
- * This is an asynchronous call. If this function returns true, the callback
- * associated with the application configuration will be called.
- *
- * @param device The remote Bluetooth device.
- * @param config The application configuration which has been registered using {@link
- * #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) }
- * @param channelId The channel id associated with the channel
- * @return If true, the callback associated with the application config will be called.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public boolean disconnectChannel(BluetoothDevice device,
- BluetoothHealthAppConfiguration config, int channelId) {
- Log.e(TAG, "disconnectChannel(): BluetoothHealth is deprecated");
- return false;
- }
-
- /**
- * Get the file descriptor of the main channel associated with the remote device
- * and application configuration.
- *
- * <p> Its the responsibility of the caller to close the ParcelFileDescriptor
- * when done.
- *
- * @param device The remote Bluetooth health device
- * @param config The application configuration
- * @return null on failure, ParcelFileDescriptor on success.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
- BluetoothHealthAppConfiguration config) {
- Log.e(TAG, "getMainChannelFd(): BluetoothHealth is deprecated");
- return null;
- }
-
- /**
- * Get the current connection state of the profile.
- *
- * This is not specific to any application configuration but represents the connection
- * state of the local Bluetooth adapter with the remote device. This can be used
- * by applications like status bar which would just like to know the state of the
- * local adapter.
- *
- * @param device Remote bluetooth device.
- * @return State of the profile connection. One of {@link #STATE_CONNECTED}, {@link
- * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
- */
- @Override
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public int getConnectionState(BluetoothDevice device) {
- Log.e(TAG, "getConnectionState(): BluetoothHealth is deprecated");
- return STATE_DISCONNECTED;
- }
-
- /**
- * Get connected devices for the health profile.
- *
- * <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
- *
- * This is not specific to any application configuration but represents the connection
- * state of the local Bluetooth adapter for this profile. This can be used
- * by applications like status bar which would just like to know the state of the
- * local adapter.
- *
- * @return List of devices. The list will be empty on error.
- */
- @Override
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public List<BluetoothDevice> getConnectedDevices() {
- Log.e(TAG, "getConnectedDevices(): BluetoothHealth is deprecated");
- return new ArrayList<>();
- }
-
- /**
- * Get a list of devices that match any of the given connection
- * states.
- *
- * <p> If none of the devices match any of the given states,
- * an empty list will be returned.
- *
- * <p>This is not specific to any application configuration but represents the connection
- * state of the local Bluetooth adapter for this profile. This can be used
- * by applications like status bar which would just like to know the state of the
- * local adapter.
- *
- * @param states Array of states. States can be one of {@link #STATE_CONNECTED}, {@link
- * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
- * @return List of devices. The list will be empty on error.
- */
- @Override
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- Log.e(TAG, "getDevicesMatchingConnectionStates(): BluetoothHealth is deprecated");
- return new ArrayList<>();
- }
-
- /** Health Channel Connection State - Disconnected
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int STATE_CHANNEL_DISCONNECTED = 0;
- /** Health Channel Connection State - Connecting
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int STATE_CHANNEL_CONNECTING = 1;
- /** Health Channel Connection State - Connected
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int STATE_CHANNEL_CONNECTED = 2;
- /** Health Channel Connection State - Disconnecting
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int STATE_CHANNEL_DISCONNECTING = 3;
-
- /** Health App Configuration registration success
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0;
- /** Health App Configuration registration failure
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int APP_CONFIG_REGISTRATION_FAILURE = 1;
- /** Health App Configuration un-registration success
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2;
- /** Health App Configuration un-registration failure
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3;
-}
diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
deleted file mode 100644
index 2f66df2..0000000
--- a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
+++ /dev/null
@@ -1,115 +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 android.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * The Bluetooth Health Application Configuration that is used in conjunction with
- * the {@link BluetoothHealth} class. This class represents an application configuration
- * that the Bluetooth Health third party application will register to communicate with the
- * remote Bluetooth health device.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
-@Deprecated
-public final class BluetoothHealthAppConfiguration implements Parcelable {
-
- /**
- * Hide auto-created default constructor
- * @hide
- */
- BluetoothHealthAppConfiguration() {}
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- /**
- * Return the data type associated with this application configuration.
- *
- * @return dataType
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public int getDataType() {
- return 0;
- }
-
- /**
- * Return the name of the application configuration.
- *
- * @return String name
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public String getName() {
- return null;
- }
-
- /**
- * Return the role associated with this application configuration.
- *
- * @return One of {@link BluetoothHealth#SOURCE_ROLE} or {@link BluetoothHealth#SINK_ROLE}
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public int getRole() {
- return 0;
- }
-
- /**
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothHealthAppConfiguration> CREATOR =
- new Parcelable.Creator<BluetoothHealthAppConfiguration>() {
- @Override
- public BluetoothHealthAppConfiguration createFromParcel(Parcel in) {
- return new BluetoothHealthAppConfiguration();
- }
-
- @Override
- public BluetoothHealthAppConfiguration[] newArray(int size) {
- return new BluetoothHealthAppConfiguration[size];
- }
- };
-
- @Override
- public void writeToParcel(Parcel out, int flags) {}
-}
diff --git a/core/java/android/bluetooth/BluetoothHealthCallback.java b/core/java/android/bluetooth/BluetoothHealthCallback.java
deleted file mode 100644
index 4769212..0000000
--- a/core/java/android/bluetooth/BluetoothHealthCallback.java
+++ /dev/null
@@ -1,88 +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 android.bluetooth;
-
-import android.annotation.BinderThread;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-/**
- * This abstract class is used to implement {@link BluetoothHealth} callbacks.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
-@Deprecated
-public abstract class BluetoothHealthCallback {
- private static final String TAG = "BluetoothHealthCallback";
-
- /**
- * Callback to inform change in registration state of the health
- * application.
- * <p> This callback is called on the binder thread (not on the UI thread)
- *
- * @param config Bluetooth Health app configuration
- * @param status Success or failure of the registration or unregistration calls. Can be one of
- * {@link BluetoothHealth#APP_CONFIG_REGISTRATION_SUCCESS} or {@link
- * BluetoothHealth#APP_CONFIG_REGISTRATION_FAILURE} or
- * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_SUCCESS}
- * or {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_FAILURE}
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @BinderThread
- @Deprecated
- public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config,
- int status) {
- Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + "Status: " + status);
- }
-
- /**
- * Callback to inform change in channel state.
- * <p> Its the responsibility of the implementor of this callback to close the
- * parcel file descriptor when done. This callback is called on the Binder
- * thread (not the UI thread)
- *
- * @param config The Health app configutation
- * @param device The Bluetooth Device
- * @param prevState The previous state of the channel
- * @param newState The new state of the channel.
- * @param fd The Parcel File Descriptor when the channel state is connected.
- * @param channelId The id associated with the channel. This id will be used in future calls
- * like when disconnecting the channel.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @BinderThread
- @Deprecated
- public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
- BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd,
- int channelId) {
- Log.d(TAG, "onHealthChannelStateChange: " + config + "Device: " + device
- + "prevState:" + prevState + "newState:" + newState + "ParcelFd:" + fd
- + "ChannelId:" + channelId);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
deleted file mode 100644
index 339a75f..0000000
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the Hearing Aid profile.
- *
- * <p>BluetoothHearingAid is a proxy object for controlling the Bluetooth Hearing Aid
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothHearingAid proxy object.
- *
- * <p> Android only supports one set of connected Bluetooth Hearing Aid device at a time. Each
- * method is protected with its appropriate permission.
- */
-public final class BluetoothHearingAid implements BluetoothProfile {
- private static final String TAG = "BluetoothHearingAid";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Intent used to broadcast the change in connection state of the Hearing Aid
- * profile. Please note that in the binaural case, there will be two different LE devices for
- * the left and right side and each device will have their own connection state changes.S
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED";
-
- /**
- * Intent used to broadcast the selection of a connected device as active.
- *
- * <p>This intent will have one extra:
- * <ul>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
- * be null if no device is active. </li>
- * </ul>
- *
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_ACTIVE_DEVICE_CHANGED =
- "android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED";
-
- /**
- * This device represents Left Hearing Aid.
- *
- * @hide
- */
- public static final int SIDE_LEFT = IBluetoothHearingAid.SIDE_LEFT;
-
- /**
- * This device represents Right Hearing Aid.
- *
- * @hide
- */
- public static final int SIDE_RIGHT = IBluetoothHearingAid.SIDE_RIGHT;
-
- /**
- * This device is Monaural.
- *
- * @hide
- */
- public static final int MODE_MONAURAL = IBluetoothHearingAid.MODE_MONAURAL;
-
- /**
- * This device is Binaural (should receive only left or right audio).
- *
- * @hide
- */
- public static final int MODE_BINAURAL = IBluetoothHearingAid.MODE_BINAURAL;
-
- /**
- * Indicates the HiSyncID could not be read and is unavailable.
- *
- * @hide
- */
- public static final long HI_SYNC_ID_INVALID = IBluetoothHearingAid.HI_SYNC_ID_INVALID;
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothHearingAid> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.HEARING_AID,
- "BluetoothHearingAid", IBluetoothHearingAid.class.getName()) {
- @Override
- public IBluetoothHearingAid getServiceInterface(IBinder service) {
- return IBluetoothHearingAid.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothHearingAid proxy object for interacting with the local
- * Bluetooth Hearing Aid service.
- */
- /* package */ BluetoothHearingAid(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- /*package*/ void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothHearingAid getService() {
- return mProfileConnector.getService();
- }
-
- /**
- * Initiate connection to a profile of the remote bluetooth device.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is already connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that
- * connection state intent for the profile will be broadcasted with
- * the state. Users can get the connection state of the profile
- * from this intent.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean connect(BluetoothDevice device) {
- if (DBG) log("connect(" + device + ")");
- final IBluetoothHearingAid service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate disconnection from a profile
- *
- * <p> This API will return false in scenarios like the profile on the
- * Bluetooth device is not in connected state etc. When this API returns,
- * true, it is guaranteed that the connection state change
- * intent will be broadcasted with the state. Users can get the
- * disconnection state of the profile from this intent.
- *
- * <p> If the disconnection is initiated by a remote device, the state
- * will transition from {@link #STATE_CONNECTED} to
- * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
- * host (local) device the state will transition from
- * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
- * state {@link #STATE_DISCONNECTED}. The transition to
- * {@link #STATE_DISCONNECTING} can be used to distinguish between the
- * two scenarios.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) log("disconnect(" + device + ")");
- final IBluetoothHearingAid service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @NonNull List<BluetoothDevice> getConnectedDevices() {
- if (VDBG) log("getConnectedDevices()");
- final IBluetoothHearingAid service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
- @NonNull int[] states) {
- if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothHearingAid service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @BluetoothProfile.BtProfileState int getConnectionState(
- @NonNull BluetoothDevice device) {
- if (VDBG) log("getState(" + device + ")");
- final IBluetoothHearingAid service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Select a connected device as active.
- *
- * The active device selection is per profile. An active device's
- * purpose is profile-specific. For example, Hearing Aid audio
- * streaming is to the active Hearing Aid device. If a remote device
- * is not connected, it cannot be selected as active.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is not connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that the
- * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
- * with the active device.
- *
- * @param device the remote Bluetooth device. Could be null to clear
- * the active device and stop streaming audio to a Bluetooth device.
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public boolean setActiveDevice(@Nullable BluetoothDevice device) {
- if (DBG) log("setActiveDevice(" + device + ")");
- final IBluetoothHearingAid service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && ((device == null) || isValidDevice(device))) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setActiveDevice(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the connected physical Hearing Aid devices that are active
- *
- * @return the list of active devices. The first element is the left active
- * device; the second element is the right active device. If either or both side
- * is not active, it will be null on that position. Returns empty list on error.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @NonNull List<BluetoothDevice> getActiveDevices() {
- if (VDBG) log("getActiveDevices()");
- final IBluetoothHearingAid service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getActiveDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set priority of the profile
- *
- * <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
- *
- * @param device Paired bluetooth device
- * @param priority
- * @return true if priority is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setPriority(BluetoothDevice device, int priority) {
- if (DBG) log("setPriority(" + device + ", " + priority + ")");
- return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- verifyDeviceNotNull(device, "setConnectionPolicy");
- final IBluetoothHearingAid service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the priority of the profile.
- *
- * <p> The priority can be any of:
- * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * @param device Bluetooth device
- * @return priority of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public int getPriority(BluetoothDevice device) {
- if (VDBG) log("getPriority(" + device + ")");
- return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- verifyDeviceNotNull(device, "getConnectionPolicy");
- final IBluetoothHearingAid service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Helper for converting a state to a string.
- *
- * For debug use only - strings are not internationalized.
- *
- * @hide
- */
- public static String stateToString(int state) {
- switch (state) {
- case STATE_DISCONNECTED:
- return "disconnected";
- case STATE_CONNECTING:
- return "connecting";
- case STATE_CONNECTED:
- return "connected";
- case STATE_DISCONNECTING:
- return "disconnecting";
- default:
- return "<unknown state " + state + ">";
- }
- }
-
- /**
- * Tells remote device to set an absolute volume.
- *
- * @param volume Absolute volume to be set on remote
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void setVolume(int volume) {
- if (DBG) Log.d(TAG, "setVolume(" + volume + ")");
- final IBluetoothHearingAid service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.setVolume(volume, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Get the HiSyncId (unique hearing aid device identifier) of the device.
- *
- * <a href=https://source.android.com/devices/bluetooth/asha#hisyncid>HiSyncId documentation
- * can be found here</a>
- *
- * @param device Bluetooth device
- * @return the HiSyncId of the device
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public long getHiSyncId(@NonNull BluetoothDevice device) {
- if (VDBG) log("getHiSyncId(" + device + ")");
- verifyDeviceNotNull(device, "getConnectionPolicy");
- final IBluetoothHearingAid service = getService();
- final long defaultValue = HI_SYNC_ID_INVALID;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Long> recv = new SynchronousResultReceiver();
- service.getHiSyncId(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the side of the device.
- *
- * @param device Bluetooth device.
- * @return SIDE_LEFT or SIDE_RIGHT
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getDeviceSide(BluetoothDevice device) {
- if (VDBG) log("getDeviceSide(" + device + ")");
- final IBluetoothHearingAid service = getService();
- final int defaultValue = SIDE_LEFT;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getDeviceSide(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the mode of the device.
- *
- * @param device Bluetooth device
- * @return MODE_MONAURAL or MODE_BINAURAL
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getDeviceMode(BluetoothDevice device) {
- if (VDBG) log("getDeviceMode(" + device + ")");
- final IBluetoothHearingAid service = getService();
- final int defaultValue = MODE_MONAURAL;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getDeviceMode(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private boolean isEnabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
- return false;
- }
-
- private void verifyDeviceNotNull(BluetoothDevice device, String methodName) {
- if (device == null) {
- Log.e(TAG, methodName + ": device param is null");
- throw new IllegalArgumentException("Device cannot be null");
- }
- }
-
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
deleted file mode 100644
index 44a355b..0000000
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ /dev/null
@@ -1,848 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Provides the public APIs to control the Bluetooth HID Device profile.
- *
- * <p>BluetoothHidDevice is a proxy object for controlling the Bluetooth HID Device Service via IPC.
- * Use {@link BluetoothAdapter#getProfileProxy} to get the BluetoothHidDevice proxy object.
- */
-public final class BluetoothHidDevice implements BluetoothProfile {
- private static final String TAG = BluetoothHidDevice.class.getSimpleName();
- private static final boolean DBG = false;
-
- /**
- * Intent used to broadcast the change in connection state of the Input Host profile.
- *
- * <p>This intent will have 3 extras:
- *
- * <ul>
- * <li>{@link #EXTRA_STATE} - The current state of the profile.
- * <li>{@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.
- * <li>{@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of {@link
- * #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, {@link #STATE_CONNECTED}, {@link
- * #STATE_DISCONNECTING}.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED";
-
- /**
- * Constant representing unspecified HID device subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS1_NONE = (byte) 0x00;
- /**
- * Constant representing keyboard subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40;
- /**
- * Constant representing mouse subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS1_MOUSE = (byte) 0x80;
- /**
- * Constant representing combo keyboard and mouse subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS1_COMBO = (byte) 0xC0;
-
- /**
- * Constant representing uncategorized HID device subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS2_UNCATEGORIZED = (byte) 0x00;
- /**
- * Constant representing joystick subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS2_JOYSTICK = (byte) 0x01;
- /**
- * Constant representing gamepad subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02;
- /**
- * Constant representing remote control subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03;
- /**
- * Constant representing sensing device subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04;
- /**
- * Constant representing digitizer tablet subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS2_DIGITIZER_TABLET = (byte) 0x05;
- /**
- * Constant representing card reader subclass.
- *
- * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)
- */
- public static final byte SUBCLASS2_CARD_READER = (byte) 0x06;
-
- /**
- * Constant representing HID Input Report type.
- *
- * @see Callback#onGetReport(BluetoothDevice, byte, byte, int)
- * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
- * @see Callback#onInterruptData(BluetoothDevice, byte, byte[])
- */
- public static final byte REPORT_TYPE_INPUT = (byte) 1;
- /**
- * Constant representing HID Output Report type.
- *
- * @see Callback#onGetReport(BluetoothDevice, byte, byte, int)
- * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
- * @see Callback#onInterruptData(BluetoothDevice, byte, byte[])
- */
- public static final byte REPORT_TYPE_OUTPUT = (byte) 2;
- /**
- * Constant representing HID Feature Report type.
- *
- * @see Callback#onGetReport(BluetoothDevice, byte, byte, int)
- * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
- * @see Callback#onInterruptData(BluetoothDevice, byte, byte[])
- */
- public static final byte REPORT_TYPE_FEATURE = (byte) 3;
-
- /**
- * Constant representing success response for Set Report.
- *
- * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
- */
- public static final byte ERROR_RSP_SUCCESS = (byte) 0;
- /**
- * Constant representing error response for Set Report due to "not ready".
- *
- * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
- */
- public static final byte ERROR_RSP_NOT_READY = (byte) 1;
- /**
- * Constant representing error response for Set Report due to "invalid report ID".
- *
- * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
- */
- public static final byte ERROR_RSP_INVALID_RPT_ID = (byte) 2;
- /**
- * Constant representing error response for Set Report due to "unsupported request".
- *
- * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
- */
- public static final byte ERROR_RSP_UNSUPPORTED_REQ = (byte) 3;
- /**
- * Constant representing error response for Set Report due to "invalid parameter".
- *
- * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
- */
- public static final byte ERROR_RSP_INVALID_PARAM = (byte) 4;
- /**
- * Constant representing error response for Set Report with unknown reason.
- *
- * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
- */
- public static final byte ERROR_RSP_UNKNOWN = (byte) 14;
-
- /**
- * Constant representing boot protocol mode used set by host. Default is always {@link
- * #PROTOCOL_REPORT_MODE} unless notified otherwise.
- *
- * @see Callback#onSetProtocol(BluetoothDevice, byte)
- */
- public static final byte PROTOCOL_BOOT_MODE = (byte) 0;
- /**
- * Constant representing report protocol mode used set by host. Default is always {@link
- * #PROTOCOL_REPORT_MODE} unless notified otherwise.
- *
- * @see Callback#onSetProtocol(BluetoothDevice, byte)
- */
- public static final byte PROTOCOL_REPORT_MODE = (byte) 1;
-
- /**
- * The template class that applications use to call callback functions on events from the HID
- * host. Callback functions are wrapped in this class and registered to the Android system
- * during app registration.
- */
- public abstract static class Callback {
-
- private static final String TAG = "BluetoothHidDevCallback";
-
- /**
- * Callback called when application registration state changes. Usually it's called due to
- * either {@link BluetoothHidDevice#registerApp (String, String, String, byte, byte[],
- * Executor, Callback)} or {@link BluetoothHidDevice#unregisterApp()} , but can be also
- * unsolicited in case e.g. Bluetooth was turned off in which case application is
- * unregistered automatically.
- *
- * @param pluggedDevice {@link BluetoothDevice} object which represents host that currently
- * has Virtual Cable established with device. Only valid when application is registered,
- * can be <code>null</code>.
- * @param registered <code>true</code> if application is registered, <code>false</code>
- * otherwise.
- */
- public void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered) {
- Log.d(
- TAG,
- "onAppStatusChanged: pluggedDevice="
- + pluggedDevice
- + " registered="
- + registered);
- }
-
- /**
- * Callback called when connection state with remote host was changed. Application can
- * assume than Virtual Cable is established when called with {@link
- * BluetoothProfile#STATE_CONNECTED} <code>state</code>.
- *
- * @param device {@link BluetoothDevice} object representing host device which connection
- * state was changed.
- * @param state Connection state as defined in {@link BluetoothProfile}.
- */
- public void onConnectionStateChanged(BluetoothDevice device, int state) {
- Log.d(TAG, "onConnectionStateChanged: device=" + device + " state=" + state);
- }
-
- /**
- * Callback called when GET_REPORT is received from remote host. Should be replied by
- * application using {@link BluetoothHidDevice#replyReport(BluetoothDevice, byte, byte,
- * byte[])}.
- *
- * @param type Requested Report Type.
- * @param id Requested Report Id, can be 0 if no Report Id are defined in descriptor.
- * @param bufferSize Requested buffer size, application shall respond with at least given
- * number of bytes.
- */
- public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
- Log.d(
- TAG,
- "onGetReport: device="
- + device
- + " type="
- + type
- + " id="
- + id
- + " bufferSize="
- + bufferSize);
- }
-
- /**
- * Callback called when SET_REPORT is received from remote host. In case received data are
- * invalid, application shall respond with {@link
- * BluetoothHidDevice#reportError(BluetoothDevice, byte)}.
- *
- * @param type Report Type.
- * @param id Report Id.
- * @param data Report data.
- */
- public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
- Log.d(TAG, "onSetReport: device=" + device + " type=" + type + " id=" + id);
- }
-
- /**
- * Callback called when SET_PROTOCOL is received from remote host. Application shall use
- * this information to send only reports valid for given protocol mode. By default, {@link
- * BluetoothHidDevice#PROTOCOL_REPORT_MODE} shall be assumed.
- *
- * @param protocol Protocol Mode.
- */
- public void onSetProtocol(BluetoothDevice device, byte protocol) {
- Log.d(TAG, "onSetProtocol: device=" + device + " protocol=" + protocol);
- }
-
- /**
- * Callback called when report data is received over interrupt channel. Report Type is
- * assumed to be {@link BluetoothHidDevice#REPORT_TYPE_OUTPUT}.
- *
- * @param reportId Report Id.
- * @param data Report data.
- */
- public void onInterruptData(BluetoothDevice device, byte reportId, byte[] data) {
- Log.d(TAG, "onInterruptData: device=" + device + " reportId=" + reportId);
- }
-
- /**
- * Callback called when Virtual Cable is removed. After this callback is received connection
- * will be disconnected automatically.
- */
- public void onVirtualCableUnplug(BluetoothDevice device) {
- Log.d(TAG, "onVirtualCableUnplug: device=" + device);
- }
- }
-
- private static class CallbackWrapper extends IBluetoothHidDeviceCallback.Stub {
-
- private final Executor mExecutor;
- private final Callback mCallback;
- private final AttributionSource mAttributionSource;
-
- CallbackWrapper(Executor executor, Callback callback, AttributionSource attributionSource) {
- mExecutor = executor;
- mCallback = callback;
- mAttributionSource = attributionSource;
- }
-
- @Override
- public void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered) {
- Attributable.setAttributionSource(pluggedDevice, mAttributionSource);
- final long token = clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onAppStatusChanged(pluggedDevice, registered));
- } finally {
- restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void onConnectionStateChanged(BluetoothDevice device, int state) {
- Attributable.setAttributionSource(device, mAttributionSource);
- final long token = clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onConnectionStateChanged(device, state));
- } finally {
- restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
- Attributable.setAttributionSource(device, mAttributionSource);
- final long token = clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onGetReport(device, type, id, bufferSize));
- } finally {
- restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
- Attributable.setAttributionSource(device, mAttributionSource);
- final long token = clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onSetReport(device, type, id, data));
- } finally {
- restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void onSetProtocol(BluetoothDevice device, byte protocol) {
- Attributable.setAttributionSource(device, mAttributionSource);
- final long token = clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onSetProtocol(device, protocol));
- } finally {
- restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void onInterruptData(BluetoothDevice device, byte reportId, byte[] data) {
- Attributable.setAttributionSource(device, mAttributionSource);
- final long token = clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onInterruptData(device, reportId, data));
- } finally {
- restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void onVirtualCableUnplug(BluetoothDevice device) {
- Attributable.setAttributionSource(device, mAttributionSource);
- final long token = clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onVirtualCableUnplug(device));
- } finally {
- restoreCallingIdentity(token);
- }
- }
- }
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothHidDevice> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.HID_DEVICE,
- "BluetoothHidDevice", IBluetoothHidDevice.class.getName()) {
- @Override
- public IBluetoothHidDevice getServiceInterface(IBinder service) {
- return IBluetoothHidDevice.Stub.asInterface(service);
- }
- };
-
- BluetoothHidDevice(Context context, ServiceListener listener, BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothHidDevice getService() {
- return mProfileConnector.getService();
- }
-
- /** {@inheritDoc} */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
- final IBluetoothHidDevice service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /** {@inheritDoc} */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- final IBluetoothHidDevice service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /** {@inheritDoc} */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
- final IBluetoothHidDevice service = getService();
- final int defaultValue = STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Registers application to be used for HID device. Connections to HID Device are only possible
- * when application is registered. Only one application can be registered at one time. When an
- * application is registered, the HID Host service will be disabled until it is unregistered.
- * When no longer used, application should be unregistered using {@link #unregisterApp()}. The
- * app will be automatically unregistered if it is not foreground. The registration status
- * should be tracked by the application by handling callback from Callback#onAppStatusChanged.
- * The app registration status is not related to the return value of this method.
- *
- * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of HID Device SDP record. The HID
- * Device SDP record is required.
- * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of Incoming QoS Settings. The
- * Incoming QoS Settings is not required. Use null or default
- * BluetoothHidDeviceAppQosSettings.Builder for default values.
- * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of Outgoing QoS Settings. The
- * Outgoing QoS Settings is not required. Use null or default
- * BluetoothHidDeviceAppQosSettings.Builder for default values.
- * @param executor {@link Executor} object on which callback will be executed. The Executor
- * object is required.
- * @param callback {@link Callback} object to which callback messages will be sent. The Callback
- * object is required.
- * @return true if the command is successfully sent; otherwise false.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean registerApp(
- BluetoothHidDeviceAppSdpSettings sdp,
- BluetoothHidDeviceAppQosSettings inQos,
- BluetoothHidDeviceAppQosSettings outQos,
- Executor executor,
- Callback callback) {
- boolean result = false;
-
- if (sdp == null) {
- throw new IllegalArgumentException("sdp parameter cannot be null");
- }
-
- if (executor == null) {
- throw new IllegalArgumentException("executor parameter cannot be null");
- }
-
- if (callback == null) {
- throw new IllegalArgumentException("callback parameter cannot be null");
- }
-
- final IBluetoothHidDevice service = getService();
- final boolean defaultValue = result;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- CallbackWrapper cbw = new CallbackWrapper(executor, callback, mAttributionSource);
- service.registerApp(sdp, inQos, outQos, cbw, mAttributionSource, recv);
- result = recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Unregisters application. Active connection will be disconnected and no new connections will
- * be allowed until registered again using {@link #registerApp
- * (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
- * BluetoothHidDeviceAppQosSettings, Executor, Callback)}. The registration status should be
- * tracked by the application by handling callback from Callback#onAppStatusChanged. The app
- * registration status is not related to the return value of this method.
- *
- * @return true if the command is successfully sent; otherwise false.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean unregisterApp() {
- final IBluetoothHidDevice service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.unregisterApp(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Sends report to remote host using interrupt channel.
- *
- * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id are not defined in
- * descriptor.
- * @param data Report data, not including Report Id.
- * @return true if the command is successfully sent; otherwise false.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
- final IBluetoothHidDevice service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.sendReport(device, id, data, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Sends report to remote host as reply for GET_REPORT request from {@link
- * Callback#onGetReport(BluetoothDevice, byte, byte, int)}.
- *
- * @param type Report Type, as in request.
- * @param id Report Id, as in request.
- * @param data Report data, not including Report Id.
- * @return true if the command is successfully sent; otherwise false.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
- final IBluetoothHidDevice service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.replyReport(device, type, id, data, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Sends error handshake message as reply for invalid SET_REPORT request from {@link
- * Callback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
- *
- * @param error Error to be sent for SET_REPORT via HANDSHAKE.
- * @return true if the command is successfully sent; otherwise false.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean reportError(BluetoothDevice device, byte error) {
- final IBluetoothHidDevice service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.reportError(device, error, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Gets the application name of the current HidDeviceService user.
- *
- * @return the current user name, or empty string if cannot get the name
- * {@hide}
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public String getUserAppName() {
- final IBluetoothHidDevice service = getService();
- final String defaultValue = "";
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<String> recv = new SynchronousResultReceiver();
- service.getUserAppName(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiates connection to host which is currently paired with this device. If the application
- * is not registered, #connect(BluetoothDevice) will fail. The connection state should be
- * tracked by the application by handling callback from Callback#onConnectionStateChanged. The
- * connection state is not related to the return value of this method.
- *
- * @return true if the command is successfully sent; otherwise false.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean connect(BluetoothDevice device) {
- final IBluetoothHidDevice service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Disconnects from currently connected host. The connection state should be tracked by the
- * application by handling callback from Callback#onConnectionStateChanged. The connection state
- * is not related to the return value of this method.
- *
- * @return true if the command is successfully sent; otherwise false.
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnect(BluetoothDevice device) {
- final IBluetoothHidDevice service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Connects Hid Device if connectionPolicy is {@link BluetoothProfile#CONNECTION_POLICY_ALLOWED}
- * and disconnects Hid device if connectionPolicy is
- * {@link BluetoothProfile#CONNECTION_POLICY_FORBIDDEN}.
- *
- * <p> The device should already be paired.
- * Connection policy can be one of:
- * {@link BluetoothProfile#CONNECTION_POLICY_ALLOWED},
- * {@link BluetoothProfile#CONNECTION_POLICY_FORBIDDEN},
- * {@link BluetoothProfile#CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy determines whether hid device should be connected or disconnected
- * @return true if hid device is connected or disconnected, false otherwise
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothHidDevice service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private boolean isEnabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
- return false;
- }
-
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
- }
-
- private static void log(String msg) {
- if (DBG) {
- Log.d(TAG, msg);
- }
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
deleted file mode 100644
index b21ebe5..0000000
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents the Quality of Service (QoS) settings for a Bluetooth HID Device application.
- *
- * <p>The BluetoothHidDevice framework will update the L2CAP QoS settings for the app during
- * registration.
- *
- * <p>{@see BluetoothHidDevice}
- */
-public final class BluetoothHidDeviceAppQosSettings implements Parcelable {
-
- private final int mServiceType;
- private final int mTokenRate;
- private final int mTokenBucketSize;
- private final int mPeakBandwidth;
- private final int mLatency;
- private final int mDelayVariation;
-
- public static final int SERVICE_NO_TRAFFIC = 0x00;
- public static final int SERVICE_BEST_EFFORT = 0x01;
- public static final int SERVICE_GUARANTEED = 0x02;
-
- public static final int MAX = (int) 0xffffffff;
-
- /**
- * Create a BluetoothHidDeviceAppQosSettings object for the Bluetooth L2CAP channel. The QoS
- * Settings is optional. Please refer to Bluetooth HID Specfication v1.1.1 Section 5.2 and
- * Appendix D for parameters.
- *
- * @param serviceType L2CAP service type, default = SERVICE_BEST_EFFORT
- * @param tokenRate L2CAP token rate, default = 0
- * @param tokenBucketSize L2CAP token bucket size, default = 0
- * @param peakBandwidth L2CAP peak bandwidth, default = 0
- * @param latency L2CAP latency, default = MAX
- * @param delayVariation L2CAP delay variation, default = MAX
- */
- public BluetoothHidDeviceAppQosSettings(
- int serviceType,
- int tokenRate,
- int tokenBucketSize,
- int peakBandwidth,
- int latency,
- int delayVariation) {
- mServiceType = serviceType;
- mTokenRate = tokenRate;
- mTokenBucketSize = tokenBucketSize;
- mPeakBandwidth = peakBandwidth;
- mLatency = latency;
- mDelayVariation = delayVariation;
- }
-
- public int getServiceType() {
- return mServiceType;
- }
-
- public int getTokenRate() {
- return mTokenRate;
- }
-
- public int getTokenBucketSize() {
- return mTokenBucketSize;
- }
-
- public int getPeakBandwidth() {
- return mPeakBandwidth;
- }
-
- public int getLatency() {
- return mLatency;
- }
-
- public int getDelayVariation() {
- return mDelayVariation;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothHidDeviceAppQosSettings> CREATOR =
- new Parcelable.Creator<BluetoothHidDeviceAppQosSettings>() {
-
- @Override
- public BluetoothHidDeviceAppQosSettings createFromParcel(Parcel in) {
-
- return new BluetoothHidDeviceAppQosSettings(
- in.readInt(),
- in.readInt(),
- in.readInt(),
- in.readInt(),
- in.readInt(),
- in.readInt());
- }
-
- @Override
- public BluetoothHidDeviceAppQosSettings[] newArray(int size) {
- return new BluetoothHidDeviceAppQosSettings[size];
- }
- };
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mServiceType);
- out.writeInt(mTokenRate);
- out.writeInt(mTokenBucketSize);
- out.writeInt(mPeakBandwidth);
- out.writeInt(mLatency);
- out.writeInt(mDelayVariation);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
deleted file mode 100644
index 4e1a2aa..0000000
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.EventLog;
-
-
-/**
- * Represents the Service Discovery Protocol (SDP) settings for a Bluetooth HID Device application.
- *
- * <p>The BluetoothHidDevice framework adds the SDP record during app registration, so that the
- * Android device can be discovered as a Bluetooth HID Device.
- *
- * <p>{@see BluetoothHidDevice}
- */
-public final class BluetoothHidDeviceAppSdpSettings implements Parcelable {
-
- private static final int MAX_DESCRIPTOR_SIZE = 2048;
-
- private final String mName;
- private final String mDescription;
- private final String mProvider;
- private final byte mSubclass;
- private final byte[] mDescriptors;
-
- /**
- * Create a BluetoothHidDeviceAppSdpSettings object for the Bluetooth SDP record.
- *
- * @param name Name of this Bluetooth HID device. Maximum length is 50 bytes.
- * @param description Description for this Bluetooth HID device. Maximum length is 50 bytes.
- * @param provider Provider of this Bluetooth HID device. Maximum length is 50 bytes.
- * @param subclass Subclass of this Bluetooth HID device. See <a
- * href="www.usb.org/developers/hidpage/HID1_11.pdf">
- * www.usb.org/developers/hidpage/HID1_11.pdf Section 4.2</a>
- * @param descriptors Descriptors of this Bluetooth HID device. See <a
- * href="www.usb.org/developers/hidpage/HID1_11.pdf">
- * www.usb.org/developers/hidpage/HID1_11.pdf Chapter 6</a> Maximum length is 2048 bytes.
- */
- public BluetoothHidDeviceAppSdpSettings(
- String name, String description, String provider, byte subclass, byte[] descriptors) {
- mName = name;
- mDescription = description;
- mProvider = provider;
- mSubclass = subclass;
-
- if (descriptors == null || descriptors.length > MAX_DESCRIPTOR_SIZE) {
- EventLog.writeEvent(0x534e4554, "119819889", -1, "");
- throw new IllegalArgumentException("descriptors must be not null and shorter than "
- + MAX_DESCRIPTOR_SIZE);
- }
- mDescriptors = descriptors.clone();
- }
-
- public String getName() {
- return mName;
- }
-
- public String getDescription() {
- return mDescription;
- }
-
- public String getProvider() {
- return mProvider;
- }
-
- public byte getSubclass() {
- return mSubclass;
- }
-
- public byte[] getDescriptors() {
- return mDescriptors;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothHidDeviceAppSdpSettings> CREATOR =
- new Parcelable.Creator<BluetoothHidDeviceAppSdpSettings>() {
-
- @Override
- public BluetoothHidDeviceAppSdpSettings createFromParcel(Parcel in) {
-
- return new BluetoothHidDeviceAppSdpSettings(
- in.readString(),
- in.readString(),
- in.readString(),
- in.readByte(),
- in.createByteArray());
- }
-
- @Override
- public BluetoothHidDeviceAppSdpSettings[] newArray(int size) {
- return new BluetoothHidDeviceAppSdpSettings[size];
- }
- };
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mName);
- out.writeString(mDescription);
- out.writeString(mProvider);
- out.writeByte(mSubclass);
- out.writeByteArray(mDescriptors);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
deleted file mode 100644
index ecbeddf..0000000
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ /dev/null
@@ -1,831 +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 android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-
-/**
- * This class provides the public APIs to control the Bluetooth Input
- * Device Profile.
- *
- * <p>BluetoothHidHost is a proxy object for controlling the Bluetooth
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothHidHost proxy object.
- *
- * <p>Each method is protected with its appropriate permission.
- *
- * @hide
- */
-@SystemApi
-public final class BluetoothHidHost implements BluetoothProfile {
- private static final String TAG = "BluetoothHidHost";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Intent used to broadcast the change in connection state of the Input
- * Device profile.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- */
- @SuppressLint("ActionValue")
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
-
- /**
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PROTOCOL_MODE_CHANGED =
- "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED";
-
- /**
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_HANDSHAKE =
- "android.bluetooth.input.profile.action.HANDSHAKE";
-
- /**
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_REPORT =
- "android.bluetooth.input.profile.action.REPORT";
-
- /**
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
- "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
-
- /**
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_IDLE_TIME_CHANGED =
- "android.bluetooth.input.profile.action.IDLE_TIME_CHANGED";
-
- /**
- * Return codes for the connect and disconnect Bluez / Dbus calls.
- *
- * @hide
- */
- public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
-
- /**
- * @hide
- */
- public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
-
- /**
- * @hide
- */
- public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
-
- /**
- * @hide
- */
- public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
-
- /**
- * @hide
- */
- public static final int INPUT_OPERATION_SUCCESS = 5004;
-
- /**
- * @hide
- */
- public static final int PROTOCOL_REPORT_MODE = 0;
-
- /**
- * @hide
- */
- public static final int PROTOCOL_BOOT_MODE = 1;
-
- /**
- * @hide
- */
- public static final int PROTOCOL_UNSUPPORTED_MODE = 255;
-
- /* int reportType, int reportType, int bufferSize */
- /**
- * @hide
- */
- public static final byte REPORT_TYPE_INPUT = 1;
-
- /**
- * @hide
- */
- public static final byte REPORT_TYPE_OUTPUT = 2;
-
- /**
- * @hide
- */
- public static final byte REPORT_TYPE_FEATURE = 3;
-
- /**
- * @hide
- */
- public static final int VIRTUAL_UNPLUG_STATUS_SUCCESS = 0;
-
- /**
- * @hide
- */
- public static final int VIRTUAL_UNPLUG_STATUS_FAIL = 1;
-
- /**
- * @hide
- */
- public static final String EXTRA_PROTOCOL_MODE =
- "android.bluetooth.BluetoothHidHost.extra.PROTOCOL_MODE";
-
- /**
- * @hide
- */
- public static final String EXTRA_REPORT_TYPE =
- "android.bluetooth.BluetoothHidHost.extra.REPORT_TYPE";
-
- /**
- * @hide
- */
- public static final String EXTRA_REPORT_ID =
- "android.bluetooth.BluetoothHidHost.extra.REPORT_ID";
-
- /**
- * @hide
- */
- public static final String EXTRA_REPORT_BUFFER_SIZE =
- "android.bluetooth.BluetoothHidHost.extra.REPORT_BUFFER_SIZE";
-
- /**
- * @hide
- */
- public static final String EXTRA_REPORT = "android.bluetooth.BluetoothHidHost.extra.REPORT";
-
- /**
- * @hide
- */
- public static final String EXTRA_STATUS = "android.bluetooth.BluetoothHidHost.extra.STATUS";
-
- /**
- * @hide
- */
- public static final String EXTRA_VIRTUAL_UNPLUG_STATUS =
- "android.bluetooth.BluetoothHidHost.extra.VIRTUAL_UNPLUG_STATUS";
-
- /**
- * @hide
- */
- public static final String EXTRA_IDLE_TIME =
- "android.bluetooth.BluetoothHidHost.extra.IDLE_TIME";
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothHidHost> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.HID_HOST,
- "BluetoothHidHost", IBluetoothHidHost.class.getName()) {
- @Override
- public IBluetoothHidHost getServiceInterface(IBinder service) {
- return IBluetoothHidHost.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothHidHost proxy object for interacting with the local
- * Bluetooth Service which handles the InputDevice profile
- */
- /* package */ BluetoothHidHost(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- /*package*/ void close() {
- if (VDBG) log("close()");
- mProfileConnector.disconnect();
- }
-
- private IBluetoothHidHost getService() {
- return mProfileConnector.getService();
- }
-
- /**
- * Initiate connection to a profile of the remote bluetooth device.
- *
- * <p> The system supports connection to multiple input devices.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is already connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that
- * connection state intent for the profile will be broadcasted with
- * the state. Users can get the connection state of the profile
- * from this intent.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean connect(BluetoothDevice device) {
- if (DBG) log("connect(" + device + ")");
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate disconnection from a profile
- *
- * <p> This API will return false in scenarios like the profile on the
- * Bluetooth device is not in connected state etc. When this API returns,
- * true, it is guaranteed that the connection state change
- * intent will be broadcasted with the state. Users can get the
- * disconnection state of the profile from this intent.
- *
- * <p> If the disconnection is initiated by a remote device, the state
- * will transition from {@link #STATE_CONNECTED} to
- * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
- * host (local) device the state will transition from
- * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
- * state {@link #STATE_DISCONNECTED}. The transition to
- * {@link #STATE_DISCONNECTING} can be used to distinguish between the
- * two scenarios.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) log("disconnect(" + device + ")");
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
- @SystemApi
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public @NonNull List<BluetoothDevice> getConnectedDevices() {
- if (VDBG) log("getConnectedDevices()");
- final IBluetoothHidHost service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothHidHost service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
- @SystemApi
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(@NonNull BluetoothDevice device) {
- if (VDBG) log("getState(" + device + ")");
- if (device == null) {
- throw new IllegalArgumentException("device must not be null");
- }
- final IBluetoothHidHost service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set priority of the profile
- *
- * <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
- *
- * @param device Paired bluetooth device
- * @param priority
- * @return true if priority is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setPriority(BluetoothDevice device, int priority) {
- if (DBG) log("setPriority(" + device + ", " + priority + ")");
- return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- if (device == null) {
- throw new IllegalArgumentException("device must not be null");
- }
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the priority of the profile.
- *
- * <p> The priority can be any of:
- * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * @param device Bluetooth device
- * @return priority of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public int getPriority(BluetoothDevice device) {
- if (VDBG) log("getPriority(" + device + ")");
- return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- if (device == null) {
- throw new IllegalArgumentException("device must not be null");
- }
- final IBluetoothHidHost service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private boolean isEnabled() {
- return mAdapter.getState() == BluetoothAdapter.STATE_ON;
- }
-
- private static boolean isValidDevice(BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-
- /**
- * Initiate virtual unplug for a HID input device.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean virtualUnplug(BluetoothDevice device) {
- if (DBG) log("virtualUnplug(" + device + ")");
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.virtualUnplug(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Send Get_Protocol_Mode command to the connected HID input device.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean getProtocolMode(BluetoothDevice device) {
- if (VDBG) log("getProtocolMode(" + device + ")");
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.getProtocolMode(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Send Set_Protocol_Mode command to the connected HID input device.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
- if (DBG) log("setProtocolMode(" + device + ")");
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setProtocolMode(device, protocolMode, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Send Get_Report command to the connected HID input device.
- *
- * @param device Remote Bluetooth Device
- * @param reportType Report type
- * @param reportId Report ID
- * @param bufferSize Report receiving buffer size
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean getReport(BluetoothDevice device, byte reportType, byte reportId,
- int bufferSize) {
- if (VDBG) {
- log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
- + "bufferSize=" + bufferSize);
- }
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.getReport(device, reportType, reportId, bufferSize, mAttributionSource,
- recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Send Set_Report command to the connected HID input device.
- *
- * @param device Remote Bluetooth Device
- * @param reportType Report type
- * @param report Report receiving buffer size
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setReport(BluetoothDevice device, byte reportType, String report) {
- if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setReport(device, reportType, report, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Send Send_Data command to the connected HID input device.
- *
- * @param device Remote Bluetooth Device
- * @param report Report to send
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean sendData(BluetoothDevice device, String report) {
- if (DBG) log("sendData(" + device + "), report=" + report);
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.sendData(device, report, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Send Get_Idle_Time command to the connected HID input device.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean getIdleTime(BluetoothDevice device) {
- if (DBG) log("getIdletime(" + device + ")");
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.getIdleTime(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Send Set_Idle_Time command to the connected HID input device.
- *
- * @param device Remote Bluetooth Device
- * @param idleTime Idle time to be set on HID Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
- if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
- final IBluetoothHidHost service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setIdleTime(device, idleTime, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothInputStream.java b/core/java/android/bluetooth/BluetoothInputStream.java
deleted file mode 100644
index 95f9229..0000000
--- a/core/java/android/bluetooth/BluetoothInputStream.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2009 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.bluetooth;
-
-import android.annotation.SuppressLint;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * BluetoothInputStream.
- *
- * Used to write to a Bluetooth socket.
- *
- * @hide
- */
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-/*package*/ final class BluetoothInputStream extends InputStream {
- private BluetoothSocket mSocket;
-
- /*package*/ BluetoothInputStream(BluetoothSocket s) {
- mSocket = s;
- }
-
- /**
- * Return number of bytes available before this stream will block.
- */
- public int available() throws IOException {
- return mSocket.available();
- }
-
- public void close() throws IOException {
- mSocket.close();
- }
-
- /**
- * Reads a single byte from this stream and returns it as an integer in the
- * range from 0 to 255. Returns -1 if the end of the stream has been
- * reached. Blocks until one byte has been read, the end of the source
- * stream is detected or an exception is thrown.
- *
- * @return the byte read or -1 if the end of stream has been reached.
- * @throws IOException if the stream is closed or another IOException occurs.
- * @since Android 1.5
- */
- public int read() throws IOException {
- byte[] b = new byte[1];
- int ret = mSocket.read(b, 0, 1);
- if (ret == 1) {
- return (int) b[0] & 0xff;
- } else {
- return -1;
- }
- }
-
- /**
- * Reads at most {@code length} bytes from this stream and stores them in
- * the byte array {@code b} starting at {@code offset}.
- *
- * @param b the byte array in which to store the bytes read.
- * @param offset the initial position in {@code buffer} to store the bytes read from this
- * stream.
- * @param length the maximum number of bytes to store in {@code b}.
- * @return the number of bytes actually read or -1 if the end of the stream has been reached.
- * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code length < 0}, or if {@code
- * offset + length} is greater than the length of {@code b}.
- * @throws IOException if the stream is closed or another IOException occurs.
- * @since Android 1.5
- */
- public int read(byte[] b, int offset, int length) throws IOException {
- if (b == null) {
- throw new NullPointerException("byte array is null");
- }
- if ((offset | length) < 0 || length > b.length - offset) {
- throw new ArrayIndexOutOfBoundsException("invalid offset or length");
- }
- return mSocket.read(b, offset, length);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothLeAudio.java b/core/java/android/bluetooth/BluetoothLeAudio.java
deleted file mode 100644
index 15db686..0000000
--- a/core/java/android/bluetooth/BluetoothLeAudio.java
+++ /dev/null
@@ -1,829 +0,0 @@
-/*
- * Copyright 2020 HIMSA II K/S - www.himsa.com.
- * Represented by EHIMA - www.ehima.com
- *
- * 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.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the LeAudio profile.
- *
- * <p>BluetoothLeAudio is a proxy object for controlling the Bluetooth LE Audio
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothLeAudio proxy object.
- *
- * <p> Android only supports one set of connected Bluetooth LeAudio device at a time. Each
- * method is protected with its appropriate permission.
- */
-public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
- private static final String TAG = "BluetoothLeAudio";
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
-
- private CloseGuard mCloseGuard;
-
- /**
- * Intent used to broadcast the change in connection state of the LeAudio
- * profile. Please note that in the binaural case, there will be two different LE devices for
- * the left and right side and each device will have their own connection state changes.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED =
- "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
-
- /**
- * Intent used to broadcast the selection of a connected device as active.
- *
- * <p>This intent will have one extra:
- * <ul>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
- * be null if no device is active. </li>
- * </ul>
- *
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED =
- "android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED";
-
- /**
- * Intent used to broadcast group node status information.
- *
- * <p>This intent will have 3 extra:
- * <ul>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
- * be null if no device is active. </li>
- * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
- * <li> {@link #EXTRA_LE_AUDIO_GROUP_NODE_STATUS} - Group node status. </li>
- * </ul>
- *
- * @hide
- */
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED =
- "android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED";
-
-
- /**
- * Intent used to broadcast group status information.
- *
- * <p>This intent will have 4 extra:
- * <ul>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
- * be null if no device is active. </li>
- * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
- * <li> {@link #EXTRA_LE_AUDIO_GROUP_STATUS} - Group status. </li>
- * </ul>
- *
- * @hide
- */
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_LE_AUDIO_GROUP_STATUS_CHANGED =
- "android.bluetooth.action.LE_AUDIO_GROUP_STATUS_CHANGED";
-
- /**
- * Intent used to broadcast group audio configuration changed information.
- *
- * <p>This intent will have 5 extra:
- * <ul>
- * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
- * <li> {@link #EXTRA_LE_AUDIO_DIRECTION} - Direction as bit mask. </li>
- * <li> {@link #EXTRA_LE_AUDIO_SINK_LOCATION} - Sink location as per Bluetooth Assigned
- * Numbers </li>
- * <li> {@link #EXTRA_LE_AUDIO_SOURCE_LOCATION} - Source location as per Bluetooth Assigned
- * Numbers </li>
- * <li> {@link #EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS} - Available contexts for group as per
- * Bluetooth Assigned Numbers </li>
- * </ul>
- *
- * @hide
- */
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_LE_AUDIO_CONF_CHANGED =
- "android.bluetooth.action.LE_AUDIO_CONF_CHANGED";
-
- /**
- * Indicates unspecified audio content.
- * @hide
- */
- public static final int CONTEXT_TYPE_UNSPECIFIED = 0x0001;
-
- /**
- * Indicates conversation between humans as, for example, in telephony or video calls.
- * @hide
- */
- public static final int CONTEXT_TYPE_COMMUNICATION = 0x0002;
-
- /**
- * Indicates media as, for example, in music, public radio, podcast or video soundtrack.
- * @hide
- */
- public static final int CONTEXT_TYPE_MEDIA = 0x0004;
-
- /**
- * Indicates instructional audio as, for example, in navigation, traffic announcements
- * or user guidance.
- * @hide
- */
- public static final int CONTEXT_TYPE_INSTRUCTIONAL = 0x0008;
-
- /**
- * Indicates attention seeking audio as, for example, in beeps signalling arrival of a message
- * or keyboard clicks.
- * @hide
- */
- public static final int CONTEXT_TYPE_ATTENTION_SEEKING = 0x0010;
-
- /**
- * Indicates immediate alerts as, for example, in a low battery alarm, timer expiry or alarm
- * clock.
- * @hide
- */
- public static final int CONTEXT_TYPE_IMMEDIATE_ALERT = 0x0020;
-
- /**
- * Indicates man machine communication as, for example, with voice recognition or virtual
- * assistant.
- * @hide
- */
- public static final int CONTEXT_TYPE_MAN_MACHINE = 0x0040;
-
- /**
- * Indicates emergency alerts as, for example, with fire alarms or other urgent alerts.
- * @hide
- */
- public static final int CONTEXT_TYPE_EMERGENCY_ALERT = 0x0080;
-
- /**
- * Indicates ringtone as in a call alert.
- * @hide
- */
- public static final int CONTEXT_TYPE_RINGTONE = 0x0100;
-
- /**
- * Indicates audio associated with a television program and/or with metadata conforming to the
- * Bluetooth Broadcast TV profile.
- * @hide
- */
- public static final int CONTEXT_TYPE_TV = 0x0200;
-
- /**
- * Indicates audio associated with a low latency live audio stream.
- *
- * @hide
- */
- public static final int CONTEXT_TYPE_LIVE = 0x0400;
-
- /**
- * Indicates audio associated with a video game stream.
- * @hide
- */
- public static final int CONTEXT_TYPE_GAME = 0x0800;
-
- /**
- * This represents an invalid group ID.
- *
- * @hide
- */
- public static final int GROUP_ID_INVALID = IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
-
- /**
- * Contains group id.
- * @hide
- */
- public static final String EXTRA_LE_AUDIO_GROUP_ID =
- "android.bluetooth.extra.LE_AUDIO_GROUP_ID";
-
- /**
- * Contains group node status, can be any of
- * <p>
- * <ul>
- * <li> {@link #GROUP_NODE_ADDED} </li>
- * <li> {@link #GROUP_NODE_REMOVED} </li>
- * </ul>
- * <p>
- * @hide
- */
- public static final String EXTRA_LE_AUDIO_GROUP_NODE_STATUS =
- "android.bluetooth.extra.LE_AUDIO_GROUP_NODE_STATUS";
-
- /**
- * Contains group status, can be any of
- *
- * <p>
- * <ul>
- * <li> {@link #GROUP_STATUS_ACTIVE} </li>
- * <li> {@link #GROUP_STATUS_INACTIVE} </li>
- * </ul>
- * <p>
- * @hide
- */
- public static final String EXTRA_LE_AUDIO_GROUP_STATUS =
- "android.bluetooth.extra.LE_AUDIO_GROUP_STATUS";
-
- /**
- * Contains bit mask for direction, bit 0 set when Sink, bit 1 set when Source.
- * @hide
- */
- public static final String EXTRA_LE_AUDIO_DIRECTION =
- "android.bluetooth.extra.LE_AUDIO_DIRECTION";
-
- /**
- * Contains source location as per Bluetooth Assigned Numbers
- * @hide
- */
- public static final String EXTRA_LE_AUDIO_SOURCE_LOCATION =
- "android.bluetooth.extra.LE_AUDIO_SOURCE_LOCATION";
-
- /**
- * Contains sink location as per Bluetooth Assigned Numbers
- * @hide
- */
- public static final String EXTRA_LE_AUDIO_SINK_LOCATION =
- "android.bluetooth.extra.LE_AUDIO_SINK_LOCATION";
-
- /**
- * Contains available context types for group as per Bluetooth Assigned Numbers
- * @hide
- */
- public static final String EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS =
- "android.bluetooth.extra.LE_AUDIO_AVAILABLE_CONTEXTS";
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- /**
- * Indicating that group is Active ( Audio device is available )
- * @hide
- */
- public static final int GROUP_STATUS_ACTIVE = IBluetoothLeAudio.GROUP_STATUS_ACTIVE;
-
- /**
- * Indicating that group is Inactive ( Audio device is not available )
- * @hide
- */
- public static final int GROUP_STATUS_INACTIVE = IBluetoothLeAudio.GROUP_STATUS_INACTIVE;
-
- /**
- * Indicating that node has been added to the group.
- * @hide
- */
- public static final int GROUP_NODE_ADDED = IBluetoothLeAudio.GROUP_NODE_ADDED;
-
- /**
- * Indicating that node has been removed from the group.
- * @hide
- */
- public static final int GROUP_NODE_REMOVED = IBluetoothLeAudio.GROUP_NODE_REMOVED;
-
- private final BluetoothProfileConnector<IBluetoothLeAudio> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.LE_AUDIO, "BluetoothLeAudio",
- IBluetoothLeAudio.class.getName()) {
- @Override
- public IBluetoothLeAudio getServiceInterface(IBinder service) {
- return IBluetoothLeAudio.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothLeAudio proxy object for interacting with the local
- * Bluetooth LeAudio service.
- */
- /* package */ BluetoothLeAudio(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- mCloseGuard = new CloseGuard();
- mCloseGuard.open("close");
- }
-
- /**
- * @hide
- */
- public void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothLeAudio getService() {
- return mProfileConnector.getService();
- }
-
- protected void finalize() {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
- close();
- }
-
- /**
- * Initiate connection to a profile of the remote bluetooth device.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is already connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that
- * connection state intent for the profile will be broadcasted with
- * the state. Users can get the connection state of the profile
- * from this intent.
- *
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean connect(@Nullable BluetoothDevice device) {
- if (DBG) log("connect(" + device + ")");
- final IBluetoothLeAudio service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate disconnection from a profile
- *
- * <p> This API will return false in scenarios like the profile on the
- * Bluetooth device is not in connected state etc. When this API returns,
- * true, it is guaranteed that the connection state change
- * intent will be broadcasted with the state. Users can get the
- * disconnection state of the profile from this intent.
- *
- * <p> If the disconnection is initiated by a remote device, the state
- * will transition from {@link #STATE_CONNECTED} to
- * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
- * host (local) device the state will transition from
- * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
- * state {@link #STATE_DISCONNECTED}. The transition to
- * {@link #STATE_DISCONNECTING} can be used to distinguish between the
- * two scenarios.
- *
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnect(@Nullable BluetoothDevice device) {
- if (DBG) log("disconnect(" + device + ")");
- final IBluetoothLeAudio service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @NonNull List<BluetoothDevice> getConnectedDevices() {
- if (VDBG) log("getConnectedDevices()");
- final IBluetoothLeAudio service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
- @NonNull int[] states) {
- if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothLeAudio service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) {
- if (VDBG) log("getState(" + device + ")");
- final IBluetoothLeAudio service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Select a connected device as active.
- *
- * The active device selection is per profile. An active device's
- * purpose is profile-specific. For example, LeAudio audio
- * streaming is to the active LeAudio device. If a remote device
- * is not connected, it cannot be selected as active.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is not connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that the
- * {@link #ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
- * with the active device.
- *
- *
- * @param device the remote Bluetooth device. Could be null to clear
- * the active device and stop streaming audio to a Bluetooth device.
- * @return false on immediate error, true otherwise
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean setActiveDevice(@Nullable BluetoothDevice device) {
- if (DBG) log("setActiveDevice(" + device + ")");
- final IBluetoothLeAudio service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled() && ((device == null) || isValidDevice(device))) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setActiveDevice(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the connected LeAudio devices that are active
- *
- * @return the list of active devices. Returns empty list on error.
- * @hide
- */
- @NonNull
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getActiveDevices() {
- if (VDBG) log("getActiveDevice()");
- final IBluetoothLeAudio service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getActiveDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get device group id. Devices with same group id belong to same group (i.e left and right
- * earbud)
- * @param device LE Audio capable device
- * @return group id that this device currently belongs to
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getGroupId(@NonNull BluetoothDevice device) {
- if (VDBG) log("getGroupId()");
- final IBluetoothLeAudio service = getService();
- final int defaultValue = GROUP_ID_INVALID;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled()) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getGroupId(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set volume for the streaming devices
- *
- * @param volume volume to set
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED})
- public void setVolume(int volume) {
- if (VDBG) log("setVolume(vol: " + volume + " )");
- final IBluetoothLeAudio service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.setVolume(volume, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Add device to the given group.
- * @param group_id group ID the device is being added to
- * @param device the active device
- * @return true on success, otherwise false
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED
- })
- public boolean groupAddNode(int group_id, @NonNull BluetoothDevice device) {
- if (VDBG) log("groupAddNode()");
- final IBluetoothLeAudio service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.groupAddNode(group_id, device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Remove device from a given group.
- * @param group_id group ID the device is being removed from
- * @param device the active device
- * @return true on success, otherwise false
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED
- })
- public boolean groupRemoveNode(int group_id, @NonNull BluetoothDevice device) {
- if (VDBG) log("groupRemoveNode()");
- final IBluetoothLeAudio service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.groupRemoveNode(group_id, device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothLeAudio service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- final IBluetoothLeAudio service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (mAdapter.isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
-
- /**
- * Helper for converting a state to a string.
- *
- * For debug use only - strings are not internationalized.
- *
- * @hide
- */
- public static String stateToString(int state) {
- switch (state) {
- case STATE_DISCONNECTED:
- return "disconnected";
- case STATE_CONNECTING:
- return "connecting";
- case STATE_CONNECTED:
- return "connected";
- case STATE_DISCONNECTING:
- return "disconnecting";
- default:
- return "<unknown state " + state + ">";
- }
- }
-
- private boolean isValidDevice(@Nullable BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java b/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java
deleted file mode 100644
index dcaf4b6..0000000
--- a/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java
+++ /dev/null
@@ -1,129 +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.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Represents the codec configuration for a Bluetooth LE Audio source device.
- * <p>Contains the source codec type.
- * <p>The source codec type values are the same as those supported by the
- * device hardware.
- *
- * {@see BluetoothLeAudioCodecConfig}
- */
-public final class BluetoothLeAudioCodecConfig {
- // Add an entry for each source codec here.
-
- /** @hide */
- @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
- SOURCE_CODEC_TYPE_LC3,
- SOURCE_CODEC_TYPE_INVALID
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface SourceCodecType {};
-
- public static final int SOURCE_CODEC_TYPE_LC3 = 0;
- public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
-
- /**
- * Represents the count of valid source codec types. Can be accessed via
- * {@link #getMaxCodecType}.
- */
- private static final int SOURCE_CODEC_TYPE_MAX = 1;
-
- private final @SourceCodecType int mCodecType;
-
- /**
- * Creates a new BluetoothLeAudioCodecConfig.
- *
- * @param codecType the source codec type
- */
- private BluetoothLeAudioCodecConfig(@SourceCodecType int codecType) {
- mCodecType = codecType;
- }
-
- @Override
- public String toString() {
- return "{codecName:" + getCodecName() + "}";
- }
-
- /**
- * Gets the codec type.
- *
- * @return the codec type
- */
- public @SourceCodecType int getCodecType() {
- return mCodecType;
- }
-
- /**
- * Returns the valid codec types count.
- */
- public static int getMaxCodecType() {
- return SOURCE_CODEC_TYPE_MAX;
- }
-
- /**
- * Gets the codec name.
- *
- * @return the codec name
- */
- public @NonNull String getCodecName() {
- switch (mCodecType) {
- case SOURCE_CODEC_TYPE_LC3:
- return "LC3";
- case SOURCE_CODEC_TYPE_INVALID:
- return "INVALID CODEC";
- default:
- break;
- }
- return "UNKNOWN CODEC(" + mCodecType + ")";
- }
-
- /**
- * Builder for {@link BluetoothLeAudioCodecConfig}.
- * <p> By default, the codec type will be set to
- * {@link BluetoothLeAudioCodecConfig#SOURCE_CODEC_TYPE_INVALID}
- */
- public static final class Builder {
- private int mCodecType = BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID;
-
- /**
- * Set codec type for Bluetooth codec config.
- *
- * @param codecType of this codec
- * @return the same Builder instance
- */
- public @NonNull Builder setCodecType(@SourceCodecType int codecType) {
- mCodecType = codecType;
- return this;
- }
-
- /**
- * Build {@link BluetoothLeAudioCodecConfig}.
- * @return new BluetoothLeAudioCodecConfig built
- */
- public @NonNull BluetoothLeAudioCodecConfig build() {
- return new BluetoothLeAudioCodecConfig(mCodecType);
- }
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothLeBroadcast.java b/core/java/android/bluetooth/BluetoothLeBroadcast.java
deleted file mode 100644
index fed9f91..0000000
--- a/core/java/android/bluetooth/BluetoothLeBroadcast.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.content.Context;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-
-/**
- * This class provides the public APIs to control the Bluetooth LE Broadcast Source profile.
- *
- * <p>BluetoothLeBroadcast is a proxy object for controlling the Bluetooth LE Broadcast
- * Source Service via IPC. Use {@link BluetoothAdapter#getProfileProxy}
- * to get the BluetoothLeBroadcast proxy object.
- *
- * @hide
- */
-public final class BluetoothLeBroadcast implements BluetoothProfile {
- private static final String TAG = "BluetoothLeBroadcast";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Constants used by the LE Audio Broadcast profile for the Broadcast state
- *
- * @hide
- */
- @IntDef(prefix = {"LE_AUDIO_BROADCAST_STATE_"}, value = {
- LE_AUDIO_BROADCAST_STATE_DISABLED,
- LE_AUDIO_BROADCAST_STATE_ENABLING,
- LE_AUDIO_BROADCAST_STATE_ENABLED,
- LE_AUDIO_BROADCAST_STATE_DISABLING,
- LE_AUDIO_BROADCAST_STATE_PLAYING,
- LE_AUDIO_BROADCAST_STATE_NOT_PLAYING
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface LeAudioBroadcastState {}
-
- /**
- * Indicates that LE Audio Broadcast mode is currently disabled
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_STATE_DISABLED = 10;
-
- /**
- * Indicates that LE Audio Broadcast mode is being enabled
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_STATE_ENABLING = 11;
-
- /**
- * Indicates that LE Audio Broadcast mode is currently enabled
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_STATE_ENABLED = 12;
- /**
- * Indicates that LE Audio Broadcast mode is being disabled
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_STATE_DISABLING = 13;
-
- /**
- * Indicates that an LE Audio Broadcast mode is currently playing
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_STATE_PLAYING = 14;
-
- /**
- * Indicates that LE Audio Broadcast is currently not playing
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_STATE_NOT_PLAYING = 15;
-
- /**
- * Constants used by the LE Audio Broadcast profile for encryption key length
- *
- * @hide
- */
- @IntDef(prefix = {"LE_AUDIO_BROADCAST_ENCRYPTION_KEY_"}, value = {
- LE_AUDIO_BROADCAST_ENCRYPTION_KEY_32BIT,
- LE_AUDIO_BROADCAST_ENCRYPTION_KEY_128BIT
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface LeAudioEncryptionKeyLength {}
-
- /**
- * Indicates that the LE Audio Broadcast encryption key size is 32 bits.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_ENCRYPTION_KEY_32BIT = 16;
-
- /**
- * Indicates that the LE Audio Broadcast encryption key size is 128 bits.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_ENCRYPTION_KEY_128BIT = 17;
-
- /**
- * Interface for receiving events related to broadcasts
- */
- public interface Callback {
- /**
- * Called when broadcast state has changed
- *
- * @param prevState broadcast state before the change
- * @param newState broadcast state after the change
- */
- @LeAudioBroadcastState
- void onBroadcastStateChange(int prevState, int newState);
- /**
- * Called when encryption key has been updated
- *
- * @param success true if the key was updated successfully, false otherwise
- */
- void onEncryptionKeySet(boolean success);
- }
-
- /**
- * Create a BluetoothLeBroadcast proxy object for interacting with the local
- * LE Audio Broadcast Source service.
- *
- * @hide
- */
- /*package*/ BluetoothLeBroadcast(Context context,
- BluetoothProfile.ServiceListener listener) {
- }
-
- /**
- * Not supported since LE Audio Broadcasts do not establish a connection
- *
- * @throws UnsupportedOperationException
- *
- * @hide
- */
- @Override
- public int getConnectionState(BluetoothDevice device) {
- throw new UnsupportedOperationException(
- "LE Audio Broadcasts are not connection-oriented.");
- }
-
- /**
- * Not supported since LE Audio Broadcasts do not establish a connection
- *
- * @throws UnsupportedOperationException
- *
- * @hide
- */
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- throw new UnsupportedOperationException(
- "LE Audio Broadcasts are not connection-oriented.");
- }
-
- /**
- * Not supported since LE Audio Broadcasts do not establish a connection
- *
- * @throws UnsupportedOperationException
- *
- * @hide
- */
- @Override
- public List<BluetoothDevice> getConnectedDevices() {
- throw new UnsupportedOperationException(
- "LE Audio Broadcasts are not connection-oriented.");
- }
-
- /**
- * Enable LE Audio Broadcast mode.
- *
- * Generates a new broadcast ID and enables sending of encrypted or unencrypted
- * isochronous PDUs
- *
- * @hide
- */
- public int enableBroadcastMode() {
- if (DBG) log("enableBroadcastMode");
- return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED;
- }
-
- /**
- * Disable LE Audio Broadcast mode.
- *
- * @hide
- */
- public int disableBroadcastMode() {
- if (DBG) log("disableBroadcastMode");
- return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED;
- }
-
- /**
- * Get the current LE Audio broadcast state
- *
- * @hide
- */
- @LeAudioBroadcastState
- public int getBroadcastState() {
- if (DBG) log("getBroadcastState");
- return LE_AUDIO_BROADCAST_STATE_DISABLED;
- }
-
- /**
- * Enable LE Audio broadcast encryption
- *
- * @param keyLength if useExisting is true, this specifies the length of the key that should
- * be generated
- * @param useExisting true, if an existing key should be used
- * false, if a new key should be generated
- *
- * @hide
- */
- @LeAudioEncryptionKeyLength
- public int enableEncryption(boolean useExisting, int keyLength) {
- if (DBG) log("enableEncryption useExisting=" + useExisting + " keyLength=" + keyLength);
- return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_ENABLE_ENCRYPTION_FAILED;
- }
-
- /**
- * Disable LE Audio broadcast encryption
- *
- * @param removeExisting true, if the existing key should be removed
- * false, otherwise
- *
- * @hide
- */
- public int disableEncryption(boolean removeExisting) {
- if (DBG) log("disableEncryption removeExisting=" + removeExisting);
- return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED;
- }
-
- /**
- * Enable or disable LE Audio broadcast encryption
- *
- * @param key use the provided key if non-null, generate a new key if null
- * @param keyLength 0 if encryption is disabled, 4 bytes (low security),
- * 16 bytes (high security)
- *
- * @hide
- */
- @LeAudioEncryptionKeyLength
- public int setEncryptionKey(byte[] key, int keyLength) {
- if (DBG) log("setEncryptionKey key=" + key + " keyLength=" + keyLength);
- return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_ENCRYPTION_KEY_FAILED;
- }
-
-
- /**
- * Get the encryption key that was set before
- *
- * @return encryption key as a byte array or null if no encryption key was set
- *
- * @hide
- */
- public byte[] getEncryptionKey() {
- if (DBG) log("getEncryptionKey");
- return null;
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java b/core/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java
deleted file mode 100644
index b866cce..0000000
--- a/core/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.bluetooth.le.ScanResult;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * This class provides a set of callbacks that are invoked when scanning for Broadcast Sources is
- * offloaded to a Broadcast Assistant.
- *
- * <p>An LE Audio Broadcast Assistant can help a Broadcast Sink to scan for available Broadcast
- * Sources. The Broadcast Sink achieves this by offloading the scan to a Broadcast Assistant. This
- * is facilitated by the Broadcast Audio Scan Service (BASS). A BASS server is a GATT server that is
- * part of the Scan Delegator on a Broadcast Sink. A BASS client instead runs on the Broadcast
- * Assistant.
- *
- * <p>Once a GATT connection is established between the BASS client and the BASS server, the
- * Broadcast Sink can offload the scans to the Broadcast Assistant. Upon finding new Broadcast
- * Sources, the Broadcast Assistant then notifies the Broadcast Sink about these over the
- * established GATT connection. The Scan Delegator on the Broadcast Sink can also notify the
- * Assistant about changes such as addition and removal of Broadcast Sources.
- *
- * @hide
- */
-public abstract class BluetoothLeBroadcastAssistantCallback {
-
- /**
- * Broadcast Audio Scan Service (BASS) codes returned by a BASS Server
- *
- * @hide
- */
- @IntDef(
- prefix = "BASS_STATUS_",
- value = {
- BASS_STATUS_SUCCESS,
- BASS_STATUS_FAILURE,
- BASS_STATUS_INVALID_GATT_HANDLE,
- BASS_STATUS_TXN_TIMEOUT,
- BASS_STATUS_INVALID_SOURCE_ID,
- BASS_STATUS_COLOCATED_SRC_UNAVAILABLE,
- BASS_STATUS_INVALID_SOURCE_SELECTED,
- BASS_STATUS_SOURCE_UNAVAILABLE,
- BASS_STATUS_DUPLICATE_ADDITION,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface BassStatus {}
-
- public static final int BASS_STATUS_SUCCESS = 0x00;
- public static final int BASS_STATUS_FAILURE = 0x01;
- public static final int BASS_STATUS_INVALID_GATT_HANDLE = 0x02;
- public static final int BASS_STATUS_TXN_TIMEOUT = 0x03;
-
- public static final int BASS_STATUS_INVALID_SOURCE_ID = 0x04;
- public static final int BASS_STATUS_COLOCATED_SRC_UNAVAILABLE = 0x05;
- public static final int BASS_STATUS_INVALID_SOURCE_SELECTED = 0x06;
- public static final int BASS_STATUS_SOURCE_UNAVAILABLE = 0x07;
- public static final int BASS_STATUS_DUPLICATE_ADDITION = 0x08;
- public static final int BASS_STATUS_NO_EMPTY_SLOT = 0x09;
- public static final int BASS_STATUS_INVALID_GROUP_OP = 0x10;
-
- /**
- * Callback invoked when a new LE Audio Broadcast Source is found.
- *
- * @param result {@link ScanResult} scan result representing a Broadcast Source
- */
- public void onBluetoothLeBroadcastSourceFound(@NonNull ScanResult result) {}
-
- /**
- * Callback invoked when the Broadcast Assistant synchronizes with Periodic Advertisements (PAs)
- * of an LE Audio Broadcast Source.
- *
- * @param source the selected Broadcast Source
- */
- public void onBluetoothLeBroadcastSourceSelected(
- @NonNull BluetoothLeBroadcastSourceInfo source, @BassStatus int status) {}
-
- /**
- * Callback invoked when the Broadcast Assistant loses synchronization with an LE Audio
- * Broadcast Source.
- *
- * @param source the Broadcast Source with which synchronization was lost
- */
- public void onBluetoothLeBroadcastSourceLost(
- @NonNull BluetoothLeBroadcastSourceInfo source, @BassStatus int status) {}
-
- /**
- * Callback invoked when a new LE Audio Broadcast Source has been successfully added to the Scan
- * Delegator (within a Broadcast Sink, for example).
- *
- * @param sink Scan Delegator device on which a new Broadcast Source has been added
- * @param source the added Broadcast Source
- */
- public void onBluetoothLeBroadcastSourceAdded(
- @NonNull BluetoothDevice sink,
- @NonNull BluetoothLeBroadcastSourceInfo source,
- @BassStatus int status) {}
-
- /**
- * Callback invoked when an existing LE Audio Broadcast Source within a remote Scan Delegator
- * has been updated.
- *
- * @param sink Scan Delegator device on which a Broadcast Source has been updated
- * @param source the updated Broadcast Source
- */
- public void onBluetoothLeBroadcastSourceUpdated(
- @NonNull BluetoothDevice sink,
- @NonNull BluetoothLeBroadcastSourceInfo source,
- @BassStatus int status) {}
-
- /**
- * Callback invoked when an LE Audio Broadcast Source has been successfully removed from the
- * Scan Delegator (within a Broadcast Sink, for example).
- *
- * @param sink Scan Delegator device from which a Broadcast Source has been removed
- * @param source the removed Broadcast Source
- */
- public void onBluetoothLeBroadcastSourceRemoved(
- @NonNull BluetoothDevice sink,
- @NonNull BluetoothLeBroadcastSourceInfo source,
- @BassStatus int status) {}
-}
diff --git a/core/java/android/bluetooth/BluetoothLeBroadcastSourceInfo.java b/core/java/android/bluetooth/BluetoothLeBroadcastSourceInfo.java
deleted file mode 100644
index cb47280..0000000
--- a/core/java/android/bluetooth/BluetoothLeBroadcastSourceInfo.java
+++ /dev/null
@@ -1,788 +0,0 @@
-/*
- * Copyright 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * This class represents an LE Audio Broadcast Source and the associated information that is needed
- * by Broadcast Audio Scan Service (BASS) residing on a Scan Delegator.
- *
- * <p>For example, the Scan Delegator on an LE Audio Broadcast Sink can use the information
- * contained within an instance of this class to synchronize with an LE Audio Broadcast Source in
- * order to listen to a Broadcast Audio Stream.
- *
- * <p>BroadcastAssistant has a BASS client which facilitates scanning and discovery of Broadcast
- * Sources on behalf of say a Broadcast Sink. Upon successful discovery of one or more Broadcast
- * sources, this information needs to be communicated to the BASS Server residing within the Scan
- * Delegator on a Broadcast Sink. This is achieved using the Periodic Advertising Synchronization
- * Transfer (PAST) procedure. This procedure uses information contained within an instance of this
- * class.
- *
- * @hide
- */
-public final class BluetoothLeBroadcastSourceInfo implements Parcelable {
- private static final String TAG = "BluetoothLeBroadcastSourceInfo";
- private static final boolean DBG = true;
-
- /**
- * Constants representing Broadcast Source address types
- *
- * @hide
- */
- @IntDef(
- prefix = "LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_",
- value = {
- LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_PUBLIC,
- LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_RANDOM,
- LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface LeAudioBroadcastSourceAddressType {}
-
- /**
- * Represents a public address used by an LE Audio Broadcast Source
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_PUBLIC = 0;
-
- /**
- * Represents a random address used by an LE Audio Broadcast Source
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_RANDOM = 1;
-
- /**
- * Represents an invalid address used by an LE Audio Broadcast Seurce
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID = 0xFFFF;
-
- /**
- * Periodic Advertising Synchronization state
- *
- * <p>Periodic Advertising (PA) enables the LE Audio Broadcast Assistant to discover broadcast
- * audio streams as well as the audio stream configuration on behalf of an LE Audio Broadcast
- * Sink. This information can then be transferred to the LE Audio Broadcast Sink using the
- * Periodic Advertising Synchronizaton Transfer (PAST) procedure.
- *
- * @hide
- */
- @IntDef(
- prefix = "LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_",
- value = {
- LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IDLE,
- LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNCINFO_REQ,
- LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IN_SYNC,
- LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNC_FAIL,
- LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_NO_PAST
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface LeAudioBroadcastSinkPaSyncState {}
-
- /**
- * Indicates that the Broadcast Sink is not synchronized with the Periodic Advertisements (PA)
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IDLE = 0;
-
- /**
- * Indicates that the Broadcast Sink requested the Broadcast Assistant to synchronize with the
- * Periodic Advertisements (PA).
- *
- * <p>This is also known as scan delegation or scan offloading.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNCINFO_REQ = 1;
-
- /**
- * Indicates that the Broadcast Sink is synchronized with the Periodic Advertisements (PA).
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IN_SYNC = 2;
-
- /**
- * Indicates that the Broadcast Sink was unable to synchronize with the Periodic Advertisements
- * (PA).
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNC_FAIL = 3;
-
- /**
- * Indicates that the Broadcast Sink should be synchronized with the Periodic Advertisements
- * (PA) using the Periodic Advertisements Synchronization Transfert (PAST) procedure.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_NO_PAST = 4;
-
- /**
- * Indicates that the Broadcast Sink synchornization state is invalid.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_INVALID = 0xFFFF;
-
- /** @hide */
- @IntDef(
- prefix = "LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_",
- value = {
- LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED,
- LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_SYNCHRONIZED
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface LeAudioBroadcastSinkAudioSyncState {}
-
- /**
- * Indicates that the Broadcast Sink is not synchronized with a Broadcast Audio Stream.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED = 0;
-
- /**
- * Indicates that the Broadcast Sink is synchronized with a Broadcast Audio Stream.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_SYNCHRONIZED = 1;
-
- /**
- * Indicates that the Broadcast Sink audio synchronization state is invalid.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_INVALID = 0xFFFF;
-
- /** @hide */
- @IntDef(
- prefix = "LE_AUDIO_BROADCAST_SINK_ENC_STATE_",
- value = {
- LE_AUDIO_BROADCAST_SINK_ENC_STATE_NOT_ENCRYPTED,
- LE_AUDIO_BROADCAST_SINK_ENC_STATE_CODE_REQUIRED,
- LE_AUDIO_BROADCAST_SINK_ENC_STATE_DECRYPTING,
- LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface LeAudioBroadcastSinkEncryptionState {}
-
- /**
- * Indicates that the Broadcast Sink is synchronized with an unencrypted audio stream.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_NOT_ENCRYPTED = 0;
-
- /**
- * Indicates that the Broadcast Sink needs a Broadcast Code to synchronize with the audio
- * stream.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_CODE_REQUIRED = 1;
-
- /**
- * Indicates that the Broadcast Sink is synchronized with an encrypted audio stream.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_DECRYPTING = 2;
-
- /**
- * Indicates that the Broadcast Sink is unable to decrypt an audio stream due to an incorrect
- * Broadcast Code
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE = 3;
-
- /**
- * Indicates that the Broadcast Sink encryption state is invalid.
- *
- * @hide
- */
- public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_INVALID = 0xFF;
-
- /**
- * Represents an invalid LE Audio Broadcast Source ID
- *
- * @hide
- */
- public static final byte LE_AUDIO_BROADCAST_SINK_INVALID_SOURCE_ID = (byte) 0x00;
-
- /**
- * Represents an invalid Broadcast ID of a Broadcast Source
- *
- * @hide
- */
- public static final int INVALID_BROADCAST_ID = 0xFFFFFF;
-
- private byte mSourceId;
- private @LeAudioBroadcastSourceAddressType int mSourceAddressType;
- private BluetoothDevice mSourceDevice;
- private byte mSourceAdvSid;
- private int mBroadcastId;
- private @LeAudioBroadcastSinkPaSyncState int mPaSyncState;
- private @LeAudioBroadcastSinkEncryptionState int mEncryptionStatus;
- private @LeAudioBroadcastSinkAudioSyncState int mAudioSyncState;
- private byte[] mBadBroadcastCode;
- private byte mNumSubGroups;
- private Map<Integer, Integer> mSubgroupBisSyncState = new HashMap<Integer, Integer>();
- private Map<Integer, byte[]> mSubgroupMetadata = new HashMap<Integer, byte[]>();
-
- private String mBroadcastCode;
- private static final int BIS_NO_PREF = 0xFFFFFFFF;
- private static final int BROADCAST_CODE_SIZE = 16;
-
- /**
- * Constructor to create an Empty object of {@link BluetoothLeBroadcastSourceInfo } with the
- * given Source Id.
- *
- * <p>This is mainly used to represent the Empty Broadcast Source entries
- *
- * @param sourceId Source Id for this Broadcast Source info object
- * @hide
- */
- public BluetoothLeBroadcastSourceInfo(byte sourceId) {
- mSourceId = sourceId;
- mSourceAddressType = LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID;
- mSourceDevice = null;
- mSourceAdvSid = (byte) 0x00;
- mBroadcastId = INVALID_BROADCAST_ID;
- mPaSyncState = LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_INVALID;
- mAudioSyncState = LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_INVALID;
- mEncryptionStatus = LE_AUDIO_BROADCAST_SINK_ENC_STATE_INVALID;
- mBadBroadcastCode = null;
- mNumSubGroups = 0;
- mBroadcastCode = null;
- }
-
- /*package*/ BluetoothLeBroadcastSourceInfo(
- byte sourceId,
- @LeAudioBroadcastSourceAddressType int addressType,
- @NonNull BluetoothDevice device,
- byte advSid,
- int broadcastId,
- @LeAudioBroadcastSinkPaSyncState int paSyncstate,
- @LeAudioBroadcastSinkEncryptionState int encryptionStatus,
- @LeAudioBroadcastSinkAudioSyncState int audioSyncstate,
- @Nullable byte[] badCode,
- byte numSubGroups,
- @NonNull Map<Integer, Integer> bisSyncState,
- @Nullable Map<Integer, byte[]> subgroupMetadata,
- @NonNull String broadcastCode) {
- mSourceId = sourceId;
- mSourceAddressType = addressType;
- mSourceDevice = device;
- mSourceAdvSid = advSid;
- mBroadcastId = broadcastId;
- mPaSyncState = paSyncstate;
- mEncryptionStatus = encryptionStatus;
- mAudioSyncState = audioSyncstate;
-
- if (badCode != null && badCode.length != 0) {
- mBadBroadcastCode = new byte[badCode.length];
- System.arraycopy(badCode, 0, mBadBroadcastCode, 0, badCode.length);
- }
- mNumSubGroups = numSubGroups;
- mSubgroupBisSyncState = new HashMap<Integer, Integer>(bisSyncState);
- mSubgroupMetadata = new HashMap<Integer, byte[]>(subgroupMetadata);
- mBroadcastCode = broadcastCode;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof BluetoothLeBroadcastSourceInfo) {
- BluetoothLeBroadcastSourceInfo other = (BluetoothLeBroadcastSourceInfo) o;
- return (other.mSourceId == mSourceId
- && other.mSourceAddressType == mSourceAddressType
- && other.mSourceDevice == mSourceDevice
- && other.mSourceAdvSid == mSourceAdvSid
- && other.mBroadcastId == mBroadcastId
- && other.mPaSyncState == mPaSyncState
- && other.mEncryptionStatus == mEncryptionStatus
- && other.mAudioSyncState == mAudioSyncState
- && Arrays.equals(other.mBadBroadcastCode, mBadBroadcastCode)
- && other.mNumSubGroups == mNumSubGroups
- && mSubgroupBisSyncState.equals(other.mSubgroupBisSyncState)
- && mSubgroupMetadata.equals(other.mSubgroupMetadata)
- && other.mBroadcastCode == mBroadcastCode);
- }
- return false;
- }
-
- /**
- * Checks if an instance of {@link BluetoothLeBroadcastSourceInfo} is empty.
- *
- * @hide
- */
- public boolean isEmpty() {
- boolean ret = false;
- if (mSourceAddressType == LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID
- && mSourceDevice == null
- && mSourceAdvSid == (byte) 0
- && mPaSyncState == LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_INVALID
- && mEncryptionStatus == LE_AUDIO_BROADCAST_SINK_ENC_STATE_INVALID
- && mAudioSyncState == LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_INVALID
- && mBadBroadcastCode == null
- && mNumSubGroups == 0
- && mSubgroupBisSyncState.size() == 0
- && mSubgroupMetadata.size() == 0
- && mBroadcastCode == null) {
- ret = true;
- }
- return ret;
- }
-
- /**
- * Compares an instance of {@link BluetoothLeBroadcastSourceInfo} with the provided instance.
- *
- * @hide
- */
- public boolean matches(BluetoothLeBroadcastSourceInfo srcInfo) {
- boolean ret = false;
- if (srcInfo == null) {
- ret = false;
- } else {
- if (mSourceDevice == null) {
- if (mSourceAdvSid == srcInfo.getAdvertisingSid()
- && mSourceAddressType == srcInfo.getAdvAddressType()) {
- ret = true;
- }
- } else {
- if (mSourceDevice.equals(srcInfo.getSourceDevice())
- && mSourceAdvSid == srcInfo.getAdvertisingSid()
- && mSourceAddressType == srcInfo.getAdvAddressType()
- && mBroadcastId == srcInfo.getBroadcastId()) {
- ret = true;
- }
- }
- }
- return ret;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(
- mSourceId,
- mSourceAddressType,
- mSourceDevice,
- mSourceAdvSid,
- mBroadcastId,
- mPaSyncState,
- mEncryptionStatus,
- mAudioSyncState,
- mBadBroadcastCode,
- mNumSubGroups,
- mSubgroupBisSyncState,
- mSubgroupMetadata,
- mBroadcastCode);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public String toString() {
- return "{BluetoothLeBroadcastSourceInfo : mSourceId"
- + mSourceId
- + " addressType: "
- + mSourceAddressType
- + " sourceDevice: "
- + mSourceDevice
- + " mSourceAdvSid:"
- + mSourceAdvSid
- + " mBroadcastId:"
- + mBroadcastId
- + " mPaSyncState:"
- + mPaSyncState
- + " mEncryptionStatus:"
- + mEncryptionStatus
- + " mAudioSyncState:"
- + mAudioSyncState
- + " mBadBroadcastCode:"
- + mBadBroadcastCode
- + " mNumSubGroups:"
- + mNumSubGroups
- + " mSubgroupBisSyncState:"
- + mSubgroupBisSyncState
- + " mSubgroupMetadata:"
- + mSubgroupMetadata
- + " mBroadcastCode:"
- + mBroadcastCode
- + "}";
- }
-
- /**
- * Get the Source Id
- *
- * @return byte representing the Source Id, {@link
- * #LE_AUDIO_BROADCAST_ASSISTANT_INVALID_SOURCE_ID} if invalid
- * @hide
- */
- public byte getSourceId() {
- return mSourceId;
- }
-
- /**
- * Set the Source Id
- *
- * @param sourceId source Id
- * @hide
- */
- public void setSourceId(byte sourceId) {
- mSourceId = sourceId;
- }
-
- /**
- * Set the Broadcast Source device
- *
- * @param sourceDevice the Broadcast Source BluetoothDevice
- * @hide
- */
- public void setSourceDevice(@NonNull BluetoothDevice sourceDevice) {
- mSourceDevice = sourceDevice;
- }
-
- /**
- * Get the Broadcast Source BluetoothDevice
- *
- * @return Broadcast Source BluetoothDevice
- * @hide
- */
- public @NonNull BluetoothDevice getSourceDevice() {
- return mSourceDevice;
- }
-
- /**
- * Set the address type of the Broadcast Source advertisements
- *
- * @hide
- */
- public void setAdvAddressType(@LeAudioBroadcastSourceAddressType int addressType) {
- mSourceAddressType = addressType;
- }
-
- /**
- * Get the address type used by advertisements from the Broadcast Source.
- * BluetoothLeBroadcastSourceInfo Object
- *
- * @hide
- */
- @LeAudioBroadcastSourceAddressType
- public int getAdvAddressType() {
- return mSourceAddressType;
- }
-
- /**
- * Set the advertising SID of the Broadcast Source advertisement.
- *
- * @param advSid advertising SID of the Broadcast Source
- * @hide
- */
- public void setAdvertisingSid(byte advSid) {
- mSourceAdvSid = advSid;
- }
-
- /**
- * Get the advertising SID of the Broadcast Source advertisement.
- *
- * @return advertising SID of the Broadcast Source
- * @hide
- */
- public byte getAdvertisingSid() {
- return mSourceAdvSid;
- }
-
- /**
- * Get the Broadcast ID of the Broadcast Source.
- *
- * @return broadcast ID
- * @hide
- */
- public int getBroadcastId() {
- return mBroadcastId;
- }
-
- /**
- * Set the Periodic Advertising (PA) Sync State.
- *
- * @hide
- */
- /*package*/ void setPaSyncState(@LeAudioBroadcastSinkPaSyncState int paSyncState) {
- mPaSyncState = paSyncState;
- }
-
- /**
- * Get the Periodic Advertising (PA) Sync State
- *
- * @hide
- */
- public @LeAudioBroadcastSinkPaSyncState int getMetadataSyncState() {
- return mPaSyncState;
- }
-
- /**
- * Set the audio sync state
- *
- * @hide
- */
- /*package*/ void setAudioSyncState(@LeAudioBroadcastSinkAudioSyncState int audioSyncState) {
- mAudioSyncState = audioSyncState;
- }
-
- /**
- * Get the audio sync state
- *
- * @hide
- */
- public @LeAudioBroadcastSinkAudioSyncState int getAudioSyncState() {
- return mAudioSyncState;
- }
-
- /**
- * Set the encryption status
- *
- * @hide
- */
- /*package*/ void setEncryptionStatus(
- @LeAudioBroadcastSinkEncryptionState int encryptionStatus) {
- mEncryptionStatus = encryptionStatus;
- }
-
- /**
- * Get the encryption status
- *
- * @hide
- */
- public @LeAudioBroadcastSinkEncryptionState int getEncryptionStatus() {
- return mEncryptionStatus;
- }
-
- /**
- * Get the incorrect broadcast code that the Scan delegator used to decrypt the Broadcast Audio
- * Stream and failed.
- *
- * <p>This code is valid only if {@link #getEncryptionStatus} returns {@link
- * #LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE}
- *
- * @return byte array containing bad broadcast value, null if the current encryption status is
- * not {@link #LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE}
- * @hide
- */
- public @Nullable byte[] getBadBroadcastCode() {
- return mBadBroadcastCode;
- }
-
- /**
- * Get the number of subgroups.
- *
- * @return number of subgroups
- * @hide
- */
- public byte getNumberOfSubGroups() {
- return mNumSubGroups;
- }
-
- public @NonNull Map<Integer, Integer> getSubgroupBisSyncState() {
- return mSubgroupBisSyncState;
- }
-
- public void setSubgroupBisSyncState(@NonNull Map<Integer, Integer> bisSyncState) {
- mSubgroupBisSyncState = new HashMap<Integer, Integer>(bisSyncState);
- }
-
- /*package*/ void setBroadcastCode(@NonNull String broadcastCode) {
- mBroadcastCode = broadcastCode;
- }
-
- /**
- * Get the broadcast code
- *
- * @return
- * @hide
- */
- public @NonNull String getBroadcastCode() {
- return mBroadcastCode;
- }
-
- /**
- * Set the broadcast ID
- *
- * @param broadcastId broadcast ID of the Broadcast Source
- * @hide
- */
- public void setBroadcastId(int broadcastId) {
- mBroadcastId = broadcastId;
- }
-
- private void writeSubgroupBisSyncStateToParcel(
- @NonNull Parcel dest, @NonNull Map<Integer, Integer> subgroupBisSyncState) {
- dest.writeInt(subgroupBisSyncState.size());
- for (Map.Entry<Integer, Integer> entry : subgroupBisSyncState.entrySet()) {
- dest.writeInt(entry.getKey());
- dest.writeInt(entry.getValue());
- }
- }
-
- private static void readSubgroupBisSyncStateFromParcel(
- @NonNull Parcel in, @NonNull Map<Integer, Integer> subgroupBisSyncState) {
- int size = in.readInt();
-
- for (int i = 0; i < size; i++) {
- Integer key = in.readInt();
- Integer value = in.readInt();
- subgroupBisSyncState.put(key, value);
- }
- }
-
- private void writeSubgroupMetadataToParcel(
- @NonNull Parcel dest, @Nullable Map<Integer, byte[]> subgroupMetadata) {
- if (subgroupMetadata == null) {
- dest.writeInt(0);
- return;
- }
-
- dest.writeInt(subgroupMetadata.size());
- for (Map.Entry<Integer, byte[]> entry : subgroupMetadata.entrySet()) {
- dest.writeInt(entry.getKey());
- byte[] metadata = entry.getValue();
- if (metadata != null) {
- dest.writeInt(metadata.length);
- dest.writeByteArray(metadata);
- }
- }
- }
-
- private static void readSubgroupMetadataFromParcel(
- @NonNull Parcel in, @NonNull Map<Integer, byte[]> subgroupMetadata) {
- int size = in.readInt();
-
- for (int i = 0; i < size; i++) {
- Integer key = in.readInt();
- Integer metaDataLen = in.readInt();
- byte[] metadata = null;
- if (metaDataLen != 0) {
- metadata = new byte[metaDataLen];
- in.readByteArray(metadata);
- }
- subgroupMetadata.put(key, metadata);
- }
- }
-
- public static final @NonNull Parcelable.Creator<BluetoothLeBroadcastSourceInfo> CREATOR =
- new Parcelable.Creator<BluetoothLeBroadcastSourceInfo>() {
- public @NonNull BluetoothLeBroadcastSourceInfo createFromParcel(
- @NonNull Parcel in) {
- final byte sourceId = in.readByte();
- final int sourceAddressType = in.readInt();
- final BluetoothDevice sourceDevice =
- in.readTypedObject(BluetoothDevice.CREATOR);
- final byte sourceAdvSid = in.readByte();
- final int broadcastId = in.readInt();
- final int paSyncState = in.readInt();
- final int audioSyncState = in.readInt();
- final int encryptionStatus = in.readInt();
- final int badBroadcastLen = in.readInt();
- byte[] badBroadcastCode = null;
-
- if (badBroadcastLen > 0) {
- badBroadcastCode = new byte[badBroadcastLen];
- in.readByteArray(badBroadcastCode);
- }
- final byte numSubGroups = in.readByte();
- final String broadcastCode = in.readString();
- Map<Integer, Integer> subgroupBisSyncState = new HashMap<Integer, Integer>();
- readSubgroupBisSyncStateFromParcel(in, subgroupBisSyncState);
- Map<Integer, byte[]> subgroupMetadata = new HashMap<Integer, byte[]>();
- readSubgroupMetadataFromParcel(in, subgroupMetadata);
-
- BluetoothLeBroadcastSourceInfo srcInfo =
- new BluetoothLeBroadcastSourceInfo(
- sourceId,
- sourceAddressType,
- sourceDevice,
- sourceAdvSid,
- broadcastId,
- paSyncState,
- encryptionStatus,
- audioSyncState,
- badBroadcastCode,
- numSubGroups,
- subgroupBisSyncState,
- subgroupMetadata,
- broadcastCode);
- return srcInfo;
- }
-
- public @NonNull BluetoothLeBroadcastSourceInfo[] newArray(int size) {
- return new BluetoothLeBroadcastSourceInfo[size];
- }
- };
-
- @Override
- public void writeToParcel(@NonNull Parcel out, int flags) {
- out.writeByte(mSourceId);
- out.writeInt(mSourceAddressType);
- out.writeTypedObject(mSourceDevice, 0);
- out.writeByte(mSourceAdvSid);
- out.writeInt(mBroadcastId);
- out.writeInt(mPaSyncState);
- out.writeInt(mAudioSyncState);
- out.writeInt(mEncryptionStatus);
-
- if (mBadBroadcastCode != null) {
- out.writeInt(mBadBroadcastCode.length);
- out.writeByteArray(mBadBroadcastCode);
- } else {
- // zero indicates that there is no "bad broadcast code"
- out.writeInt(0);
- }
- out.writeByte(mNumSubGroups);
- out.writeString(mBroadcastCode);
- writeSubgroupBisSyncStateToParcel(out, mSubgroupBisSyncState);
- writeSubgroupMetadataToParcel(out, mSubgroupMetadata);
- }
-
- private static void log(@NonNull String msg) {
- if (DBG) {
- Log.d(TAG, msg);
- }
- }
-}
-;
diff --git a/core/java/android/bluetooth/BluetoothLeCall.java b/core/java/android/bluetooth/BluetoothLeCall.java
deleted file mode 100644
index fb7789d..0000000
--- a/core/java/android/bluetooth/BluetoothLeCall.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright 2021 HIMSA II K/S - www.himsa.com.
- * Represented by EHIMA - www.ehima.com
- *
- * 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.ParcelUuid;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-import java.util.UUID;
-
-/**
- * Representation of Call
- *
- * @hide
- */
-public final class BluetoothLeCall implements Parcelable {
-
- /** @hide */
- @IntDef(prefix = "STATE_", value = {
- STATE_INCOMING,
- STATE_DIALING,
- STATE_ALERTING,
- STATE_ACTIVE,
- STATE_LOCALLY_HELD,
- STATE_REMOTELY_HELD,
- STATE_LOCALLY_AND_REMOTELY_HELD
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface State {
- }
-
- /**
- * A remote party is calling (incoming call).
- *
- * @hide
- */
- public static final int STATE_INCOMING = 0x00;
-
- /**
- * The process to call the remote party has started but the remote party is not
- * being alerted (outgoing call).
- *
- * @hide
- */
- public static final int STATE_DIALING = 0x01;
-
- /**
- * A remote party is being alerted (outgoing call).
- *
- * @hide
- */
- public static final int STATE_ALERTING = 0x02;
-
- /**
- * The call is in an active conversation.
- *
- * @hide
- */
- public static final int STATE_ACTIVE = 0x03;
-
- /**
- * The call is connected but held locally. “Locally Held” implies that either
- * the server or the client can affect the state.
- *
- * @hide
- */
- public static final int STATE_LOCALLY_HELD = 0x04;
-
- /**
- * The call is connected but held remotely. “Remotely Held” means that the state
- * is controlled by the remote party of a call.
- *
- * @hide
- */
- public static final int STATE_REMOTELY_HELD = 0x05;
-
- /**
- * The call is connected but held both locally and remotely.
- *
- * @hide
- */
- public static final int STATE_LOCALLY_AND_REMOTELY_HELD = 0x06;
-
- /**
- * Whether the call direction is outgoing.
- *
- * @hide
- */
- public static final int FLAG_OUTGOING_CALL = 0x00000001;
-
- /**
- * Whether the call URI and Friendly Name are withheld by server.
- *
- * @hide
- */
- public static final int FLAG_WITHHELD_BY_SERVER = 0x00000002;
-
- /**
- * Whether the call URI and Friendly Name are withheld by network.
- *
- * @hide
- */
- public static final int FLAG_WITHHELD_BY_NETWORK = 0x00000004;
-
- /** Unique UUID that identifies this call */
- private UUID mUuid;
-
- /** Remote Caller URI */
- private String mUri;
-
- /** Caller friendly name */
- private String mFriendlyName;
-
- /** Call state */
- private @State int mState;
-
- /** Call flags */
- private int mCallFlags;
-
- /** @hide */
- public BluetoothLeCall(@NonNull BluetoothLeCall that) {
- mUuid = new UUID(that.getUuid().getMostSignificantBits(),
- that.getUuid().getLeastSignificantBits());
- mUri = that.mUri;
- mFriendlyName = that.mFriendlyName;
- mState = that.mState;
- mCallFlags = that.mCallFlags;
- }
-
- /** @hide */
- public BluetoothLeCall(@NonNull UUID uuid, @NonNull String uri, @NonNull String friendlyName,
- @State int state, int callFlags) {
- mUuid = uuid;
- mUri = uri;
- mFriendlyName = friendlyName;
- mState = state;
- mCallFlags = callFlags;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (o == null || getClass() != o.getClass())
- return false;
- BluetoothLeCall that = (BluetoothLeCall) o;
- return mUuid.equals(that.mUuid) && mUri.equals(that.mUri)
- && mFriendlyName.equals(that.mFriendlyName) && mState == that.mState
- && mCallFlags == that.mCallFlags;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mUuid, mUri, mFriendlyName, mState, mCallFlags);
- }
-
- /**
- * Returns a string representation of this BluetoothLeCall.
- *
- * <p>
- * Currently this is the UUID.
- *
- * @return string representation of this BluetoothLeCall
- */
- @Override
- public String toString() {
- return mUuid.toString();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel out, int flags) {
- out.writeParcelable(new ParcelUuid(mUuid), 0);
- out.writeString(mUri);
- out.writeString(mFriendlyName);
- out.writeInt(mState);
- out.writeInt(mCallFlags);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothLeCall> CREATOR =
- new Parcelable.Creator<BluetoothLeCall>() {
- public BluetoothLeCall createFromParcel(Parcel in) {
- return new BluetoothLeCall(in);
- }
-
- public BluetoothLeCall[] newArray(int size) {
- return new BluetoothLeCall[size];
- }
- };
-
- private BluetoothLeCall(Parcel in) {
- mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
- mUri = in.readString();
- mFriendlyName = in.readString();
- mState = in.readInt();
- mCallFlags = in.readInt();
- }
-
- /**
- * Returns an UUID of this BluetoothLeCall.
- *
- * <p>
- * An UUID is unique identifier of a BluetoothLeCall.
- *
- * @return UUID of this BluetoothLeCall
- * @hide
- */
- public @NonNull UUID getUuid() {
- return mUuid;
- }
-
- /**
- * Returns a URI of the remote party of this BluetoothLeCall.
- *
- * @return string representation of this BluetoothLeCall
- * @hide
- */
- public @NonNull String getUri() {
- return mUri;
- }
-
- /**
- * Returns a friendly name of the call.
- *
- * @return friendly name representation of this BluetoothLeCall
- * @hide
- */
- public @NonNull String getFriendlyName() {
- return mFriendlyName;
- }
-
- /**
- * Returns the call state.
- *
- * @return the state of this BluetoothLeCall
- * @hide
- */
- public @State int getState() {
- return mState;
- }
-
- /**
- * Returns the call flags.
- *
- * @return call flags
- * @hide
- */
- public int getCallFlags() {
- return mCallFlags;
- }
-
- /**
- * Whether the call direction is incoming.
- *
- * @return true if incoming call, false otherwise
- * @hide
- */
- public boolean isIncomingCall() {
- return (mCallFlags & FLAG_OUTGOING_CALL) == 0;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothLeCallControl.java b/core/java/android/bluetooth/BluetoothLeCallControl.java
deleted file mode 100644
index fb080c9..0000000
--- a/core/java/android/bluetooth/BluetoothLeCallControl.java
+++ /dev/null
@@ -1,899 +0,0 @@
-/*
- * Copyright 2019 HIMSA II K/S - www.himsa.com.
- * Represented by EHIMA - www.ehima.com
- *
- * 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.bluetooth;
-
-import android.Manifest;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-import android.annotation.SuppressLint;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.Executor;
-
-/**
- * This class provides the APIs to control the Call Control profile.
- *
- * <p>
- * This class provides Bluetooth Telephone Bearer Service functionality,
- * allowing applications to expose a GATT Service based interface to control the
- * state of the calls by remote devices such as LE audio devices.
- *
- * <p>
- * BluetoothLeCallControl is a proxy object for controlling the Bluetooth Telephone Bearer
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get the
- * BluetoothLeCallControl proxy object.
- *
- * @hide
- */
-public final class BluetoothLeCallControl implements BluetoothProfile {
- private static final String TAG = "BluetoothLeCallControl";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /** @hide */
- @IntDef(prefix = "RESULT_", value = {
- RESULT_SUCCESS,
- RESULT_ERROR_UNKNOWN_CALL_ID,
- RESULT_ERROR_INVALID_URI,
- RESULT_ERROR_APPLICATION
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Result {
- }
-
- /**
- * Opcode write was successful.
- *
- * @hide
- */
- public static final int RESULT_SUCCESS = 0;
-
- /**
- * Unknown call Id has been used in the operation.
- *
- * @hide
- */
- public static final int RESULT_ERROR_UNKNOWN_CALL_ID = 1;
-
- /**
- * The URI provided in {@link Callback#onPlaceCallRequest} is invalid.
- *
- * @hide
- */
- public static final int RESULT_ERROR_INVALID_URI = 2;
-
- /**
- * Application internal error.
- *
- * @hide
- */
- public static final int RESULT_ERROR_APPLICATION = 3;
-
- /** @hide */
- @IntDef(prefix = "TERMINATION_REASON_", value = {
- TERMINATION_REASON_INVALID_URI,
- TERMINATION_REASON_FAIL,
- TERMINATION_REASON_REMOTE_HANGUP,
- TERMINATION_REASON_SERVER_HANGUP,
- TERMINATION_REASON_LINE_BUSY,
- TERMINATION_REASON_NETWORK_CONGESTION,
- TERMINATION_REASON_CLIENT_HANGUP,
- TERMINATION_REASON_NO_SERVICE,
- TERMINATION_REASON_NO_ANSWER
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TerminationReason {
- }
-
- /**
- * Remote Caller ID value used to place a call was formed improperly.
- *
- * @hide
- */
- public static final int TERMINATION_REASON_INVALID_URI = 0x00;
-
- /**
- * Call fail.
- *
- * @hide
- */
- public static final int TERMINATION_REASON_FAIL = 0x01;
-
- /**
- * Remote party ended call.
- *
- * @hide
- */
- public static final int TERMINATION_REASON_REMOTE_HANGUP = 0x02;
-
- /**
- * Call ended from the server.
- *
- * @hide
- */
- public static final int TERMINATION_REASON_SERVER_HANGUP = 0x03;
-
- /**
- * Line busy.
- *
- * @hide
- */
- public static final int TERMINATION_REASON_LINE_BUSY = 0x04;
-
- /**
- * Network congestion.
- *
- * @hide
- */
- public static final int TERMINATION_REASON_NETWORK_CONGESTION = 0x05;
-
- /**
- * Client terminated.
- *
- * @hide
- */
- public static final int TERMINATION_REASON_CLIENT_HANGUP = 0x06;
-
- /**
- * No service.
- *
- * @hide
- */
- public static final int TERMINATION_REASON_NO_SERVICE = 0x07;
-
- /**
- * No answer.
- *
- * @hide
- */
- public static final int TERMINATION_REASON_NO_ANSWER = 0x08;
-
- /*
- * Flag indicating support for hold/unhold call feature.
- *
- * @hide
- */
- public static final int CAPABILITY_HOLD_CALL = 0x00000001;
-
- /**
- * Flag indicating support for joining calls feature.
- *
- * @hide
- */
- public static final int CAPABILITY_JOIN_CALLS = 0x00000002;
-
- private static final int MESSAGE_TBS_SERVICE_CONNECTED = 102;
- private static final int MESSAGE_TBS_SERVICE_DISCONNECTED = 103;
-
- private static final int REG_TIMEOUT = 10000;
-
- /**
- * The template class is used to call callback functions on events from the TBS
- * server. Callback functions are wrapped in this class and registered to the
- * Android system during app registration.
- *
- * @hide
- */
- public abstract static class Callback {
-
- private static final String TAG = "BluetoothLeCallControl.Callback";
-
- /**
- * Called when a remote client requested to accept the call.
- *
- * <p>
- * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
- * request.
- *
- * @param requestId The Id of the request
- * @param callId The call Id requested to be accepted
- * @hide
- */
- public abstract void onAcceptCall(int requestId, @NonNull UUID callId);
-
- /**
- * A remote client has requested to terminate the call.
- *
- * <p>
- * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
- * request.
- *
- * @param requestId The Id of the request
- * @param callId The call Id requested to terminate
- * @hide
- */
- public abstract void onTerminateCall(int requestId, @NonNull UUID callId);
-
- /**
- * A remote client has requested to hold the call.
- *
- * <p>
- * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
- * request.
- *
- * @param requestId The Id of the request
- * @param callId The call Id requested to be put on hold
- * @hide
- */
- public void onHoldCall(int requestId, @NonNull UUID callId) {
- Log.e(TAG, "onHoldCall: unimplemented, however CAPABILITY_HOLD_CALL is set!");
- }
-
- /**
- * A remote client has requested to unhold the call.
- *
- * <p>
- * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
- * request.
- *
- * @param requestId The Id of the request
- * @param callId The call Id requested to unhold
- * @hide
- */
- public void onUnholdCall(int requestId, @NonNull UUID callId) {
- Log.e(TAG, "onUnholdCall: unimplemented, however CAPABILITY_HOLD_CALL is set!");
- }
-
- /**
- * A remote client has requested to place a call.
- *
- * <p>
- * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
- * request.
- *
- * @param requestId The Id of the request
- * @param callId The Id to be assigned for the new call
- * @param uri The caller URI requested
- * @hide
- */
- public abstract void onPlaceCall(int requestId, @NonNull UUID callId, @NonNull String uri);
-
- /**
- * A remote client has requested to join the calls.
- *
- * <p>
- * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
- * request.
- *
- * @param requestId The Id of the request
- * @param callIds The call Id list requested to join
- * @hide
- */
- public void onJoinCalls(int requestId, @NonNull List<UUID> callIds) {
- Log.e(TAG, "onJoinCalls: unimplemented, however CAPABILITY_JOIN_CALLS is set!");
- }
- }
-
- private class CallbackWrapper extends IBluetoothLeCallControlCallback.Stub {
-
- private final Executor mExecutor;
- private final Callback mCallback;
-
- CallbackWrapper(Executor executor, Callback callback) {
- mExecutor = executor;
- mCallback = callback;
- }
-
- @Override
- public void onBearerRegistered(int ccid) {
- if (mCallback != null) {
- mCcid = ccid;
- } else {
- // registration timeout
- Log.e(TAG, "onBearerRegistered: mCallback is null");
- }
- }
-
- @Override
- public void onAcceptCall(int requestId, ParcelUuid uuid) {
- final long identityToken = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onAcceptCall(requestId, uuid.getUuid()));
- } finally {
- Binder.restoreCallingIdentity(identityToken);
- }
- }
-
- @Override
- public void onTerminateCall(int requestId, ParcelUuid uuid) {
- final long identityToken = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onTerminateCall(requestId, uuid.getUuid()));
- } finally {
- Binder.restoreCallingIdentity(identityToken);
- }
- }
-
- @Override
- public void onHoldCall(int requestId, ParcelUuid uuid) {
- final long identityToken = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onHoldCall(requestId, uuid.getUuid()));
- } finally {
- Binder.restoreCallingIdentity(identityToken);
- }
- }
-
- @Override
- public void onUnholdCall(int requestId, ParcelUuid uuid) {
- final long identityToken = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onUnholdCall(requestId, uuid.getUuid()));
- } finally {
- Binder.restoreCallingIdentity(identityToken);
- }
- }
-
- @Override
- public void onPlaceCall(int requestId, ParcelUuid uuid, String uri) {
- final long identityToken = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onPlaceCall(requestId, uuid.getUuid(), uri));
- } finally {
- Binder.restoreCallingIdentity(identityToken);
- }
- }
-
- @Override
- public void onJoinCalls(int requestId, List<ParcelUuid> parcelUuids) {
- List<UUID> uuids = new ArrayList<>();
- for (ParcelUuid parcelUuid : parcelUuids) {
- uuids.add(parcelUuid.getUuid());
- }
-
- final long identityToken = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallback.onJoinCalls(requestId, uuids));
- } finally {
- Binder.restoreCallingIdentity(identityToken);
- }
- }
- };
-
- private Context mContext;
- private ServiceListener mServiceListener;
- private volatile IBluetoothLeCallControl mService;
- private BluetoothAdapter mAdapter;
- private int mCcid = 0;
- private String mToken;
- private Callback mCallback = null;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG)
- Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- doUnbind();
- } else {
- doBind();
- }
- }
- };
-
- /**
- * Create a BluetoothLeCallControl proxy object for interacting with the local Bluetooth
- * telephone bearer service.
- */
- /* package */ BluetoothLeCallControl(Context context, ServiceListener listener) {
- mContext = context;
- mAdapter = BluetoothAdapter.getDefaultAdapter();
- mServiceListener = listener;
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- private boolean doBind() {
- synchronized (mConnection) {
- if (mService == null) {
- if (VDBG)
- Log.d(TAG, "Binding service...");
- try {
- return mAdapter.getBluetoothManager().
- bindBluetoothProfileService(BluetoothProfile.LE_CALL_CONTROL,
- mConnection);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to bind TelephoneBearerService", e);
- }
- }
- }
- return false;
- }
-
- private void doUnbind() {
- synchronized (mConnection) {
- if (mService != null) {
- if (VDBG)
- Log.d(TAG, "Unbinding service...");
- try {
- mAdapter.getBluetoothManager().
- unbindBluetoothProfileService(BluetoothProfile.LE_CALL_CONTROL,
- mConnection);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to unbind TelephoneBearerService", e);
- } finally {
- mService = null;
- }
- }
- }
- }
-
- /* package */ void close() {
- if (VDBG)
- log("close()");
- unregisterBearer();
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "", re);
- }
- }
- mServiceListener = null;
- doUnbind();
- }
-
- private IBluetoothLeCallControl getService() {
- return mService;
- }
-
- /**
- * Not supported
- *
- * @throws UnsupportedOperationException
- */
- @Override
- public int getConnectionState(@Nullable BluetoothDevice device) {
- throw new UnsupportedOperationException("not supported");
- }
-
- /**
- * Not supported
- *
- * @throws UnsupportedOperationException
- */
- @Override
- public @NonNull List<BluetoothDevice> getConnectedDevices() {
- throw new UnsupportedOperationException("not supported");
- }
-
- /**
- * Not supported
- *
- * @throws UnsupportedOperationException
- */
- @Override
- public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
- @NonNull int[] states) {
- throw new UnsupportedOperationException("not supported");
- }
-
- /**
- * Register Telephone Bearer exposing the interface that allows remote devices
- * to track and control the call states.
- *
- * <p>
- * This is an asynchronous call. The callback is used to notify success or
- * failure if the function returns true.
- *
- * <p>
- * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * <!-- The UCI is a String identifier of the telephone bearer as defined at
- * https://www.bluetooth.com/specifications/assigned-numbers/uniform-caller-identifiers
- * (login required). -->
- *
- * <!-- The examples of common URI schemes can be found in
- * https://iana.org/assignments/uri-schemes/uri-schemes.xhtml -->
- *
- * <!-- The Technology is an integer value. The possible values are defined at
- * https://www.bluetooth.com/specifications/assigned-numbers (login required).
- * -->
- *
- * @param uci Bearer Unique Client Identifier
- * @param uriSchemes URI Schemes supported list
- * @param capabilities bearer capabilities
- * @param provider Network provider name
- * @param technology Network technology
- * @param executor {@link Executor} object on which callback will be
- * executed. The Executor object is required.
- * @param callback {@link Callback} object to which callback messages will
- * be sent. The Callback object is required.
- * @return true on success, false otherwise
- * @hide
- */
- @SuppressLint("ExecutorRegistration")
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public boolean registerBearer(@Nullable String uci,
- @NonNull List<String> uriSchemes, int capabilities,
- @NonNull String provider, int technology,
- @NonNull Executor executor, @NonNull Callback callback) {
- if (DBG) {
- Log.d(TAG, "registerBearer");
- }
- if (callback == null) {
- throw new IllegalArgumentException("null parameter: " + callback);
- }
- if (mCcid != 0) {
- return false;
- }
-
- mToken = uci;
-
- final IBluetoothLeCallControl service = getService();
- if (service != null) {
- if (mCallback != null) {
- Log.e(TAG, "Bearer can be opened only once");
- return false;
- }
-
- mCallback = callback;
- try {
- CallbackWrapper callbackWrapper = new CallbackWrapper(executor, callback);
- service.registerBearer(mToken, callbackWrapper, uci, uriSchemes, capabilities,
- provider, technology);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- mCallback = null;
- return false;
- }
-
- if (mCcid == 0) {
- mCallback = null;
- return false;
- }
-
- return true;
- }
-
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- }
-
- return false;
- }
-
- /**
- * Unregister Telephone Bearer Service and destroy all the associated data.
- *
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void unregisterBearer() {
- if (DBG) {
- Log.d(TAG, "unregisterBearer");
- }
- if (mCcid == 0) {
- return;
- }
-
- int ccid = mCcid;
- mCcid = 0;
- mCallback = null;
-
- final IBluetoothLeCallControl service = getService();
- if (service != null) {
- try {
- service.unregisterBearer(mToken);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- }
- }
-
- /**
- * Get the Content Control ID (CCID) value.
- *
- * @return ccid Content Control ID value
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public int getContentControlId() {
- return mCcid;
- }
-
- /**
- * Notify about the newly added call.
- *
- * <p>
- * This shall be called as early as possible after the call has been added.
- *
- * <p>
- * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param call Newly added call
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void onCallAdded(@NonNull BluetoothLeCall call) {
- if (DBG) {
- Log.d(TAG, "onCallAdded: call=" + call);
- }
- if (mCcid == 0) {
- return;
- }
-
- final IBluetoothLeCallControl service = getService();
- if (service != null) {
- try {
- service.callAdded(mCcid, call);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- }
- }
-
- /**
- * Notify about the removed call.
- *
- * <p>
- * This shall be called as early as possible after the call has been removed.
- *
- * <p>
- * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param callId The Id of a call that has been removed
- * @param reason Call termination reason
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void onCallRemoved(@NonNull UUID callId, @TerminationReason int reason) {
- if (DBG) {
- Log.d(TAG, "callRemoved: callId=" + callId);
- }
- if (mCcid == 0) {
- return;
- }
-
- final IBluetoothLeCallControl service = getService();
- if (service != null) {
- try {
- service.callRemoved(mCcid, new ParcelUuid(callId), reason);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- }
- }
-
- /**
- * Notify the call state change
- *
- * <p>
- * This shall be called as early as possible after the state of the call has
- * changed.
- *
- * <p>
- * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param callId The call Id that state has been changed
- * @param state Call state
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void onCallStateChanged(@NonNull UUID callId, @BluetoothLeCall.State int state) {
- if (DBG) {
- Log.d(TAG, "callStateChanged: callId=" + callId + " state=" + state);
- }
- if (mCcid == 0) {
- return;
- }
-
- final IBluetoothLeCallControl service = getService();
- if (service != null) {
- try {
- service.callStateChanged(mCcid, new ParcelUuid(callId), state);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- }
- }
-
- /**
- * Provide the current calls list
- *
- * <p>
- * This function must be invoked after registration if application has any
- * calls.
- *
- * @param calls current calls list
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void currentCallsList(@NonNull List<BluetoothLeCall> calls) {
- final IBluetoothLeCallControl service = getService();
- if (service != null) {
- try {
- service.currentCallsList(mCcid, calls);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- }
-
- /**
- * Provide the network current status
- *
- * <p>
- * This function must be invoked on change of network state.
- *
- * <p>
- * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * <!-- The Technology is an integer value. The possible values are defined at
- * https://www.bluetooth.com/specifications/assigned-numbers (login required).
- * -->
- *
- * @param provider Network provider name
- * @param technology Network technology
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void networkStateChanged(@NonNull String provider, int technology) {
- if (DBG) {
- Log.d(TAG, "networkStateChanged: provider=" + provider + ", technology=" + technology);
- }
- if (mCcid == 0) {
- return;
- }
-
- final IBluetoothLeCallControl service = getService();
- if (service != null) {
- try {
- service.networkStateChanged(mCcid, provider, technology);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- }
- }
-
- /**
- * Send a response to a call control request to a remote device.
- *
- * <p>
- * This function must be invoked in when a request is received by one of these
- * callback methods:
- *
- * <ul>
- * <li>{@link Callback#onAcceptCall}
- * <li>{@link Callback#onTerminateCall}
- * <li>{@link Callback#onHoldCall}
- * <li>{@link Callback#onUnholdCall}
- * <li>{@link Callback#onPlaceCall}
- * <li>{@link Callback#onJoinCalls}
- * </ul>
- *
- * @param requestId The ID of the request that was received with the callback
- * @param result The result of the request to be sent to the remote devices
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void requestResult(int requestId, @Result int result) {
- if (DBG) {
- Log.d(TAG, "requestResult: requestId=" + requestId + " result=" + result);
- }
- if (mCcid == 0) {
- return;
- }
-
- final IBluetoothLeCallControl service = getService();
- if (service != null) {
- try {
- service.requestResult(mCcid, requestId, result);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- private static boolean isValidDevice(@Nullable BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-
- private final IBluetoothProfileServiceConnection mConnection =
- new IBluetoothProfileServiceConnection.Stub() {
- @Override
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) {
- Log.d(TAG, "Proxy object connected");
- }
- mService = IBluetoothLeCallControl.Stub.asInterface(Binder.allowBlocking(service));
- mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_TBS_SERVICE_CONNECTED));
- }
-
- @Override
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) {
- Log.d(TAG, "Proxy object disconnected");
- }
- doUnbind();
- mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_TBS_SERVICE_DISCONNECTED));
- }
- };
-
- private final Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_TBS_SERVICE_CONNECTED: {
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.LE_CALL_CONTROL,
- BluetoothLeCallControl.this);
- }
- break;
- }
- case MESSAGE_TBS_SERVICE_DISCONNECTED: {
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.LE_CALL_CONTROL);
- }
- break;
- }
- }
- }
- };
-}
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
deleted file mode 100644
index fef6f22..0000000
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2013 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.bluetooth;
-
-import android.annotation.RequiresFeature;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemService;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * High level manager used to obtain an instance of an {@link BluetoothAdapter}
- * and to conduct overall Bluetooth Management.
- * <p>
- * Use {@link android.content.Context#getSystemService(java.lang.String)}
- * with {@link Context#BLUETOOTH_SERVICE} to create an {@link BluetoothManager},
- * then call {@link #getAdapter} to obtain the {@link BluetoothAdapter}.
- * </p>
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>
- * For more information about using BLUETOOTH, read the <a href=
- * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
- * guide.
- * </p>
- * </div>
- *
- * @see Context#getSystemService
- * @see BluetoothAdapter#getDefaultAdapter()
- */
-@SystemService(Context.BLUETOOTH_SERVICE)
-@RequiresFeature(PackageManager.FEATURE_BLUETOOTH)
-public final class BluetoothManager {
- private static final String TAG = "BluetoothManager";
- private static final boolean DBG = false;
-
- private final AttributionSource mAttributionSource;
- private final BluetoothAdapter mAdapter;
-
- /**
- * @hide
- */
- public BluetoothManager(Context context) {
- mAttributionSource = (context != null) ? context.getAttributionSource() :
- AttributionSource.myAttributionSource();
- mAdapter = BluetoothAdapter.createAdapter(mAttributionSource);
- }
-
- /**
- * Get the BLUETOOTH Adapter for this device.
- *
- * @return the BLUETOOTH Adapter
- */
- @RequiresNoPermission
- public BluetoothAdapter getAdapter() {
- return mAdapter;
- }
-
- /**
- * Get the current connection state of the profile to the remote device.
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for certain profile.
- * This can be used by applications like status bar which would just like
- * to know the state of Bluetooth.
- *
- * @param device Remote bluetooth device.
- * @param profile GATT or GATT_SERVER
- * @return State of the profile connection. One of {@link BluetoothProfile#STATE_CONNECTED},
- * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_DISCONNECTED},
- * {@link BluetoothProfile#STATE_DISCONNECTING}
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device, int profile) {
- if (DBG) Log.d(TAG, "getConnectionState()");
-
- List<BluetoothDevice> connectedDevices = getConnectedDevices(profile);
- for (BluetoothDevice connectedDevice : connectedDevices) {
- if (device.equals(connectedDevice)) {
- return BluetoothProfile.STATE_CONNECTED;
- }
- }
-
- return BluetoothProfile.STATE_DISCONNECTED;
- }
-
- /**
- * Get connected devices for the specified profile.
- *
- * <p> Return the set of devices which are in state {@link BluetoothProfile#STATE_CONNECTED}
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of Bluetooth for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of Bluetooth.
- *
- * @param profile GATT or GATT_SERVER
- * @return List of devices. The list will be empty on error.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices(int profile) {
- if (DBG) Log.d(TAG, "getConnectedDevices");
- return getDevicesMatchingConnectionStates(profile, new int[] {
- BluetoothProfile.STATE_CONNECTED
- });
- }
-
- /**
- * Get a list of devices that match any of the given connection
- * states.
- *
- * <p> If none of the devices match any of the given states,
- * an empty list will be returned.
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * @param profile GATT or GATT_SERVER
- * @param states Array of states. States can be one of {@link BluetoothProfile#STATE_CONNECTED},
- * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_DISCONNECTED},
- * {@link BluetoothProfile#STATE_DISCONNECTING},
- * @return List of devices. The list will be empty on error.
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int profile, int[] states) {
- if (DBG) Log.d(TAG, "getDevicesMatchingConnectionStates");
-
- if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
- throw new IllegalArgumentException("Profile not supported: " + profile);
- }
-
- List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
-
- try {
- IBluetoothManager managerService = mAdapter.getBluetoothManager();
- IBluetoothGatt iGatt = managerService.getBluetoothGatt();
- if (iGatt == null) return devices;
- devices = Attributable.setAttributionSource(
- iGatt.getDevicesMatchingConnectionStates(states, mAttributionSource),
- mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
-
- return devices;
- }
-
- /**
- * Open a GATT Server
- * The callback is used to deliver results to Caller, such as connection status as well
- * as the results of any other GATT server operations.
- * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
- * to conduct GATT server operations.
- *
- * @param context App context
- * @param callback GATT server callback handler that will receive asynchronous callbacks.
- * @return BluetoothGattServer instance
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothGattServer openGattServer(Context context,
- BluetoothGattServerCallback callback) {
-
- return (openGattServer(context, callback, BluetoothDevice.TRANSPORT_AUTO));
- }
-
- /**
- * Open a GATT Server
- * The callback is used to deliver results to Caller, such as connection status as well
- * as the results of any other GATT server operations.
- * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
- * to conduct GATT server operations.
- *
- * @param context App context
- * @param callback GATT server callback handler that will receive asynchronous callbacks.
- * @param eatt_support idicates if server should use eatt channel for notifications.
- * @return BluetoothGattServer instance
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothGattServer openGattServer(Context context,
- BluetoothGattServerCallback callback, boolean eatt_support) {
- return (openGattServer(context, callback, BluetoothDevice.TRANSPORT_AUTO, eatt_support));
- }
-
- /**
- * Open a GATT Server
- * The callback is used to deliver results to Caller, such as connection status as well
- * as the results of any other GATT server operations.
- * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
- * to conduct GATT server operations.
- *
- * @param context App context
- * @param callback GATT server callback handler that will receive asynchronous callbacks.
- * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
- * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
- * BluetoothDevice#TRANSPORT_LE}
- * @return BluetoothGattServer instance
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothGattServer openGattServer(Context context,
- BluetoothGattServerCallback callback, int transport) {
- return (openGattServer(context, callback, transport, false));
- }
-
- /**
- * Open a GATT Server
- * The callback is used to deliver results to Caller, such as connection status as well
- * as the results of any other GATT server operations.
- * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
- * to conduct GATT server operations.
- *
- * @param context App context
- * @param callback GATT server callback handler that will receive asynchronous callbacks.
- * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
- * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
- * BluetoothDevice#TRANSPORT_LE}
- * @param eatt_support idicates if server should use eatt channel for notifications.
- * @return BluetoothGattServer instance
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothGattServer openGattServer(Context context,
- BluetoothGattServerCallback callback, int transport, boolean eatt_support) {
- if (context == null || callback == null) {
- throw new IllegalArgumentException("null parameter: " + context + " " + callback);
- }
-
- // TODO(Bluetooth) check whether platform support BLE
- // Do the check here or in GattServer?
-
- try {
- IBluetoothManager managerService = mAdapter.getBluetoothManager();
- IBluetoothGatt iGatt = managerService.getBluetoothGatt();
- if (iGatt == null) {
- Log.e(TAG, "Fail to get GATT Server connection");
- return null;
- }
- BluetoothGattServer mGattServer =
- new BluetoothGattServer(iGatt, transport, mAdapter);
- Boolean regStatus = mGattServer.registerCallback(callback, eatt_support);
- return regStatus ? mGattServer : null;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return null;
- }
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
deleted file mode 100644
index 56e4972..0000000
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (C) 2008 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.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the APIs to control the Bluetooth MAP
- * Profile.
- *
- * @hide
- */
-@SystemApi
-public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
-
- private static final String TAG = "BluetoothMap";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- private CloseGuard mCloseGuard;
-
- /** @hide */
- @SuppressLint("ActionValue")
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
-
- /**
- * There was an error trying to obtain the state
- *
- * @hide
- */
- public static final int STATE_ERROR = -1;
-
- /** @hide */
- public static final int RESULT_FAILURE = 0;
- /** @hide */
- public static final int RESULT_SUCCESS = 1;
- /**
- * Connection canceled before completion.
- *
- * @hide
- */
- public static final int RESULT_CANCELED = 2;
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothMap> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.MAP,
- "BluetoothMap", IBluetoothMap.class.getName()) {
- @Override
- public IBluetoothMap getServiceInterface(IBinder service) {
- return IBluetoothMap.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothMap proxy object.
- */
- /* package */ BluetoothMap(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- if (DBG) Log.d(TAG, "Create BluetoothMap proxy object");
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- mCloseGuard = new CloseGuard();
- mCloseGuard.open("close");
- }
-
- protected void finalize() {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
- close();
- }
-
- /**
- * Close the connection to the backing service.
- * Other public functions of BluetoothMap will return default error
- * results once close() has been called. Multiple invocations of close()
- * are ok.
- *
- * @hide
- */
- @SystemApi
- public void close() {
- if (VDBG) log("close()");
- mProfileConnector.disconnect();
- }
-
- private IBluetoothMap getService() {
- return mProfileConnector.getService();
- }
-
- /**
- * Get the current state of the BluetoothMap service.
- *
- * @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not
- * connected to the Map service.
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getState() {
- if (VDBG) log("getState()");
- final IBluetoothMap service = getService();
- final int defaultValue = BluetoothMap.STATE_ERROR;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getState(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the currently connected remote Bluetooth device (PCE).
- *
- * @return The remote Bluetooth device, or null if not in connected or connecting state, or if
- * this proxy object is not connected to the Map service.
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothDevice getClient() {
- if (VDBG) log("getClient()");
- final IBluetoothMap service = getService();
- final BluetoothDevice defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<BluetoothDevice> recv =
- new SynchronousResultReceiver();
- service.getClient(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns true if the specified Bluetooth device is connected.
- * Returns false if not connected, or if this proxy object is not
- * currently connected to the Map service.
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isConnected(BluetoothDevice device) {
- if (VDBG) log("isConnected(" + device + ")");
- final IBluetoothMap service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isConnected(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate connection. Initiation of outgoing connections is not
- * supported for MAP server.
- *
- * @hide
- */
- @RequiresNoPermission
- public boolean connect(BluetoothDevice device) {
- if (DBG) log("connect(" + device + ")" + "not supported for MAPS");
- return false;
- }
-
- /**
- * Initiate disconnect.
- *
- * @param device Remote Bluetooth Device
- * @return false on error, true otherwise
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) log("disconnect(" + device + ")");
- final IBluetoothMap service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Check class bits for possible Map support.
- * This is a simple heuristic that tries to guess if a device with the
- * given class bits might support Map. It is not accurate for all
- * devices. It tries to err on the side of false positives.
- *
- * @return True if this device might support Map.
- *
- * @hide
- */
- public static boolean doesClassMatchSink(BluetoothClass btClass) {
- // TODO optimize the rule
- switch (btClass.getDeviceClass()) {
- case BluetoothClass.Device.COMPUTER_DESKTOP:
- case BluetoothClass.Device.COMPUTER_LAPTOP:
- case BluetoothClass.Device.COMPUTER_SERVER:
- case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Get the list of connected devices. Currently at most one.
- *
- * @return list of connected devices
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @NonNull List<BluetoothDevice> getConnectedDevices() {
- if (DBG) log("getConnectedDevices()");
- final IBluetoothMap service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the list of devices matching specified states. Currently at most one.
- *
- * @return list of matching devices
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (DBG) log("getDevicesMatchingStates()");
- final IBluetoothMap service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get connection state of device
- *
- * @return device connection state
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
- if (DBG) log("getConnectionState(" + device + ")");
- final IBluetoothMap service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv =
- new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set priority of the profile
- *
- * <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
- *
- * @param device Paired bluetooth device
- * @param priority
- * @return true if priority is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setPriority(BluetoothDevice device, int priority) {
- if (DBG) log("setPriority(" + device + ", " + priority + ")");
- return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothMap service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the priority of the profile.
- *
- * <p> The priority can be any of:
- * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * @param device Bluetooth device
- * @return priority of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public int getPriority(BluetoothDevice device) {
- if (VDBG) log("getPriority(" + device + ")");
- return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- final IBluetoothMap service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-
- private boolean isEnabled() {
- return mAdapter.isEnabled();
- }
-
- private static boolean isValidDevice(BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
deleted file mode 100644
index 03536f9a..0000000
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
-import android.app.PendingIntent;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the APIs to control the Bluetooth MAP MCE Profile.
- *
- * @hide
- */
-@SystemApi
-public final class BluetoothMapClient implements BluetoothProfile {
-
- private static final String TAG = "BluetoothMapClient";
- private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
-
- /** @hide */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED";
- /** @hide */
- @RequiresPermission(android.Manifest.permission.RECEIVE_SMS)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MESSAGE_RECEIVED =
- "android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED";
- /* Actions to be used for pending intents */
- /** @hide */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MESSAGE_SENT_SUCCESSFULLY =
- "android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY";
- /** @hide */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MESSAGE_DELIVERED_SUCCESSFULLY =
- "android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY";
-
- /**
- * Action to notify read status changed
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MESSAGE_READ_STATUS_CHANGED =
- "android.bluetooth.mapmce.profile.action.MESSAGE_READ_STATUS_CHANGED";
-
- /**
- * Action to notify deleted status changed
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MESSAGE_DELETED_STATUS_CHANGED =
- "android.bluetooth.mapmce.profile.action.MESSAGE_DELETED_STATUS_CHANGED";
-
- /**
- * Extras used in ACTION_MESSAGE_RECEIVED intent.
- * NOTE: HANDLE is only valid for a single session with the device.
- */
- /** @hide */
- public static final String EXTRA_MESSAGE_HANDLE =
- "android.bluetooth.mapmce.profile.extra.MESSAGE_HANDLE";
- /** @hide */
- public static final String EXTRA_MESSAGE_TIMESTAMP =
- "android.bluetooth.mapmce.profile.extra.MESSAGE_TIMESTAMP";
- /** @hide */
- public static final String EXTRA_MESSAGE_READ_STATUS =
- "android.bluetooth.mapmce.profile.extra.MESSAGE_READ_STATUS";
- /** @hide */
- public static final String EXTRA_SENDER_CONTACT_URI =
- "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_URI";
- /** @hide */
- public static final String EXTRA_SENDER_CONTACT_NAME =
- "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
-
- /**
- * Used as a boolean extra in ACTION_MESSAGE_DELETED_STATUS_CHANGED
- * Contains the MAP message deleted status
- * Possible values are:
- * true: deleted
- * false: undeleted
- *
- * @hide
- */
- public static final String EXTRA_MESSAGE_DELETED_STATUS =
- "android.bluetooth.mapmce.profile.extra.MESSAGE_DELETED_STATUS";
-
- /**
- * Extra used in ACTION_MESSAGE_READ_STATUS_CHANGED or ACTION_MESSAGE_DELETED_STATUS_CHANGED
- * Possible values are:
- * 0: failure
- * 1: success
- *
- * @hide
- */
- public static final String EXTRA_RESULT_CODE =
- "android.bluetooth.device.extra.RESULT_CODE";
-
- /**
- * There was an error trying to obtain the state
- * @hide
- */
- public static final int STATE_ERROR = -1;
-
- /** @hide */
- public static final int RESULT_FAILURE = 0;
- /** @hide */
- public static final int RESULT_SUCCESS = 1;
- /**
- * Connection canceled before completion.
- * @hide
- */
- public static final int RESULT_CANCELED = 2;
- /** @hide */
- private static final int UPLOADING_FEATURE_BITMASK = 0x08;
-
- /*
- * UNREAD, READ, UNDELETED, DELETED are passed as parameters
- * to setMessageStatus to indicate the messages new state.
- */
-
- /** @hide */
- public static final int UNREAD = 0;
- /** @hide */
- public static final int READ = 1;
- /** @hide */
- public static final int UNDELETED = 2;
- /** @hide */
- public static final int DELETED = 3;
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothMapClient> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.MAP_CLIENT,
- "BluetoothMapClient", IBluetoothMapClient.class.getName()) {
- @Override
- public IBluetoothMapClient getServiceInterface(IBinder service) {
- return IBluetoothMapClient.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothMapClient proxy object.
- */
- /* package */ BluetoothMapClient(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- if (DBG) Log.d(TAG, "Create BluetoothMapClient proxy object");
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- /**
- * Close the connection to the backing service.
- * Other public functions of BluetoothMap will return default error
- * results once close() has been called. Multiple invocations of close()
- * are ok.
- * @hide
- */
- public void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothMapClient getService() {
- return mProfileConnector.getService();
- }
-
- /**
- * Returns true if the specified Bluetooth device is connected.
- * Returns false if not connected, or if this proxy object is not
- * currently connected to the Map service.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isConnected(BluetoothDevice device) {
- if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
- final IBluetoothMapClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isConnected(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate connection. Initiation of outgoing connections is not
- * supported for MAP server.
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean connect(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
- final IBluetoothMapClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate disconnect.
- *
- * @param device Remote Bluetooth Device
- * @return false on error, true otherwise
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "disconnect(" + device + ")");
- final IBluetoothMapClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the list of connected devices. Currently at most one.
- *
- * @return list of connected devices
- * @hide
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
- if (DBG) Log.d(TAG, "getConnectedDevices()");
- final IBluetoothMapClient service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the list of devices matching specified states. Currently at most one.
- *
- * @return list of matching devices
- * @hide
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
- final IBluetoothMapClient service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get connection state of device
- *
- * @return device connection state
- * @hide
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
- final IBluetoothMapClient service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver<>();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set priority of the profile
- *
- * <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
- *
- * @param device Paired bluetooth device
- * @param priority
- * @return true if priority is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setPriority(BluetoothDevice device, int priority) {
- if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
- return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) Log.d(TAG, "setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothMapClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the priority of the profile.
- *
- * <p> The priority can be any of:
- * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * @param device Bluetooth device
- * @return priority of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public int getPriority(BluetoothDevice device) {
- if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
- return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
- if (VDBG) Log.d(TAG, "getConnectionPolicy(" + device + ")");
- final IBluetoothMapClient service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Send a message.
- *
- * Send an SMS message to either the contacts primary number or the telephone number specified.
- *
- * @param device Bluetooth device
- * @param contacts Uri Collection of the contacts
- * @param message Message to be sent
- * @param sentIntent intent issued when message is sent
- * @param deliveredIntent intent issued when message is delivered
- * @return true if the message is enqueued, false on error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.SEND_SMS,
- })
- public boolean sendMessage(@NonNull BluetoothDevice device, @NonNull Collection<Uri> contacts,
- @NonNull String message, @Nullable PendingIntent sentIntent,
- @Nullable PendingIntent deliveredIntent) {
- return sendMessage(device, contacts.toArray(new Uri[contacts.size()]), message, sentIntent,
- deliveredIntent);
- }
-
- /**
- * Send a message.
- *
- * Send an SMS message to either the contacts primary number or the telephone number specified.
- *
- * @param device Bluetooth device
- * @param contacts Uri[] of the contacts
- * @param message Message to be sent
- * @param sentIntent intent issued when message is sent
- * @param deliveredIntent intent issued when message is delivered
- * @return true if the message is enqueued, false on error
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.SEND_SMS,
- })
- public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
- PendingIntent sentIntent, PendingIntent deliveredIntent) {
- if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
- final IBluetoothMapClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.sendMessage(device, contacts, message, sentIntent, deliveredIntent,
- mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get unread messages. Unread messages will be published via {@link #ACTION_MESSAGE_RECEIVED}.
- *
- * @param device Bluetooth device
- * @return true if the message is enqueued, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.READ_SMS,
- })
- public boolean getUnreadMessages(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
- final IBluetoothMapClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.getUnreadMessages(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns the "Uploading" feature bit value from the SDP record's
- * MapSupportedFeatures field (see Bluetooth MAP 1.4 spec, page 114).
- * @param device The Bluetooth device to get this value for.
- * @return Returns true if the Uploading bit value in SDP record's
- * MapSupportedFeatures field is set. False is returned otherwise.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isUploadingSupported(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "isUploadingSupported(" + device + ")");
- final IBluetoothMapClient service = getService();
- final int defaultValue = 0;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getSupportedFeatures(device, mAttributionSource, recv);
- return (recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue)
- & UPLOADING_FEATURE_BITMASK) > 0;
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return false;
- }
-
- /**
- * Set message status of message on MSE
- * <p>
- * When read status changed, the result will be published via
- * {@link #ACTION_MESSAGE_READ_STATUS_CHANGED}
- * When deleted status changed, the result will be published via
- * {@link #ACTION_MESSAGE_DELETED_STATUS_CHANGED}
- *
- * @param device Bluetooth device
- * @param handle message handle
- * @param status <code>UNREAD</code> for "unread", <code>READ</code> for
- * "read", <code>UNDELETED</code> for "undeleted", <code>DELETED</code> for
- * "deleted", otherwise return error
- * @return <code>true</code> if request has been sent, <code>false</code> on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.READ_SMS,
- })
- public boolean setMessageStatus(BluetoothDevice device, String handle, int status) {
- if (DBG) Log.d(TAG, "setMessageStatus(" + device + ", " + handle + ", " + status + ")");
- final IBluetoothMapClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device) && handle != null && (status == READ
- || status == UNREAD || status == UNDELETED || status == DELETED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setMessageStatus(device, handle, status, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private boolean isEnabled() {
- return mAdapter.isEnabled();
- }
-
- private static boolean isValidDevice(BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothMasInstance.java b/core/java/android/bluetooth/BluetoothMasInstance.java
deleted file mode 100644
index eeaf085..0000000
--- a/core/java/android/bluetooth/BluetoothMasInstance.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public final class BluetoothMasInstance implements Parcelable {
- private final int mId;
- private final String mName;
- private final int mChannel;
- private final int mMsgTypes;
-
- public BluetoothMasInstance(int id, String name, int channel, int msgTypes) {
- mId = id;
- mName = name;
- mChannel = channel;
- mMsgTypes = msgTypes;
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (o instanceof BluetoothMasInstance) {
- return mId == ((BluetoothMasInstance) o).mId;
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return mId + (mChannel << 8) + (mMsgTypes << 16);
- }
-
- @Override
- public String toString() {
- return Integer.toString(mId) + ":" + mName + ":" + mChannel + ":"
- + Integer.toHexString(mMsgTypes);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BluetoothMasInstance> CREATOR =
- new Parcelable.Creator<BluetoothMasInstance>() {
- public BluetoothMasInstance createFromParcel(Parcel in) {
- return new BluetoothMasInstance(in.readInt(), in.readString(),
- in.readInt(), in.readInt());
- }
-
- public BluetoothMasInstance[] newArray(int size) {
- return new BluetoothMasInstance[size];
- }
- };
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mId);
- out.writeString(mName);
- out.writeInt(mChannel);
- out.writeInt(mMsgTypes);
- }
-
- public static final class MessageType {
- public static final int EMAIL = 0x01;
- public static final int SMS_GSM = 0x02;
- public static final int SMS_CDMA = 0x04;
- public static final int MMS = 0x08;
- }
-
- public int getId() {
- return mId;
- }
-
- public String getName() {
- return mName;
- }
-
- public int getChannel() {
- return mChannel;
- }
-
- public int getMsgTypes() {
- return mMsgTypes;
- }
-
- public boolean msgSupported(int msg) {
- return (mMsgTypes & msg) != 0;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothOutputStream.java b/core/java/android/bluetooth/BluetoothOutputStream.java
deleted file mode 100644
index ac2b3ed..0000000
--- a/core/java/android/bluetooth/BluetoothOutputStream.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2009 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.bluetooth;
-
-import android.annotation.SuppressLint;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * BluetoothOutputStream.
- *
- * Used to read from a Bluetooth socket.
- *
- * @hide
- */
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-/*package*/ final class BluetoothOutputStream extends OutputStream {
- private BluetoothSocket mSocket;
-
- /*package*/ BluetoothOutputStream(BluetoothSocket s) {
- mSocket = s;
- }
-
- /**
- * Close this output stream and the socket associated with it.
- */
- public void close() throws IOException {
- mSocket.close();
- }
-
- /**
- * Writes a single byte to this stream. Only the least significant byte of
- * the integer {@code oneByte} is written to the stream.
- *
- * @param oneByte the byte to be written.
- * @throws IOException if an error occurs while writing to this stream.
- * @since Android 1.0
- */
- public void write(int oneByte) throws IOException {
- byte[] b = new byte[1];
- b[0] = (byte) oneByte;
- mSocket.write(b, 0, 1);
- }
-
- /**
- * Writes {@code count} bytes from the byte array {@code buffer} starting
- * at position {@code offset} to this stream.
- *
- * @param b the buffer to be written.
- * @param offset the start position in {@code buffer} from where to get bytes.
- * @param count the number of bytes from {@code buffer} to write to this stream.
- * @throws IOException if an error occurs while writing to this stream.
- * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code count < 0}, or if {@code
- * offset + count} is bigger than the length of {@code buffer}.
- * @since Android 1.0
- */
- public void write(byte[] b, int offset, int count) throws IOException {
- if (b == null) {
- throw new NullPointerException("buffer is null");
- }
- if ((offset | count) < 0 || count > b.length - offset) {
- throw new IndexOutOfBoundsException("invalid offset or length");
- }
- mSocket.write(b, offset, count);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
deleted file mode 100644
index d4ad4ef4..0000000
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Copyright (C) 2008 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.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the APIs to control the Bluetooth Pan
- * Profile.
- *
- * <p>BluetoothPan is a proxy object for controlling the Bluetooth
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothPan proxy object.
- *
- * <p>Each method is protected with its appropriate permission.
- *
- * @hide
- */
-@SystemApi
-public final class BluetoothPan implements BluetoothProfile {
- private static final String TAG = "BluetoothPan";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Intent used to broadcast the change in connection state of the Pan
- * profile.
- *
- * <p>This intent will have 4 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * <li> {@link #EXTRA_LOCAL_ROLE} - Which local role the remote device is
- * bound to. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- *
- * <p> {@link #EXTRA_LOCAL_ROLE} can be one of {@link #LOCAL_NAP_ROLE} or
- * {@link #LOCAL_PANU_ROLE}
- */
- @SuppressLint("ActionValue")
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
-
- /**
- * Extra for {@link #ACTION_CONNECTION_STATE_CHANGED} intent
- * The local role of the PAN profile that the remote device is bound to.
- * It can be one of {@link #LOCAL_NAP_ROLE} or {@link #LOCAL_PANU_ROLE}.
- */
- @SuppressLint("ActionValue")
- public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
-
- /**
- * Intent used to broadcast the change in tethering state of the Pan
- * Profile
- *
- * <p>This intent will have 1 extra:
- * <ul>
- * <li> {@link #EXTRA_TETHERING_STATE} - The current state of Bluetooth
- * tethering. </li>
- * </ul>
- *
- * <p> {@link #EXTRA_TETHERING_STATE} can be any of {@link #TETHERING_STATE_OFF} or
- * {@link #TETHERING_STATE_ON}
- */
- @RequiresLegacyBluetoothPermission
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_TETHERING_STATE_CHANGED =
- "android.bluetooth.action.TETHERING_STATE_CHANGED";
-
- /**
- * Extra for {@link #ACTION_TETHERING_STATE_CHANGED} intent
- * The tethering state of the PAN profile.
- * It can be one of {@link #TETHERING_STATE_OFF} or {@link #TETHERING_STATE_ON}.
- */
- public static final String EXTRA_TETHERING_STATE =
- "android.bluetooth.extra.TETHERING_STATE";
-
- /** @hide */
- @IntDef({PAN_ROLE_NONE, LOCAL_NAP_ROLE, LOCAL_PANU_ROLE})
- @Retention(RetentionPolicy.SOURCE)
- public @interface LocalPanRole {}
-
- public static final int PAN_ROLE_NONE = 0;
- /**
- * The local device is acting as a Network Access Point.
- */
- public static final int LOCAL_NAP_ROLE = 1;
-
- /**
- * The local device is acting as a PAN User.
- */
- public static final int LOCAL_PANU_ROLE = 2;
-
- /** @hide */
- @IntDef({PAN_ROLE_NONE, REMOTE_NAP_ROLE, REMOTE_PANU_ROLE})
- @Retention(RetentionPolicy.SOURCE)
- public @interface RemotePanRole {}
-
- public static final int REMOTE_NAP_ROLE = 1;
-
- public static final int REMOTE_PANU_ROLE = 2;
-
- /** @hide **/
- @IntDef({TETHERING_STATE_OFF, TETHERING_STATE_ON})
- @Retention(RetentionPolicy.SOURCE)
- public @interface TetheringState{}
-
- public static final int TETHERING_STATE_OFF = 1;
-
- public static final int TETHERING_STATE_ON = 2;
- /**
- * Return codes for the connect and disconnect Bluez / Dbus calls.
- *
- * @hide
- */
- public static final int PAN_DISCONNECT_FAILED_NOT_CONNECTED = 1000;
-
- /**
- * @hide
- */
- public static final int PAN_CONNECT_FAILED_ALREADY_CONNECTED = 1001;
-
- /**
- * @hide
- */
- public static final int PAN_CONNECT_FAILED_ATTEMPT_FAILED = 1002;
-
- /**
- * @hide
- */
- public static final int PAN_OPERATION_GENERIC_FAILURE = 1003;
-
- /**
- * @hide
- */
- public static final int PAN_OPERATION_SUCCESS = 1004;
-
- private final Context mContext;
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothPan> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.PAN,
- "BluetoothPan", IBluetoothPan.class.getName()) {
- @Override
- public IBluetoothPan getServiceInterface(IBinder service) {
- return IBluetoothPan.Stub.asInterface(service);
- }
- };
-
-
- /**
- * Create a BluetoothPan proxy object for interacting with the local
- * Bluetooth Service which handles the Pan profile
- *
- * @hide
- */
- @UnsupportedAppUsage
- /* package */ BluetoothPan(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mContext = context;
- mProfileConnector.connect(context, listener);
- }
-
- /**
- * Closes the connection to the service and unregisters callbacks
- */
- @UnsupportedAppUsage
- void close() {
- if (VDBG) log("close()");
- mProfileConnector.disconnect();
- }
-
- private IBluetoothPan getService() {
- return mProfileConnector.getService();
- }
-
- /** @hide */
- protected void finalize() {
- close();
- }
-
- /**
- * Initiate connection to a profile of the remote bluetooth device.
- *
- * <p> This API returns false in scenarios like the profile on the
- * device is already connected or Bluetooth is not turned on.
- * When this API returns true, it is guaranteed that
- * connection state intent for the profile will be broadcasted with
- * the state. Users can get the connection state of the profile
- * from this intent.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean connect(BluetoothDevice device) {
- if (DBG) log("connect(" + device + ")");
- final IBluetoothPan service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate disconnection from a profile
- *
- * <p> This API will return false in scenarios like the profile on the
- * Bluetooth device is not in connected state etc. When this API returns,
- * true, it is guaranteed that the connection state change
- * intent will be broadcasted with the state. Users can get the
- * disconnection state of the profile from this intent.
- *
- * <p> If the disconnection is initiated by a remote device, the state
- * will transition from {@link #STATE_CONNECTED} to
- * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
- * host (local) device the state will transition from
- * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
- * state {@link #STATE_DISCONNECTED}. The transition to
- * {@link #STATE_DISCONNECTING} can be used to distinguish between the
- * two scenarios.
- *
- * @param device Remote Bluetooth Device
- * @return false on immediate error, true otherwise
- * @hide
- */
- @UnsupportedAppUsage
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) log("disconnect(" + device + ")");
- final IBluetoothPan service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothPan service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- * @hide
- */
- @SystemApi
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @NonNull List<BluetoothDevice> getConnectedDevices() {
- if (VDBG) log("getConnectedDevices()");
- final IBluetoothPan service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- * @hide
- */
- @Override
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothPan service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- * @hide
- */
- @SystemApi
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public int getConnectionState(@NonNull BluetoothDevice device) {
- if (VDBG) log("getState(" + device + ")");
- final IBluetoothPan service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Turns on/off bluetooth tethering
- *
- * @param value is whether to enable or disable bluetooth tethering
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- android.Manifest.permission.TETHER_PRIVILEGED,
- })
- public void setBluetoothTethering(boolean value) {
- String pkgName = mContext.getOpPackageName();
- if (DBG) log("setBluetoothTethering(" + value + "), calling package:" + pkgName);
- final IBluetoothPan service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.setBluetoothTethering(value, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Determines whether tethering is enabled
- *
- * @return true if tethering is on, false if not or some error occurred
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isTetheringOn() {
- if (VDBG) log("isTetheringOn()");
- final IBluetoothPan service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isTetheringOn(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- @UnsupportedAppUsage
- private boolean isEnabled() {
- return mAdapter.getState() == BluetoothAdapter.STATE_ON;
- }
-
- @UnsupportedAppUsage
- private static boolean isValidDevice(BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-
- @UnsupportedAppUsage
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
deleted file mode 100644
index de2db9c..0000000
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2008 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.bluetooth;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Public API for controlling the Bluetooth Pbap Service. This includes
- * Bluetooth Phone book Access profile.
- * BluetoothPbap is a proxy object for controlling the Bluetooth Pbap
- * Service via IPC.
- *
- * Creating a BluetoothPbap object will create a binding with the
- * BluetoothPbap service. Users of this object should call close() when they
- * are finished with the BluetoothPbap, so that this proxy object can unbind
- * from the service.
- *
- * This BluetoothPbap object is not immediately bound to the
- * BluetoothPbap service. Use the ServiceListener interface to obtain a
- * notification when it is bound, this is especially important if you wish to
- * immediately call methods on BluetoothPbap after construction.
- *
- * To get an instance of the BluetoothPbap class, you can call
- * {@link BluetoothAdapter#getProfileProxy(Context, ServiceListener, int)} with the final param
- * being {@link BluetoothProfile#PBAP}. The ServiceListener should be able to get the instance of
- * BluetoothPbap in {@link android.bluetooth.BluetoothProfile.ServiceListener#onServiceConnected}.
- *
- * Android only supports one connected Bluetooth Pce at a time.
- *
- * @hide
- */
-@SystemApi
-public class BluetoothPbap implements BluetoothProfile {
-
- private static final String TAG = "BluetoothPbap";
- private static final boolean DBG = false;
-
- /**
- * Intent used to broadcast the change in connection state of the PBAP
- * profile.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link BluetoothProfile#EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link BluetoothProfile#EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- * <p>{@link BluetoothProfile#EXTRA_STATE} or {@link BluetoothProfile#EXTRA_PREVIOUS_STATE}
- * can be any of {@link BluetoothProfile#STATE_DISCONNECTED},
- * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_CONNECTED},
- * {@link BluetoothProfile#STATE_DISCONNECTING}.
- *
- * @hide
- */
- @SuppressLint("ActionValue")
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
-
- private final AttributionSource mAttributionSource;
-
- /** @hide */
- public static final int RESULT_FAILURE = 0;
- /** @hide */
- public static final int RESULT_SUCCESS = 1;
- /**
- * Connection canceled before completion.
- *
- * @hide
- */
- public static final int RESULT_CANCELED = 2;
-
- private BluetoothAdapter mAdapter;
- private final BluetoothProfileConnector<IBluetoothPbap> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.PBAP, "BluetoothPbap",
- IBluetoothPbap.class.getName()) {
- @Override
- public IBluetoothPbap getServiceInterface(IBinder service) {
- return IBluetoothPbap.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothPbap proxy object.
- *
- * @hide
- */
- public BluetoothPbap(Context context, ServiceListener listener, BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- /** @hide */
- protected void finalize() throws Throwable {
- try {
- close();
- } finally {
- super.finalize();
- }
- }
-
- /**
- * Close the connection to the backing service.
- * Other public functions of BluetoothPbap will return default error
- * results once close() has been called. Multiple invocations of close()
- * are ok.
- *
- * @hide
- */
- public synchronized void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothPbap getService() {
- return (IBluetoothPbap) mProfileConnector.getService();
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
- log("getConnectedDevices()");
- final IBluetoothPbap service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- return new ArrayList<BluetoothDevice>();
- }
- try {
- return Attributable.setAttributionSource(
- service.getConnectedDevices(mAttributionSource), mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
- return new ArrayList<BluetoothDevice>();
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
- @SystemApi
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) {
- log("getConnectionState: device=" + device);
- try {
- final IBluetoothPbap service = getService();
- if (service != null && isEnabled() && isValidDevice(device)) {
- return service.getConnectionState(device, mAttributionSource);
- }
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- }
- return BluetoothProfile.STATE_DISCONNECTED;
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
- return BluetoothProfile.STATE_DISCONNECTED;
- }
-
- /**
- * {@inheritDoc}
- *
- * @hide
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- log("getDevicesMatchingConnectionStates: states=" + Arrays.toString(states));
- final IBluetoothPbap service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- return new ArrayList<BluetoothDevice>();
- }
- try {
- return Attributable.setAttributionSource(
- service.getDevicesMatchingConnectionStates(states, mAttributionSource),
- mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
- return new ArrayList<BluetoothDevice>();
- }
-
- /**
- * Set connection policy of the profile and tries to disconnect it if connectionPolicy is
- * {@link BluetoothProfile#CONNECTION_POLICY_FORBIDDEN}
- *
- * <p> The device should already be paired.
- * Connection policy can be one of:
- * {@link BluetoothProfile#CONNECTION_POLICY_ALLOWED},
- * {@link BluetoothProfile#CONNECTION_POLICY_FORBIDDEN},
- * {@link BluetoothProfile#CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- try {
- final IBluetoothPbap service = getService();
- if (service != null && isEnabled()
- && isValidDevice(device)) {
- if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
- return false;
- }
- return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource);
- }
- if (service == null) Log.w(TAG, "Proxy not attached to service");
- return false;
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return false;
- }
- }
-
- /**
- * Disconnects the current Pbap client (PCE). Currently this call blocks,
- * it may soon be made asynchronous. Returns false if this proxy object is
- * not currently connected to the Pbap service.
- *
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnect(BluetoothDevice device) {
- log("disconnect()");
- final IBluetoothPbap service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- return false;
- }
- try {
- service.disconnect(device, mAttributionSource);
- return true;
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
- return false;
- }
-
- private boolean isEnabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
- return false;
- }
-
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
- }
-
- private static void log(String msg) {
- if (DBG) {
- Log.d(TAG, msg);
- }
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
deleted file mode 100644
index e096de8..0000000
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the APIs to control the Bluetooth PBAP Client Profile.
- *
- * @hide
- */
-public final class BluetoothPbapClient implements BluetoothProfile {
-
- private static final String TAG = "BluetoothPbapClient";
- private static final boolean DBG = false;
- private static final boolean VDBG = false;
-
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED";
-
- /** There was an error trying to obtain the state */
- public static final int STATE_ERROR = -1;
-
- public static final int RESULT_FAILURE = 0;
- public static final int RESULT_SUCCESS = 1;
- /** Connection canceled before completion. */
- public static final int RESULT_CANCELED = 2;
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothPbapClient> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.PBAP_CLIENT,
- "BluetoothPbapClient", IBluetoothPbapClient.class.getName()) {
- @Override
- public IBluetoothPbapClient getServiceInterface(IBinder service) {
- return IBluetoothPbapClient.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothPbapClient proxy object.
- */
- BluetoothPbapClient(Context context, ServiceListener listener, BluetoothAdapter adapter) {
- if (DBG) {
- Log.d(TAG, "Create BluetoothPbapClient proxy object");
- }
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- protected void finalize() throws Throwable {
- try {
- close();
- } finally {
- super.finalize();
- }
- }
-
- /**
- * Close the connection to the backing service.
- * Other public functions of BluetoothPbapClient will return default error
- * results once close() has been called. Multiple invocations of close()
- * are ok.
- */
- public synchronized void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothPbapClient getService() {
- return mProfileConnector.getService();
- }
-
- /**
- * Initiate connection.
- * Upon successful connection to remote PBAP server the Client will
- * attempt to automatically download the users phonebook and call log.
- *
- * @param device a remote device we want connect to
- * @return <code>true</code> if command has been issued successfully; <code>false</code>
- * otherwise;
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean connect(BluetoothDevice device) {
- if (DBG) {
- log("connect(" + device + ") for PBAP Client.");
- }
- final IBluetoothPbapClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.connect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate disconnect.
- *
- * @param device Remote Bluetooth Device
- * @return false on error, true otherwise
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) {
- log("disconnect(" + device + ")" + new Exception());
- }
- final IBluetoothPbapClient service = getService();
- final boolean defaultValue = true;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- return true;
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the list of connected devices.
- * Currently at most one.
- *
- * @return list of connected devices
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
- if (DBG) {
- log("getConnectedDevices()");
- }
- final IBluetoothPbapClient service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the list of devices matching specified states. Currently at most one.
- *
- * @return list of matching devices
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (DBG) {
- log("getDevicesMatchingStates()");
- }
- final IBluetoothPbapClient service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get connection state of device
- *
- * @return device connection state
- */
- @Override
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
- if (DBG) {
- log("getConnectionState(" + device + ")");
- }
- final IBluetoothPbapClient service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-
- private boolean isEnabled() {
- return mAdapter.isEnabled();
- }
-
- private static boolean isValidDevice(BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-
- /**
- * Set priority of the profile
- *
- * <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
- *
- * @param device Paired bluetooth device
- * @param priority
- * @return true if priority is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setPriority(BluetoothDevice device, int priority) {
- if (DBG) log("setPriority(" + device + ", " + priority + ")");
- return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) {
- log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- }
- final IBluetoothPbapClient service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the priority of the profile.
- *
- * <p> The priority can be any of:
- * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * @param device Bluetooth device
- * @return priority of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public int getPriority(BluetoothDevice device) {
- if (VDBG) log("getPriority(" + device + ")");
- return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
- if (VDBG) {
- log("getConnectionPolicy(" + device + ")");
- }
- final IBluetoothPbapClient service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
deleted file mode 100644
index d0f74e9..0000000
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright (C) 2010-2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.RequiresNoPermission;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-
-/**
- * Public APIs for the Bluetooth Profiles.
- *
- * <p> Clients should call {@link BluetoothAdapter#getProfileProxy},
- * to get the Profile Proxy. Each public profile implements this
- * interface.
- */
-public interface BluetoothProfile {
-
- /**
- * Extra for the connection state intents of the individual profiles.
- *
- * This extra represents the current connection state of the profile of the
- * Bluetooth device.
- */
- @SuppressLint("ActionValue")
- String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
-
- /**
- * Extra for the connection state intents of the individual profiles.
- *
- * This extra represents the previous connection state of the profile of the
- * Bluetooth device.
- */
- @SuppressLint("ActionValue")
- String EXTRA_PREVIOUS_STATE =
- "android.bluetooth.profile.extra.PREVIOUS_STATE";
-
- /** The profile is in disconnected state */
- int STATE_DISCONNECTED = 0;
- /** The profile is in connecting state */
- int STATE_CONNECTING = 1;
- /** The profile is in connected state */
- int STATE_CONNECTED = 2;
- /** The profile is in disconnecting state */
- int STATE_DISCONNECTING = 3;
-
- /** @hide */
- @IntDef({
- STATE_DISCONNECTED,
- STATE_CONNECTING,
- STATE_CONNECTED,
- STATE_DISCONNECTING,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface BtProfileState {}
-
- /**
- * Headset and Handsfree profile
- */
- int HEADSET = 1;
-
- /**
- * A2DP profile.
- */
- int A2DP = 2;
-
- /**
- * Health Profile
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
- @Deprecated
- int HEALTH = 3;
-
- /**
- * HID Host
- *
- * @hide
- */
- int HID_HOST = 4;
-
- /**
- * PAN Profile
- *
- * @hide
- */
- @SystemApi
- int PAN = 5;
-
- /**
- * PBAP
- *
- * @hide
- */
- int PBAP = 6;
-
- /**
- * GATT
- */
- int GATT = 7;
-
- /**
- * GATT_SERVER
- */
- int GATT_SERVER = 8;
-
- /**
- * MAP Profile
- *
- * @hide
- */
- int MAP = 9;
-
- /*
- * SAP Profile
- * @hide
- */
- int SAP = 10;
-
- /**
- * A2DP Sink Profile
- *
- * @hide
- */
- @SystemApi
- int A2DP_SINK = 11;
-
- /**
- * AVRCP Controller Profile
- *
- * @hide
- */
- @SystemApi
- int AVRCP_CONTROLLER = 12;
-
- /**
- * AVRCP Target Profile
- *
- * @hide
- */
- int AVRCP = 13;
-
- /**
- * Headset Client - HFP HF Role
- *
- * @hide
- */
- @SystemApi
- int HEADSET_CLIENT = 16;
-
- /**
- * PBAP Client
- *
- * @hide
- */
- @SystemApi
- int PBAP_CLIENT = 17;
-
- /**
- * MAP Messaging Client Equipment (MCE)
- *
- * @hide
- */
- @SystemApi
- int MAP_CLIENT = 18;
-
- /**
- * HID Device
- */
- int HID_DEVICE = 19;
-
- /**
- * Object Push Profile (OPP)
- *
- * @hide
- */
- int OPP = 20;
-
- /**
- * Hearing Aid Device
- *
- */
- int HEARING_AID = 21;
-
- /**
- * LE Audio Device
- *
- */
- int LE_AUDIO = 22;
-
- /**
- * Volume Control profile
- *
- * @hide
- */
- @SystemApi
- int VOLUME_CONTROL = 23;
-
- /**
- * @hide
- * Media Control Profile server
- *
- */
- int MCP_SERVER = 24;
-
- /**
- * Coordinated Set Identification Profile set coordinator
- *
- */
- int CSIP_SET_COORDINATOR = 25;
-
- /**
- * LE Audio Broadcast Source
- *
- * @hide
- */
- int LE_AUDIO_BROADCAST = 26;
-
- /**
- * @hide
- * Telephone Bearer Service from Call Control Profile
- *
- */
- int LE_CALL_CONTROL = 27;
-
- /**
- * Max profile ID. This value should be updated whenever a new profile is added to match
- * the largest value assigned to a profile.
- *
- * @hide
- */
- int MAX_PROFILE_ID = 27;
-
- /**
- * Default priority for devices that we try to auto-connect to and
- * and allow incoming connections for the profile
- *
- * @hide
- **/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- int PRIORITY_AUTO_CONNECT = 1000;
-
- /**
- * Default priority for devices that allow incoming
- * and outgoing connections for the profile
- *
- * @hide
- * @deprecated Replaced with {@link #CONNECTION_POLICY_ALLOWED}
- **/
- @Deprecated
- @SystemApi
- int PRIORITY_ON = 100;
-
- /**
- * Default priority for devices that does not allow incoming
- * connections and outgoing connections for the profile.
- *
- * @hide
- * @deprecated Replaced with {@link #CONNECTION_POLICY_FORBIDDEN}
- **/
- @Deprecated
- @SystemApi
- int PRIORITY_OFF = 0;
-
- /**
- * Default priority when not set or when the device is unpaired
- *
- * @hide
- */
- @UnsupportedAppUsage
- int PRIORITY_UNDEFINED = -1;
-
- /** @hide */
- @IntDef(prefix = "CONNECTION_POLICY_", value = {CONNECTION_POLICY_ALLOWED,
- CONNECTION_POLICY_FORBIDDEN, CONNECTION_POLICY_UNKNOWN})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ConnectionPolicy{}
-
- /**
- * Default connection policy for devices that allow incoming and outgoing connections
- * for the profile
- *
- * @hide
- **/
- @SystemApi
- int CONNECTION_POLICY_ALLOWED = 100;
-
- /**
- * Default connection policy for devices that do not allow incoming or outgoing connections
- * for the profile.
- *
- * @hide
- **/
- @SystemApi
- int CONNECTION_POLICY_FORBIDDEN = 0;
-
- /**
- * Default connection policy when not set or when the device is unpaired
- *
- * @hide
- */
- @SystemApi
- int CONNECTION_POLICY_UNKNOWN = -1;
-
- /**
- * Get connected devices for this specific profile.
- *
- * <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
- *
- * @return List of devices. The list will be empty on error.
- */
- public List<BluetoothDevice> getConnectedDevices();
-
- /**
- * Get a list of devices that match any of the given connection
- * states.
- *
- * <p> If none of the devices match any of the given states,
- * an empty list will be returned.
- *
- * @param states Array of states. States can be one of {@link #STATE_CONNECTED}, {@link
- * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
- * @return List of devices. The list will be empty on error.
- */
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states);
-
- /**
- * Get the current connection state of the profile
- *
- * @param device Remote bluetooth device.
- * @return State of the profile connection. One of {@link #STATE_CONNECTED}, {@link
- * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
- */
- @BtProfileState int getConnectionState(BluetoothDevice device);
-
- /**
- * An interface for notifying BluetoothProfile IPC clients when they have
- * been connected or disconnected to the service.
- */
- public interface ServiceListener {
- /**
- * Called to notify the client when the proxy object has been
- * connected to the service.
- *
- * @param profile - One of {@link #HEADSET} or {@link #A2DP}
- * @param proxy - One of {@link BluetoothHeadset} or {@link BluetoothA2dp}
- */
- @RequiresNoPermission
- public void onServiceConnected(int profile, BluetoothProfile proxy);
-
- /**
- * Called to notify the client that this proxy object has been
- * disconnected from the service.
- *
- * @param profile - One of {@link #HEADSET} or {@link #A2DP}
- */
- @RequiresNoPermission
- public void onServiceDisconnected(int profile);
- }
-
- /**
- * Convert an integer value of connection state into human readable string
- *
- * @param connectionState - One of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, or {@link #STATE_DISCONNECTED}
- * @return a string representation of the connection state, STATE_UNKNOWN if the state
- * is not defined
- * @hide
- */
- static String getConnectionStateName(int connectionState) {
- switch (connectionState) {
- case STATE_DISCONNECTED:
- return "STATE_DISCONNECTED";
- case STATE_CONNECTING:
- return "STATE_CONNECTING";
- case STATE_CONNECTED:
- return "STATE_CONNECTED";
- case STATE_DISCONNECTING:
- return "STATE_DISCONNECTING";
- default:
- return "STATE_UNKNOWN";
- }
- }
-
- /**
- * Convert an integer value of profile ID into human readable string
- *
- * @param profile profile ID
- * @return profile name as String, UNKOWN_PROFILE if the profile ID is not defined.
- * @hide
- */
- static String getProfileName(int profile) {
- switch(profile) {
- case HEADSET:
- return "HEADSET";
- case A2DP:
- return "A2DP";
- case HID_HOST:
- return "HID_HOST";
- case PAN:
- return "PAN";
- case PBAP:
- return "PBAP";
- case GATT:
- return "GATT";
- case GATT_SERVER:
- return "GATT_SERVER";
- case MAP:
- return "MAP";
- case SAP:
- return "SAP";
- case A2DP_SINK:
- return "A2DP_SINK";
- case AVRCP_CONTROLLER:
- return "AVRCP_CONTROLLER";
- case AVRCP:
- return "AVRCP";
- case HEADSET_CLIENT:
- return "HEADSET_CLIENT";
- case PBAP_CLIENT:
- return "PBAP_CLIENT";
- case MAP_CLIENT:
- return "MAP_CLIENT";
- case HID_DEVICE:
- return "HID_DEVICE";
- case OPP:
- return "OPP";
- case HEARING_AID:
- return "HEARING_AID";
- case LE_AUDIO:
- return "LE_AUDIO";
- default:
- return "UNKNOWN_PROFILE";
- }
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothProfileConnector.java b/core/java/android/bluetooth/BluetoothProfileConnector.java
deleted file mode 100644
index 79373f1a..0000000
--- a/core/java/android/bluetooth/BluetoothProfileConnector.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import java.util.List;
-/**
- * Connector for Bluetooth profile proxies to bind manager service and
- * profile services
- * @param <T> The Bluetooth profile interface for this connection.
- * @hide
- */
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-public abstract class BluetoothProfileConnector<T> {
- private final CloseGuard mCloseGuard = new CloseGuard();
- private final int mProfileId;
- private BluetoothProfile.ServiceListener mServiceListener;
- private final BluetoothProfile mProfileProxy;
- private Context mContext;
- private final String mProfileName;
- private final String mServiceName;
- private volatile T mService;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (up) {
- doBind();
- } else {
- doUnbind();
- }
- }
- };
-
- private @Nullable ComponentName resolveSystemService(@NonNull Intent intent,
- @NonNull PackageManager pm, @PackageManager.ComponentInfoFlags int flags) {
- List<ResolveInfo> results = pm.queryIntentServices(intent, flags);
- if (results == null) {
- return null;
- }
- ComponentName comp = null;
- for (int i = 0; i < results.size(); i++) {
- ResolveInfo ri = results.get(i);
- if ((ri.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- continue;
- }
- ComponentName foundComp = new ComponentName(ri.serviceInfo.applicationInfo.packageName,
- ri.serviceInfo.name);
- if (comp != null) {
- throw new IllegalStateException("Multiple system services handle " + intent
- + ": " + comp + ", " + foundComp);
- }
- comp = foundComp;
- }
- return comp;
- }
-
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- logDebug("Proxy object connected");
- mService = getServiceInterface(service);
-
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(mProfileId, mProfileProxy);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- logDebug("Proxy object disconnected");
- doUnbind();
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(mProfileId);
- }
- }
- };
-
- BluetoothProfileConnector(BluetoothProfile profile, int profileId, String profileName,
- String serviceName) {
- mProfileId = profileId;
- mProfileProxy = profile;
- mProfileName = profileName;
- mServiceName = serviceName;
- }
-
- /** {@hide} */
- @Override
- public void finalize() {
- mCloseGuard.warnIfOpen();
- doUnbind();
- }
-
- @SuppressLint("AndroidFrameworkRequiresPermission")
- private boolean doBind() {
- synchronized (mConnection) {
- if (mService == null) {
- logDebug("Binding service...");
- mCloseGuard.open("doUnbind");
- try {
- Intent intent = new Intent(mServiceName);
- ComponentName comp = resolveSystemService(intent, mContext.getPackageManager(),
- 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT)) {
- logError("Could not bind to Bluetooth Service with " + intent);
- return false;
- }
- } catch (SecurityException se) {
- logError("Failed to bind service. " + se);
- return false;
- }
- }
- }
- return true;
- }
-
- private void doUnbind() {
- synchronized (mConnection) {
- if (mService != null) {
- logDebug("Unbinding service...");
- mCloseGuard.close();
- try {
- mContext.unbindService(mConnection);
- } catch (IllegalArgumentException ie) {
- logError("Unable to unbind service: " + ie);
- } finally {
- mService = null;
- }
- }
- }
- }
-
- void connect(Context context, BluetoothProfile.ServiceListener listener) {
- mContext = context;
- mServiceListener = listener;
- IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
-
- // Preserve legacy compatibility where apps were depending on
- // registerStateChangeCallback() performing a permissions check which
- // has been relaxed in modern platform versions
- if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.R
- && context.checkSelfPermission(android.Manifest.permission.BLUETOOTH)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Need BLUETOOTH permission");
- }
-
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- logError("Failed to register state change callback. " + re);
- }
- }
- doBind();
- }
-
- void disconnect() {
- mServiceListener = null;
- IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- logError("Failed to unregister state change callback" + re);
- }
- }
- doUnbind();
- }
-
- T getService() {
- return mService;
- }
-
- /**
- * This abstract function is used to implement method to get the
- * connected Bluetooth service interface.
- * @param service the connected binder service.
- * @return T the binder interface of {@code service}.
- * @hide
- */
- public abstract T getServiceInterface(IBinder service);
-
- private void logDebug(String log) {
- Log.d(mProfileName, log);
- }
-
- private void logError(String log) {
- Log.e(mProfileName, log);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
deleted file mode 100644
index 808fa39..0000000
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright (C) 2008 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.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the APIs to control the Bluetooth SIM
- * Access Profile (SAP).
- *
- * <p>BluetoothSap is a proxy object for controlling the Bluetooth
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothSap proxy object.
- *
- * <p>Each method is protected with its appropriate permission.
- *
- * @hide
- */
-public final class BluetoothSap implements BluetoothProfile {
-
- private static final String TAG = "BluetoothSap";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Intent used to broadcast the change in connection state of the profile.
- *
- * <p>This intent will have 4 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- *
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
-
- /**
- * There was an error trying to obtain the state.
- *
- * @hide
- */
- public static final int STATE_ERROR = -1;
-
- /**
- * Connection state change succceeded.
- *
- * @hide
- */
- public static final int RESULT_SUCCESS = 1;
-
- /**
- * Connection canceled before completion.
- *
- * @hide
- */
- public static final int RESULT_CANCELED = 2;
-
- private final BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothSap> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.SAP,
- "BluetoothSap", IBluetoothSap.class.getName()) {
- @Override
- public IBluetoothSap getServiceInterface(IBinder service) {
- return IBluetoothSap.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothSap proxy object.
- */
- /* package */ BluetoothSap(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- if (DBG) Log.d(TAG, "Create BluetoothSap proxy object");
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- }
-
- protected void finalize() throws Throwable {
- try {
- close();
- } finally {
- super.finalize();
- }
- }
-
- /**
- * Close the connection to the backing service.
- * Other public functions of BluetoothSap will return default error
- * results once close() has been called. Multiple invocations of close()
- * are ok.
- *
- * @hide
- */
- public synchronized void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothSap getService() {
- return mProfileConnector.getService();
- }
-
- /**
- * Get the current state of the BluetoothSap service.
- *
- * @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not
- * connected to the Sap service.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getState() {
- if (VDBG) log("getState()");
- final IBluetoothSap service = getService();
- final int defaultValue = BluetoothSap.STATE_ERROR;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getState(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the currently connected remote Bluetooth device (PCE).
- *
- * @return The remote Bluetooth device, or null if not in connected or connecting state, or if
- * this proxy object is not connected to the Sap service.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public BluetoothDevice getClient() {
- if (VDBG) log("getClient()");
- final IBluetoothSap service = getService();
- final BluetoothDevice defaultValue = null;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<BluetoothDevice> recv =
- new SynchronousResultReceiver();
- service.getClient(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Returns true if the specified Bluetooth device is connected.
- * Returns false if not connected, or if this proxy object is not
- * currently connected to the Sap service.
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isConnected(BluetoothDevice device) {
- if (VDBG) log("isConnected(" + device + ")");
- final IBluetoothSap service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isConnected(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Initiate connection. Initiation of outgoing connections is not
- * supported for SAP server.
- *
- * @hide
- */
- @RequiresNoPermission
- public boolean connect(BluetoothDevice device) {
- if (DBG) log("connect(" + device + ")" + "not supported for SAPS");
- return false;
- }
-
- /**
- * Initiate disconnect.
- *
- * @param device Remote Bluetooth Device
- * @return false on error, true otherwise
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnect(BluetoothDevice device) {
- if (DBG) log("disconnect(" + device + ")");
- final IBluetoothSap service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.disconnect(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the list of connected devices. Currently at most one.
- *
- * @return list of connected devices
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
- if (DBG) log("getConnectedDevices()");
- final IBluetoothSap service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the list of devices matching specified states. Currently at most one.
- *
- * @return list of matching devices
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (DBG) log("getDevicesMatchingStates()");
- final IBluetoothSap service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get connection state of device
- *
- * @return device connection state
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
- if (DBG) log("getConnectionState(" + device + ")");
- final IBluetoothSap service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Set priority of the profile
- *
- * <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
- *
- * @param device Paired bluetooth device
- * @param priority
- * @return true if priority is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setPriority(BluetoothDevice device, int priority) {
- if (DBG) log("setPriority(" + device + ", " + priority + ")");
- return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothSap service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the priority of the profile.
- *
- * <p> The priority can be any of:
- * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
- *
- * @param device Bluetooth device
- * @return priority of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public int getPriority(BluetoothDevice device) {
- if (VDBG) log("getPriority(" + device + ")");
- return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionPolicy int getConnectionPolicy(BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- final IBluetoothSap service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-
- private boolean isEnabled() {
- return mAdapter.isEnabled();
- }
-
- private static boolean isValidDevice(BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
deleted file mode 100644
index bb4e354..0000000
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2009 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.bluetooth;
-
-import android.annotation.SuppressLint;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Handler;
-import android.os.ParcelUuid;
-import android.util.Log;
-
-import java.io.Closeable;
-import java.io.IOException;
-
-/**
- * A listening Bluetooth socket.
- *
- * <p>The interface for Bluetooth Sockets is similar to that of TCP sockets:
- * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server
- * side, use a {@link BluetoothServerSocket} to create a listening server
- * socket. When a connection is accepted by the {@link BluetoothServerSocket},
- * it will return a new {@link BluetoothSocket} to manage the connection.
- * On the client side, use a single {@link BluetoothSocket} to both initiate
- * an outgoing connection and to manage the connection.
- *
- * <p>For Bluetooth BR/EDR, the most common type of socket is RFCOMM, which is the type supported by
- * the Android APIs. RFCOMM is a connection-oriented, streaming transport over Bluetooth BR/EDR. It
- * is also known as the Serial Port Profile (SPP). To create a listening
- * {@link BluetoothServerSocket} that's ready for incoming Bluetooth BR/EDR connections, use {@link
- * BluetoothAdapter#listenUsingRfcommWithServiceRecord
- * BluetoothAdapter.listenUsingRfcommWithServiceRecord()}.
- *
- * <p>For Bluetooth LE, the socket uses LE Connection-oriented Channel (CoC). LE CoC is a
- * connection-oriented, streaming transport over Bluetooth LE and has a credit-based flow control.
- * Correspondingly, use {@link BluetoothAdapter#listenUsingL2capChannel
- * BluetoothAdapter.listenUsingL2capChannel()} to create a listening {@link BluetoothServerSocket}
- * that's ready for incoming Bluetooth LE CoC connections. For LE CoC, you can use {@link #getPsm()}
- * to get the protocol/service multiplexer (PSM) value that the peer needs to use to connect to your
- * socket.
- *
- * <p> After the listening {@link BluetoothServerSocket} is created, call {@link #accept()} to
- * listen for incoming connection requests. This call will block until a connection is established,
- * at which point, it will return a {@link BluetoothSocket} to manage the connection. Once the
- * {@link BluetoothSocket} is acquired, it's a good idea to call {@link #close()} on the {@link
- * BluetoothServerSocket} when it's no longer needed for accepting
- * connections. Closing the {@link BluetoothServerSocket} will <em>not</em> close the returned
- * {@link BluetoothSocket}.
- *
- * <p>{@link BluetoothServerSocket} is thread
- * safe. In particular, {@link #close} will always immediately abort ongoing
- * operations and close the server socket.
- *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about using Bluetooth, read the
- * <a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer guide.</p>
- * </div>
- *
- * {@see BluetoothSocket}
- */
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-public final class BluetoothServerSocket implements Closeable {
-
- private static final String TAG = "BluetoothServerSocket";
- private static final boolean DBG = false;
- @UnsupportedAppUsage(publicAlternatives = "Use public {@link BluetoothServerSocket} API "
- + "instead.")
- /*package*/ final BluetoothSocket mSocket;
- private Handler mHandler;
- private int mMessage;
- private int mChannel;
-
- /**
- * Construct a socket for incoming connections.
- *
- * @param type type of socket
- * @param auth require the remote device to be authenticated
- * @param encrypt require the connection to be encrypted
- * @param port remote port
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * privileges
- */
- /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port)
- throws IOException {
- mChannel = port;
- mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null);
- if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
- mSocket.setExcludeSdp(true);
- }
- }
-
- /**
- * Construct a socket for incoming connections.
- *
- * @param type type of socket
- * @param auth require the remote device to be authenticated
- * @param encrypt require the connection to be encrypted
- * @param port remote port
- * @param mitm enforce person-in-the-middle protection for authentication.
- * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * privileges
- */
- /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port,
- boolean mitm, boolean min16DigitPin)
- throws IOException {
- mChannel = port;
- mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null, mitm,
- min16DigitPin);
- if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
- mSocket.setExcludeSdp(true);
- }
- }
-
- /**
- * Construct a socket for incoming connections.
- *
- * @param type type of socket
- * @param auth require the remote device to be authenticated
- * @param encrypt require the connection to be encrypted
- * @param uuid uuid
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * privileges
- */
- /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, ParcelUuid uuid)
- throws IOException {
- mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, -1, uuid);
- // TODO: This is the same as mChannel = -1 - is this intentional?
- mChannel = mSocket.getPort();
- }
-
-
- /**
- * Block until a connection is established.
- * <p>Returns a connected {@link BluetoothSocket} on successful connection.
- * <p>Once this call returns, it can be called again to accept subsequent
- * incoming connections.
- * <p>{@link #close} can be used to abort this call from another thread.
- *
- * @return a connected {@link BluetoothSocket}
- * @throws IOException on error, for example this call was aborted, or timeout
- */
- public BluetoothSocket accept() throws IOException {
- return accept(-1);
- }
-
- /**
- * Block until a connection is established, with timeout.
- * <p>Returns a connected {@link BluetoothSocket} on successful connection.
- * <p>Once this call returns, it can be called again to accept subsequent
- * incoming connections.
- * <p>{@link #close} can be used to abort this call from another thread.
- *
- * @return a connected {@link BluetoothSocket}
- * @throws IOException on error, for example this call was aborted, or timeout
- */
- public BluetoothSocket accept(int timeout) throws IOException {
- return mSocket.accept(timeout);
- }
-
- /**
- * Immediately close this socket, and release all associated resources.
- * <p>Causes blocked calls on this socket in other threads to immediately
- * throw an IOException.
- * <p>Closing the {@link BluetoothServerSocket} will <em>not</em>
- * close any {@link BluetoothSocket} received from {@link #accept()}.
- */
- public void close() throws IOException {
- if (DBG) Log.d(TAG, "BluetoothServerSocket:close() called. mChannel=" + mChannel);
- synchronized (this) {
- if (mHandler != null) {
- mHandler.obtainMessage(mMessage).sendToTarget();
- }
- }
- mSocket.close();
- }
-
- /*package*/
- synchronized void setCloseHandler(Handler handler, int message) {
- mHandler = handler;
- mMessage = message;
- }
-
- /*package*/ void setServiceName(String serviceName) {
- mSocket.setServiceName(serviceName);
- }
-
- /**
- * Returns the channel on which this socket is bound.
- *
- * @hide
- */
- public int getChannel() {
- return mChannel;
- }
-
- /**
- * Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP
- * Connection-oriented Channel (CoC) server socket. This server socket must be returned by the
- * {@link BluetoothAdapter#listenUsingL2capChannel()} or {@link
- * BluetoothAdapter#listenUsingInsecureL2capChannel()}. The returned value is undefined if this
- * method is called on non-L2CAP server sockets.
- *
- * @return the assigned PSM or LE_PSM value depending on transport
- */
- public int getPsm() {
- return mChannel;
- }
-
- /**
- * Sets the channel on which future sockets are bound.
- * Currently used only when a channel is auto generated.
- */
- /*package*/ void setChannel(int newChannel) {
- /* TODO: From a design/architecture perspective this is wrong.
- * The bind operation should be conducted through this class
- * and the resulting port should be kept in mChannel, and
- * not set from BluetoothAdapter. */
- if (mSocket != null) {
- if (mSocket.getPort() != newChannel) {
- Log.w(TAG, "The port set is different that the underlying port. mSocket.getPort(): "
- + mSocket.getPort() + " requested newChannel: " + newChannel);
- }
- }
- mChannel = newChannel;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("ServerSocket: Type: ");
- switch (mSocket.getConnectionType()) {
- case BluetoothSocket.TYPE_RFCOMM: {
- sb.append("TYPE_RFCOMM");
- break;
- }
- case BluetoothSocket.TYPE_L2CAP: {
- sb.append("TYPE_L2CAP");
- break;
- }
- case BluetoothSocket.TYPE_L2CAP_LE: {
- sb.append("TYPE_L2CAP_LE");
- break;
- }
- case BluetoothSocket.TYPE_SCO: {
- sb.append("TYPE_SCO");
- break;
- }
- }
- sb.append(" Channel: ").append(mChannel);
- return sb.toString();
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
deleted file mode 100644
index db5b751..0000000
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ /dev/null
@@ -1,809 +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.bluetooth;
-
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.net.LocalSocket;
-import android.os.Build;
-import android.os.ParcelFileDescriptor;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.Closeable;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.Locale;
-import java.util.UUID;
-
-/**
- * A connected or connecting Bluetooth socket.
- *
- * <p>The interface for Bluetooth Sockets is similar to that of TCP sockets:
- * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server
- * side, use a {@link BluetoothServerSocket} to create a listening server
- * socket. When a connection is accepted by the {@link BluetoothServerSocket},
- * it will return a new {@link BluetoothSocket} to manage the connection.
- * On the client side, use a single {@link BluetoothSocket} to both initiate
- * an outgoing connection and to manage the connection.
- *
- * <p>The most common type of Bluetooth socket is RFCOMM, which is the type
- * supported by the Android APIs. RFCOMM is a connection-oriented, streaming
- * transport over Bluetooth. It is also known as the Serial Port Profile (SPP).
- *
- * <p>To create a {@link BluetoothSocket} for connecting to a known device, use
- * {@link BluetoothDevice#createRfcommSocketToServiceRecord
- * BluetoothDevice.createRfcommSocketToServiceRecord()}.
- * Then call {@link #connect()} to attempt a connection to the remote device.
- * This call will block until a connection is established or the connection
- * fails.
- *
- * <p>To create a {@link BluetoothSocket} as a server (or "host"), see the
- * {@link BluetoothServerSocket} documentation.
- *
- * <p>Once the socket is connected, whether initiated as a client or accepted
- * as a server, open the IO streams by calling {@link #getInputStream} and
- * {@link #getOutputStream} in order to retrieve {@link java.io.InputStream}
- * and {@link java.io.OutputStream} objects, respectively, which are
- * automatically connected to the socket.
- *
- * <p>{@link BluetoothSocket} is thread
- * safe. In particular, {@link #close} will always immediately abort ongoing
- * operations and close the socket.
- *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about using Bluetooth, read the
- * <a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer guide.</p>
- * </div>
- *
- * {@see BluetoothServerSocket}
- * {@see java.io.InputStream}
- * {@see java.io.OutputStream}
- */
-public final class BluetoothSocket implements Closeable {
- private static final String TAG = "BluetoothSocket";
- private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
-
- /** @hide */
- public static final int MAX_RFCOMM_CHANNEL = 30;
- /*package*/ static final int MAX_L2CAP_PACKAGE_SIZE = 0xFFFF;
-
- /** RFCOMM socket */
- public static final int TYPE_RFCOMM = 1;
-
- /** SCO socket */
- public static final int TYPE_SCO = 2;
-
- /** L2CAP socket */
- public static final int TYPE_L2CAP = 3;
-
- /** L2CAP socket on BR/EDR transport
- * @hide
- */
- public static final int TYPE_L2CAP_BREDR = TYPE_L2CAP;
-
- /** L2CAP socket on LE transport
- * @hide
- */
- public static final int TYPE_L2CAP_LE = 4;
-
- /*package*/ static final int EBADFD = 77;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- /*package*/ static final int EADDRINUSE = 98;
-
- /*package*/ static final int SEC_FLAG_ENCRYPT = 1;
- /*package*/ static final int SEC_FLAG_AUTH = 1 << 1;
- /*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2;
- /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3;
- /*package*/ static final int SEC_FLAG_AUTH_16_DIGIT = 1 << 4;
-
- private final int mType; /* one of TYPE_RFCOMM etc */
- private BluetoothDevice mDevice; /* remote device */
- private String mAddress; /* remote address */
- private final boolean mAuth;
- private final boolean mEncrypt;
- private final BluetoothInputStream mInputStream;
- private final BluetoothOutputStream mOutputStream;
- private final ParcelUuid mUuid;
- /** when true no SPP SDP record will be created */
- private boolean mExcludeSdp = false;
- /** when true Person-in-the-middle protection will be enabled */
- private boolean mAuthMitm = false;
- /** Minimum 16 digit pin for sec mode 2 connections */
- private boolean mMin16DigitPin = false;
- @UnsupportedAppUsage(publicAlternatives = "Use {@link BluetoothSocket} public API instead.")
- private ParcelFileDescriptor mPfd;
- @UnsupportedAppUsage
- private LocalSocket mSocket;
- private InputStream mSocketIS;
- private OutputStream mSocketOS;
- @UnsupportedAppUsage
- private int mPort; /* RFCOMM channel or L2CAP psm */
- private int mFd;
- private String mServiceName;
- private static final int PROXY_CONNECTION_TIMEOUT = 5000;
-
- private static final int SOCK_SIGNAL_SIZE = 20;
-
- private ByteBuffer mL2capBuffer = null;
- private int mMaxTxPacketSize = 0; // The l2cap maximum packet size supported by the peer.
- private int mMaxRxPacketSize = 0; // The l2cap maximum packet size that can be received.
-
- private enum SocketState {
- INIT,
- CONNECTED,
- LISTENING,
- CLOSED,
- }
-
- /** prevents all native calls after destroyNative() */
- private volatile SocketState mSocketState;
-
- /** protects mSocketState */
- //private final ReentrantReadWriteLock mLock;
-
- /**
- * Construct a BluetoothSocket.
- *
- * @param type type of socket
- * @param fd fd to use for connected socket, or -1 for a new socket
- * @param auth require the remote device to be authenticated
- * @param encrypt require the connection to be encrypted
- * @param device remote device that this socket can connect to
- * @param port remote port
- * @param uuid SDP uuid
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * privileges
- */
- /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
- BluetoothDevice device, int port, ParcelUuid uuid) throws IOException {
- this(type, fd, auth, encrypt, device, port, uuid, false, false);
- }
-
- /**
- * Construct a BluetoothSocket.
- *
- * @param type type of socket
- * @param fd fd to use for connected socket, or -1 for a new socket
- * @param auth require the remote device to be authenticated
- * @param encrypt require the connection to be encrypted
- * @param device remote device that this socket can connect to
- * @param port remote port
- * @param uuid SDP uuid
- * @param mitm enforce person-in-the-middle protection.
- * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * privileges
- */
- /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
- BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm, boolean min16DigitPin)
- throws IOException {
- if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type);
- if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1
- && port != BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
- if (port < 1 || port > MAX_RFCOMM_CHANNEL) {
- throw new IOException("Invalid RFCOMM channel: " + port);
- }
- }
- if (uuid != null) {
- mUuid = uuid;
- } else {
- mUuid = new ParcelUuid(new UUID(0, 0));
- }
- mType = type;
- mAuth = auth;
- mAuthMitm = mitm;
- mMin16DigitPin = min16DigitPin;
- mEncrypt = encrypt;
- mDevice = device;
- mPort = port;
- mFd = fd;
-
- mSocketState = SocketState.INIT;
-
- if (device == null) {
- // Server socket
- mAddress = BluetoothAdapter.getDefaultAdapter().getAddress();
- } else {
- // Remote socket
- mAddress = device.getAddress();
- }
- mInputStream = new BluetoothInputStream(this);
- mOutputStream = new BluetoothOutputStream(this);
- }
-
- private BluetoothSocket(BluetoothSocket s) {
- if (VDBG) Log.d(TAG, "Creating new Private BluetoothSocket of type: " + s.mType);
- mUuid = s.mUuid;
- mType = s.mType;
- mAuth = s.mAuth;
- mEncrypt = s.mEncrypt;
- mPort = s.mPort;
- mInputStream = new BluetoothInputStream(this);
- mOutputStream = new BluetoothOutputStream(this);
- mMaxRxPacketSize = s.mMaxRxPacketSize;
- mMaxTxPacketSize = s.mMaxTxPacketSize;
-
- mServiceName = s.mServiceName;
- mExcludeSdp = s.mExcludeSdp;
- mAuthMitm = s.mAuthMitm;
- mMin16DigitPin = s.mMin16DigitPin;
- }
-
- private BluetoothSocket acceptSocket(String remoteAddr) throws IOException {
- BluetoothSocket as = new BluetoothSocket(this);
- as.mSocketState = SocketState.CONNECTED;
- FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors();
- if (DBG) Log.d(TAG, "socket fd passed by stack fds: " + Arrays.toString(fds));
- if (fds == null || fds.length != 1) {
- Log.e(TAG, "socket fd passed from stack failed, fds: " + Arrays.toString(fds));
- as.close();
- throw new IOException("bt socket acept failed");
- }
-
- as.mPfd = ParcelFileDescriptor.dup(fds[0]);
- as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]);
- as.mSocketIS = as.mSocket.getInputStream();
- as.mSocketOS = as.mSocket.getOutputStream();
- as.mAddress = remoteAddr;
- as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(remoteAddr);
- return as;
- }
-
- /**
- * Construct a BluetoothSocket from address. Used by native code.
- *
- * @param type type of socket
- * @param fd fd to use for connected socket, or -1 for a new socket
- * @param auth require the remote device to be authenticated
- * @param encrypt require the connection to be encrypted
- * @param address remote device that this socket can connect to
- * @param port remote port
- * @throws IOException On error, for example Bluetooth not available, or insufficient
- * privileges
- */
- private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address,
- int port) throws IOException {
- this(type, fd, auth, encrypt, new BluetoothDevice(address), port, null, false, false);
- }
-
- /** @hide */
- @Override
- protected void finalize() throws Throwable {
- try {
- close();
- } finally {
- super.finalize();
- }
- }
-
- private int getSecurityFlags() {
- int flags = 0;
- if (mAuth) {
- flags |= SEC_FLAG_AUTH;
- }
- if (mEncrypt) {
- flags |= SEC_FLAG_ENCRYPT;
- }
- if (mExcludeSdp) {
- flags |= BTSOCK_FLAG_NO_SDP;
- }
- if (mAuthMitm) {
- flags |= SEC_FLAG_AUTH_MITM;
- }
- if (mMin16DigitPin) {
- flags |= SEC_FLAG_AUTH_16_DIGIT;
- }
- return flags;
- }
-
- /**
- * Get the remote device this socket is connecting, or connected, to.
- *
- * @return remote device
- */
- @RequiresNoPermission
- public BluetoothDevice getRemoteDevice() {
- return mDevice;
- }
-
- /**
- * Get the input stream associated with this socket.
- * <p>The input stream will be returned even if the socket is not yet
- * connected, but operations on that stream will throw IOException until
- * the associated socket is connected.
- *
- * @return InputStream
- */
- @RequiresNoPermission
- public InputStream getInputStream() throws IOException {
- return mInputStream;
- }
-
- /**
- * Get the output stream associated with this socket.
- * <p>The output stream will be returned even if the socket is not yet
- * connected, but operations on that stream will throw IOException until
- * the associated socket is connected.
- *
- * @return OutputStream
- */
- @RequiresNoPermission
- public OutputStream getOutputStream() throws IOException {
- return mOutputStream;
- }
-
- /**
- * Get the connection status of this socket, ie, whether there is an active connection with
- * remote device.
- *
- * @return true if connected false if not connected
- */
- @RequiresNoPermission
- public boolean isConnected() {
- return mSocketState == SocketState.CONNECTED;
- }
-
- /*package*/ void setServiceName(String name) {
- mServiceName = name;
- }
-
- /**
- * Attempt to connect to a remote device.
- * <p>This method will block until a connection is made or the connection
- * fails. If this method returns without an exception then this socket
- * is now connected.
- * <p>Creating new connections to
- * remote Bluetooth devices should not be attempted while device discovery
- * is in progress. Device discovery is a heavyweight procedure on the
- * Bluetooth adapter and will significantly slow a device connection.
- * Use {@link BluetoothAdapter#cancelDiscovery()} to cancel an ongoing
- * discovery. Discovery is not managed by the Activity,
- * but is run as a system service, so an application should always call
- * {@link BluetoothAdapter#cancelDiscovery()} even if it
- * did not directly request a discovery, just to be sure.
- * <p>{@link #close} can be used to abort this call from another thread.
- *
- * @throws IOException on error, for example connection failure
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void connect() throws IOException {
- if (mDevice == null) throw new IOException("Connect is called on null device");
-
- try {
- if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
- IBluetooth bluetoothProxy =
- BluetoothAdapter.getDefaultAdapter().getBluetoothService();
- if (bluetoothProxy == null) throw new IOException("Bluetooth is off");
- mPfd = bluetoothProxy.getSocketManager().connectSocket(mDevice, mType,
- mUuid, mPort, getSecurityFlags());
- synchronized (this) {
- if (DBG) Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd);
- if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
- if (mPfd == null) throw new IOException("bt socket connect failed");
- FileDescriptor fd = mPfd.getFileDescriptor();
- mSocket = LocalSocket.createConnectedLocalSocket(fd);
- mSocketIS = mSocket.getInputStream();
- mSocketOS = mSocket.getOutputStream();
- }
- int channel = readInt(mSocketIS);
- if (channel <= 0) {
- throw new IOException("bt socket connect failed");
- }
- mPort = channel;
- waitSocketSignal(mSocketIS);
- synchronized (this) {
- if (mSocketState == SocketState.CLOSED) {
- throw new IOException("bt socket closed");
- }
- mSocketState = SocketState.CONNECTED;
- }
- } catch (RemoteException e) {
- Log.e(TAG, Log.getStackTraceString(new Throwable()));
- throw new IOException("unable to send RPC: " + e.getMessage());
- }
- }
-
- /**
- * Currently returns unix errno instead of throwing IOException,
- * so that BluetoothAdapter can check the error code for EADDRINUSE
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- /*package*/ int bindListen() {
- int ret;
- if (mSocketState == SocketState.CLOSED) return EBADFD;
- IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService();
- if (bluetoothProxy == null) {
- Log.e(TAG, "bindListen fail, reason: bluetooth is off");
- return -1;
- }
- try {
- if (DBG) Log.d(TAG, "bindListen(): mPort=" + mPort + ", mType=" + mType);
- mPfd = bluetoothProxy.getSocketManager().createSocketChannel(mType, mServiceName,
- mUuid, mPort, getSecurityFlags());
- } catch (RemoteException e) {
- Log.e(TAG, Log.getStackTraceString(new Throwable()));
- return -1;
- }
-
- // read out port number
- try {
- synchronized (this) {
- if (DBG) {
- Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + mPfd);
- }
- if (mSocketState != SocketState.INIT) return EBADFD;
- if (mPfd == null) return -1;
- FileDescriptor fd = mPfd.getFileDescriptor();
- if (fd == null) {
- Log.e(TAG, "bindListen(), null file descriptor");
- return -1;
- }
-
- if (DBG) Log.d(TAG, "bindListen(), Create LocalSocket");
- mSocket = LocalSocket.createConnectedLocalSocket(fd);
- if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()");
- mSocketIS = mSocket.getInputStream();
- mSocketOS = mSocket.getOutputStream();
- }
- if (DBG) Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS);
- int channel = readInt(mSocketIS);
- synchronized (this) {
- if (mSocketState == SocketState.INIT) {
- mSocketState = SocketState.LISTENING;
- }
- }
- if (DBG) Log.d(TAG, "bindListen(): channel=" + channel + ", mPort=" + mPort);
- if (mPort <= -1) {
- mPort = channel;
- } // else ASSERT(mPort == channel)
- ret = 0;
- } catch (IOException e) {
- if (mPfd != null) {
- try {
- mPfd.close();
- } catch (IOException e1) {
- Log.e(TAG, "bindListen, close mPfd: " + e1);
- }
- mPfd = null;
- }
- Log.e(TAG, "bindListen, fail to get port number, exception: " + e);
- return -1;
- }
- return ret;
- }
-
- /*package*/ BluetoothSocket accept(int timeout) throws IOException {
- BluetoothSocket acceptedSocket;
- if (mSocketState != SocketState.LISTENING) {
- throw new IOException("bt socket is not in listen state");
- }
- if (timeout > 0) {
- Log.d(TAG, "accept() set timeout (ms):" + timeout);
- mSocket.setSoTimeout(timeout);
- }
- String RemoteAddr = waitSocketSignal(mSocketIS);
- if (timeout > 0) {
- mSocket.setSoTimeout(0);
- }
- synchronized (this) {
- if (mSocketState != SocketState.LISTENING) {
- throw new IOException("bt socket is not in listen state");
- }
- acceptedSocket = acceptSocket(RemoteAddr);
- //quick drop the reference of the file handle
- }
- return acceptedSocket;
- }
-
- /*package*/ int available() throws IOException {
- if (VDBG) Log.d(TAG, "available: " + mSocketIS);
- return mSocketIS.available();
- }
-
- /*package*/ int read(byte[] b, int offset, int length) throws IOException {
- int ret = 0;
- if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length);
- if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
- int bytesToRead = length;
- if (VDBG) {
- Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length
- + "mL2capBuffer= " + mL2capBuffer);
- }
- if (mL2capBuffer == null) {
- createL2capRxBuffer();
- }
- if (mL2capBuffer.remaining() == 0) {
- if (VDBG) Log.v(TAG, "l2cap buffer empty, refilling...");
- if (fillL2capRxBuffer() == -1) {
- return -1;
- }
- }
- if (bytesToRead > mL2capBuffer.remaining()) {
- bytesToRead = mL2capBuffer.remaining();
- }
- if (VDBG) {
- Log.v(TAG, "get(): offset: " + offset
- + " bytesToRead: " + bytesToRead);
- }
- mL2capBuffer.get(b, offset, bytesToRead);
- ret = bytesToRead;
- } else {
- if (VDBG) Log.v(TAG, "default: read(): offset: " + offset + " length:" + length);
- ret = mSocketIS.read(b, offset, length);
- }
- if (ret < 0) {
- throw new IOException("bt socket closed, read return: " + ret);
- }
- if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret);
- return ret;
- }
-
- /*package*/ int write(byte[] b, int offset, int length) throws IOException {
-
- //TODO: Since bindings can exist between the SDU size and the
- // protocol, we might need to throw an exception instead of just
- // splitting the write into multiple smaller writes.
- // Rfcomm uses dynamic allocation, and should not have any bindings
- // to the actual message length.
- if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length);
- if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
- if (length <= mMaxTxPacketSize) {
- mSocketOS.write(b, offset, length);
- } else {
- if (DBG) {
- Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n"
- + "Packet will be divided into SDU packets of size "
- + mMaxTxPacketSize);
- }
- int tmpOffset = offset;
- int bytesToWrite = length;
- while (bytesToWrite > 0) {
- int tmpLength = (bytesToWrite > mMaxTxPacketSize)
- ? mMaxTxPacketSize
- : bytesToWrite;
- mSocketOS.write(b, tmpOffset, tmpLength);
- tmpOffset += tmpLength;
- bytesToWrite -= tmpLength;
- }
- }
- } else {
- mSocketOS.write(b, offset, length);
- }
- // There is no good way to confirm since the entire process is asynchronous anyway
- if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length);
- return length;
- }
-
- @Override
- public void close() throws IOException {
- Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS
- + ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket + ", mSocketState: "
- + mSocketState);
- if (mSocketState == SocketState.CLOSED) {
- return;
- } else {
- synchronized (this) {
- if (mSocketState == SocketState.CLOSED) {
- return;
- }
- mSocketState = SocketState.CLOSED;
- if (mSocket != null) {
- if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket);
- mSocket.shutdownInput();
- mSocket.shutdownOutput();
- mSocket.close();
- mSocket = null;
- }
- if (mPfd != null) {
- mPfd.close();
- mPfd = null;
- }
- }
- }
- }
-
- /*package */ void removeChannel() {
- }
-
- /*package */ int getPort() {
- return mPort;
- }
-
- /**
- * Get the maximum supported Transmit packet size for the underlying transport.
- * Use this to optimize the writes done to the output socket, to avoid sending
- * half full packets.
- *
- * @return the maximum supported Transmit packet size for the underlying transport.
- */
- @RequiresNoPermission
- public int getMaxTransmitPacketSize() {
- return mMaxTxPacketSize;
- }
-
- /**
- * Get the maximum supported Receive packet size for the underlying transport.
- * Use this to optimize the reads done on the input stream, as any call to read
- * will return a maximum of this amount of bytes - or for some transports a
- * multiple of this value.
- *
- * @return the maximum supported Receive packet size for the underlying transport.
- */
- @RequiresNoPermission
- public int getMaxReceivePacketSize() {
- return mMaxRxPacketSize;
- }
-
- /**
- * Get the type of the underlying connection.
- *
- * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP}
- */
- @RequiresNoPermission
- public int getConnectionType() {
- if (mType == TYPE_L2CAP_LE) {
- // Treat the LE CoC to be the same type as L2CAP.
- return TYPE_L2CAP;
- }
- return mType;
- }
-
- /**
- * Change if a SDP entry should be automatically created.
- * Must be called before calling .bind, for the call to have any effect.
- *
- * @param excludeSdp <li>TRUE - do not auto generate SDP record. <li>FALSE - default - auto
- * generate SPP SDP record.
- * @hide
- */
- @RequiresNoPermission
- public void setExcludeSdp(boolean excludeSdp) {
- mExcludeSdp = excludeSdp;
- }
-
- /**
- * Set the LE Transmit Data Length to be the maximum that the BT Controller is capable of. This
- * parameter is used by the BT Controller to set the maximum transmission packet size on this
- * connection. This function is currently used for testing only.
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void requestMaximumTxDataLength() throws IOException {
- if (mDevice == null) {
- throw new IOException("requestMaximumTxDataLength is called on null device");
- }
-
- try {
- if (mSocketState == SocketState.CLOSED) {
- throw new IOException("socket closed");
- }
- IBluetooth bluetoothProxy =
- BluetoothAdapter.getDefaultAdapter().getBluetoothService();
- if (bluetoothProxy == null) {
- throw new IOException("Bluetooth is off");
- }
-
- if (DBG) Log.d(TAG, "requestMaximumTxDataLength");
- bluetoothProxy.getSocketManager().requestMaximumTxDataLength(mDevice);
- } catch (RemoteException e) {
- Log.e(TAG, Log.getStackTraceString(new Throwable()));
- throw new IOException("unable to send RPC: " + e.getMessage());
- }
- }
-
- private String convertAddr(final byte[] addr) {
- return String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
- addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
- }
-
- private String waitSocketSignal(InputStream is) throws IOException {
- byte[] sig = new byte[SOCK_SIGNAL_SIZE];
- int ret = readAll(is, sig);
- if (VDBG) {
- Log.d(TAG, "waitSocketSignal read " + SOCK_SIGNAL_SIZE + " bytes signal ret: " + ret);
- }
- ByteBuffer bb = ByteBuffer.wrap(sig);
- /* the struct in native is decorated with __attribute__((packed)), hence this is possible */
- bb.order(ByteOrder.nativeOrder());
- int size = bb.getShort();
- if (size != SOCK_SIGNAL_SIZE) {
- throw new IOException("Connection failure, wrong signal size: " + size);
- }
- byte[] addr = new byte[6];
- bb.get(addr);
- int channel = bb.getInt();
- int status = bb.getInt();
- mMaxTxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value
- mMaxRxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value
- String RemoteAddr = convertAddr(addr);
- if (VDBG) {
- Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: "
- + RemoteAddr + ", channel: " + channel + ", status: " + status
- + " MaxRxPktSize: " + mMaxRxPacketSize + " MaxTxPktSize: " + mMaxTxPacketSize);
- }
- if (status != 0) {
- throw new IOException("Connection failure, status: " + status);
- }
- return RemoteAddr;
- }
-
- private void createL2capRxBuffer() {
- if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
- // Allocate the buffer to use for reads.
- if (VDBG) Log.v(TAG, " Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize);
- mL2capBuffer = ByteBuffer.wrap(new byte[mMaxRxPacketSize]);
- if (VDBG) Log.v(TAG, "mL2capBuffer.remaining()" + mL2capBuffer.remaining());
- mL2capBuffer.limit(0); // Ensure we do a real read at the first read-request
- if (VDBG) {
- Log.v(TAG, "mL2capBuffer.remaining() after limit(0):" + mL2capBuffer.remaining());
- }
- }
- }
-
- private int readAll(InputStream is, byte[] b) throws IOException {
- int left = b.length;
- while (left > 0) {
- int ret = is.read(b, b.length - left, left);
- if (ret <= 0) {
- throw new IOException("read failed, socket might closed or timeout, read ret: "
- + ret);
- }
- left -= ret;
- if (left != 0) {
- Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left)
- + ", expect size: " + b.length);
- }
- }
- return b.length;
- }
-
- private int readInt(InputStream is) throws IOException {
- byte[] ibytes = new byte[4];
- int ret = readAll(is, ibytes);
- if (VDBG) Log.d(TAG, "inputStream.read ret: " + ret);
- ByteBuffer bb = ByteBuffer.wrap(ibytes);
- bb.order(ByteOrder.nativeOrder());
- return bb.getInt();
- }
-
- private int fillL2capRxBuffer() throws IOException {
- mL2capBuffer.rewind();
- int ret = mSocketIS.read(mL2capBuffer.array());
- if (ret == -1) {
- // reached end of stream - return -1
- mL2capBuffer.limit(0);
- return -1;
- }
- mL2capBuffer.limit(ret);
- return ret;
- }
-
-
-}
diff --git a/core/java/android/bluetooth/BluetoothStatusCodes.java b/core/java/android/bluetooth/BluetoothStatusCodes.java
deleted file mode 100644
index 9dafa07..0000000
--- a/core/java/android/bluetooth/BluetoothStatusCodes.java
+++ /dev/null
@@ -1,292 +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.bluetooth;
-
-import android.annotation.SystemApi;
-
-/**
- * A class with constants representing possible return values for Bluetooth APIs. General return
- * values occupy the range 0 to 99. Profile-specific return values occupy the range 100-999.
- * API-specific return values start at 1000. The exception to this is the "UNKNOWN" error code which
- * occupies the max integer value.
- */
-public final class BluetoothStatusCodes {
-
- private BluetoothStatusCodes() {}
-
- /**
- * Indicates that the API call was successful
- */
- public static final int SUCCESS = 0;
-
- /**
- * Error code indicating that Bluetooth is not enabled
- */
- public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1;
-
- /**
- * Error code indicating that the API call was initiated by neither the system nor the active
- * Zuser
- */
- public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2;
-
- /**
- * Error code indicating that the Bluetooth Device specified is not bonded
- */
- public static final int ERROR_DEVICE_NOT_BONDED = 3;
-
- /**
- * Error code indicating that the Bluetooth Device specified is not connected, but is bonded
- *
- * @hide
- */
- public static final int ERROR_DEVICE_NOT_CONNECTED = 4;
-
- /**
- * Error code indicating that the caller does not have the
- * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission
- *
- * @hide
- */
- public static final int ERROR_MISSING_BLUETOOTH_ADVERTISE_PERMISSION = 5;
-
- /**
- * Error code indicating that the caller does not have the
- * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission
- */
- public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6;
-
- /**
- * Error code indicating that the caller does not have the
- * {@link android.Manifest.permission#BLUETOOTH_SCAN} permission
- *
- * @hide
- */
- public static final int ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION = 7;
-
- /**
- * Error code indicating that the caller does not have the
- * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission
- */
- public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8;
-
- /**
- * Error code indicating that the profile service is not bound. You can bind a profile service
- * by calling {@link BluetoothAdapter#getProfileProxy}
- */
- public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9;
-
- /**
- * Error code indicating that the feature is not supported.
- */
- public static final int ERROR_FEATURE_NOT_SUPPORTED = 10;
-
- /**
- * A GATT writeCharacteristic request is not permitted on the remote device.
- */
- public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101;
-
- /**
- * A GATT writeCharacteristic request is issued to a busy remote device.
- */
- public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102;
-
- /**
- * If another application has already requested {@link OobData} then another fetch will be
- * disallowed until the callback is removed.
- *
- * @hide
- */
- @SystemApi
- public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000;
-
- /**
- * Indicates that the ACL disconnected due to an explicit request from the local device.
- * <p>
- * Example cause: This is a normal disconnect reason, e.g., user/app initiates
- * disconnection.
- *
- * @hide
- */
- public static final int ERROR_DISCONNECT_REASON_LOCAL_REQUEST = 1100;
-
- /**
- * Indicates that the ACL disconnected due to an explicit request from the remote device.
- * <p>
- * Example cause: This is a normal disconnect reason, e.g., user/app initiates
- * disconnection.
- * <p>
- * Example solution: The app can also prompt the user to check their remote device.
- *
- * @hide
- */
- public static final int ERROR_DISCONNECT_REASON_REMOTE_REQUEST = 1101;
-
- /**
- * Generic disconnect reason indicating the ACL disconnected due to an error on the local
- * device.
- * <p>
- * Example solution: Prompt the user to check their local device (e.g., phone, car
- * headunit).
- *
- * @hide
- */
- public static final int ERROR_DISCONNECT_REASON_LOCAL = 1102;
-
- /**
- * Generic disconnect reason indicating the ACL disconnected due to an error on the remote
- * device.
- * <p>
- * Example solution: Prompt the user to check their remote device (e.g., headset, car
- * headunit, watch).
- *
- * @hide
- */
- public static final int ERROR_DISCONNECT_REASON_REMOTE = 1103;
-
- /**
- * Indicates that the ACL disconnected due to a timeout.
- * <p>
- * Example cause: remote device might be out of range.
- * <p>
- * Example solution: Prompt user to verify their remote device is on or in
- * connection/pairing mode.
- *
- * @hide
- */
- public static final int ERROR_DISCONNECT_REASON_TIMEOUT = 1104;
-
- /**
- * Indicates that the ACL disconnected due to link key issues.
- * <p>
- * Example cause: Devices are either unpaired or remote device is refusing our pairing
- * request.
- * <p>
- * Example solution: Prompt user to unpair and pair again.
- *
- * @hide
- */
- public static final int ERROR_DISCONNECT_REASON_SECURITY = 1105;
-
- /**
- * Indicates that the ACL disconnected due to the local device's system policy.
- * <p>
- * Example cause: privacy policy, power management policy, permissions, etc.
- * <p>
- * Example solution: Prompt the user to check settings, or check with their system
- * administrator (e.g. some corp-managed devices do not allow OPP connection).
- *
- * @hide
- */
- public static final int ERROR_DISCONNECT_REASON_SYSTEM_POLICY = 1106;
-
- /**
- * Indicates that the ACL disconnected due to resource constraints, either on the local
- * device or the remote device.
- * <p>
- * Example cause: controller is busy, memory limit reached, maximum number of connections
- * reached.
- * <p>
- * Example solution: The app should wait and try again. If still failing, prompt the user
- * to disconnect some devices, or toggle Bluetooth on the local and/or the remote device.
- *
- * @hide
- */
- public static final int ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED = 1107;
-
- /**
- * Indicates that the ACL disconnected because another ACL connection already exists.
- *
- * @hide
- */
- public static final int ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS = 1108;
-
- /**
- * Indicates that the ACL disconnected due to incorrect parameters passed in from the app.
- * <p>
- * Example solution: Change parameters and try again. If error persists, the app can report
- * telemetry and/or log the error in a bugreport.
- *
- * @hide
- */
- public static final int ERROR_DISCONNECT_REASON_BAD_PARAMETERS = 1109;
-
- /**
- * Indicates that setting the LE Audio Broadcast mode failed.
- * <p>
- * Example solution: Change parameters and try again. If error persists, the app can report
- * telemetry and/or log the error in a bugreport.
- *
- * @hide
- */
- public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED = 1110;
-
- /**
- * Indicates that setting a new encryption key for Bluetooth LE Audio Broadcast Source failed.
- * <p>
- * Example solution: Change parameters and try again. If error persists, the app can report
- * telemetry and/or log the error in a bugreport.
- *
- * @hide
- */
- public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_ENCRYPTION_KEY_FAILED = 1111;
-
- /**
- * Indicates that connecting to a remote Broadcast Audio Scan Service failed.
- * <p>
- * Example solution: Change parameters and try again. If error persists, the app can report
- * telemetry and/or log the error in a bugreport.
- *
- * @hide
- */
- public static final int ERROR_LE_AUDIO_BROADCAST_AUDIO_SCAN_SERVICE_CONNECT_FAILED = 1112;
-
- /**
- * Indicates that disconnecting from a remote Broadcast Audio Scan Service failed.
- * <p>
- * Example solution: Change parameters and try again. If error persists, the app can report
- * telemetry and/or log the error in a bugreport.
- *
- * @hide
- */
- public static final int ERROR_LE_AUDIO_BROADCAST_AUDIO_SCAN_SERVICE_DISCONNECT_FAILED = 1113;
-
- /**
- * Indicates that enabling LE Audio Broadcast encryption failed
- * <p>
- * Example solution: Change parameters and try again. If error persists, the app can report
- * telemetry and/or log the error in a bugreport.
- *
- * @hide
- */
- public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_ENABLE_ENCRYPTION_FAILED = 1114;
-
- /**
- * Indicates that disabling LE Audio Broadcast encryption failed
- * <p>
- * Example solution: Change parameters and try again. If error persists, the app can report
- * telemetry and/or log the error in a bugreport.
- *
- * @hide
- */
- public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED = 1115;
-
- /**
- * Indicates that an unknown error has occurred has occurred.
- */
- public static final int ERROR_UNKNOWN = Integer.MAX_VALUE;
-}
diff --git a/core/java/android/bluetooth/BluetoothUtils.java b/core/java/android/bluetooth/BluetoothUtils.java
deleted file mode 100644
index 8674692..0000000
--- a/core/java/android/bluetooth/BluetoothUtils.java
+++ /dev/null
@@ -1,41 +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.bluetooth;
-
-import java.time.Duration;
-
-/**
- * {@hide}
- */
-public final class BluetoothUtils {
- /**
- * This utility class cannot be instantiated
- */
- private BluetoothUtils() {}
-
- /**
- * Timeout value for synchronous binder call
- */
- private static final Duration SYNC_CALLS_TIMEOUT = Duration.ofSeconds(5);
-
- /**
- * @return timeout value for synchronous binder call
- */
- static Duration getSyncTimeout() {
- return SYNC_CALLS_TIMEOUT;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
deleted file mode 100644
index 2a8ff51..0000000
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (C) 2009 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.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.ParcelUuid;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.UUID;
-
-/**
- * Static helper methods and constants to decode the ParcelUuid of remote devices.
- *
- * @hide
- */
-@SystemApi
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-public final class BluetoothUuid {
-
- /* See Bluetooth Assigned Numbers document - SDP section, to get the values of UUIDs
- * for the various services.
- *
- * The following 128 bit values are calculated as:
- * uuid * 2^96 + BASE_UUID
- */
-
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid A2DP_SINK =
- ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid A2DP_SOURCE =
- ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid ADV_AUDIO_DIST =
- ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid HSP =
- ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid HSP_AG =
- ParcelUuid.fromString("00001112-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid HFP =
- ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid HFP_AG =
- ParcelUuid.fromString("0000111F-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid AVRCP_CONTROLLER =
- ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid AVRCP_TARGET =
- ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid OBEX_OBJECT_PUSH =
- ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid HID =
- ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid HOGP =
- ParcelUuid.fromString("00001812-0000-1000-8000-00805f9b34fb");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid PANU =
- ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid NAP =
- ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid BNEP =
- ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid PBAP_PCE =
- ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid PBAP_PSE =
- ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid MAP =
- ParcelUuid.fromString("00001134-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid MNS =
- ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid MAS =
- ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid SAP =
- ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid HEARING_AID =
- ParcelUuid.fromString("0000FDF0-0000-1000-8000-00805f9b34fb");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid LE_AUDIO =
- ParcelUuid.fromString("0000184E-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid DIP =
- ParcelUuid.fromString("00001200-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid VOLUME_CONTROL =
- ParcelUuid.fromString("00001844-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid GENERIC_MEDIA_CONTROL =
- ParcelUuid.fromString("00001849-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid MEDIA_CONTROL =
- ParcelUuid.fromString("00001848-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid COORDINATED_SET =
- ParcelUuid.fromString("00001846-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid CAP =
- ParcelUuid.fromString("00001853-0000-1000-8000-00805F9B34FB");
- /** @hide */
- @NonNull
- @SystemApi
- public static final ParcelUuid BASE_UUID =
- ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
-
- /**
- * Length of bytes for 16 bit UUID
- *
- * @hide
- */
- @SystemApi
- public static final int UUID_BYTES_16_BIT = 2;
- /**
- * Length of bytes for 32 bit UUID
- *
- * @hide
- */
- @SystemApi
- public static final int UUID_BYTES_32_BIT = 4;
- /**
- * Length of bytes for 128 bit UUID
- *
- * @hide
- */
- @SystemApi
- public static final int UUID_BYTES_128_BIT = 16;
-
- /**
- * Returns true if there any common ParcelUuids in uuidA and uuidB.
- *
- * @param uuidA - List of ParcelUuids
- * @param uuidB - List of ParcelUuids
- *
- * @hide
- */
- @SystemApi
- public static boolean containsAnyUuid(@Nullable ParcelUuid[] uuidA,
- @Nullable ParcelUuid[] uuidB) {
- if (uuidA == null && uuidB == null) return true;
-
- if (uuidA == null) {
- return uuidB.length == 0;
- }
-
- if (uuidB == null) {
- return uuidA.length == 0;
- }
-
- HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid>(Arrays.asList(uuidA));
- for (ParcelUuid uuid : uuidB) {
- if (uuidSet.contains(uuid)) return true;
- }
- return false;
- }
-
- /**
- * Extract the Service Identifier or the actual uuid from the Parcel Uuid.
- * For example, if 0000110B-0000-1000-8000-00805F9B34FB is the parcel Uuid,
- * this function will return 110B
- *
- * @param parcelUuid
- * @return the service identifier.
- */
- private static int getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid) {
- UUID uuid = parcelUuid.getUuid();
- long value = (uuid.getMostSignificantBits() & 0xFFFFFFFF00000000L) >>> 32;
- return (int) value;
- }
-
- /**
- * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID,
- * but the returned UUID is always in 128-bit format.
- * Note UUID is little endian in Bluetooth.
- *
- * @param uuidBytes Byte representation of uuid.
- * @return {@link ParcelUuid} parsed from bytes.
- * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public static ParcelUuid parseUuidFrom(@Nullable byte[] uuidBytes) {
- if (uuidBytes == null) {
- throw new IllegalArgumentException("uuidBytes cannot be null");
- }
- int length = uuidBytes.length;
- if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT
- && length != UUID_BYTES_128_BIT) {
- throw new IllegalArgumentException("uuidBytes length invalid - " + length);
- }
-
- // Construct a 128 bit UUID.
- if (length == UUID_BYTES_128_BIT) {
- ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN);
- long msb = buf.getLong(8);
- long lsb = buf.getLong(0);
- return new ParcelUuid(new UUID(msb, lsb));
- }
-
- // For 16 bit and 32 bit UUID we need to convert them to 128 bit value.
- // 128_bit_value = uuid * 2^96 + BASE_UUID
- long shortUuid;
- if (length == UUID_BYTES_16_BIT) {
- shortUuid = uuidBytes[0] & 0xFF;
- shortUuid += (uuidBytes[1] & 0xFF) << 8;
- } else {
- shortUuid = uuidBytes[0] & 0xFF;
- shortUuid += (uuidBytes[1] & 0xFF) << 8;
- shortUuid += (uuidBytes[2] & 0xFF) << 16;
- shortUuid += (uuidBytes[3] & 0xFF) << 24;
- }
- long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32);
- long lsb = BASE_UUID.getUuid().getLeastSignificantBits();
- return new ParcelUuid(new UUID(msb, lsb));
- }
-
- /**
- * Parse UUID to bytes. The returned value is shortest representation, a 16-bit, 32-bit or
- * 128-bit UUID, Note returned value is little endian (Bluetooth).
- *
- * @param uuid uuid to parse.
- * @return shortest representation of {@code uuid} as bytes.
- * @throws IllegalArgumentException If the {@code uuid} is null.
- *
- * @hide
- */
- public static byte[] uuidToBytes(ParcelUuid uuid) {
- if (uuid == null) {
- throw new IllegalArgumentException("uuid cannot be null");
- }
-
- if (is16BitUuid(uuid)) {
- byte[] uuidBytes = new byte[UUID_BYTES_16_BIT];
- int uuidVal = getServiceIdentifierFromParcelUuid(uuid);
- uuidBytes[0] = (byte) (uuidVal & 0xFF);
- uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8);
- return uuidBytes;
- }
-
- if (is32BitUuid(uuid)) {
- byte[] uuidBytes = new byte[UUID_BYTES_32_BIT];
- int uuidVal = getServiceIdentifierFromParcelUuid(uuid);
- uuidBytes[0] = (byte) (uuidVal & 0xFF);
- uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8);
- uuidBytes[2] = (byte) ((uuidVal & 0xFF0000) >> 16);
- uuidBytes[3] = (byte) ((uuidVal & 0xFF000000) >> 24);
- return uuidBytes;
- }
-
- // Construct a 128 bit UUID.
- long msb = uuid.getUuid().getMostSignificantBits();
- long lsb = uuid.getUuid().getLeastSignificantBits();
-
- byte[] uuidBytes = new byte[UUID_BYTES_128_BIT];
- ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN);
- buf.putLong(8, msb);
- buf.putLong(0, lsb);
- return uuidBytes;
- }
-
- /**
- * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid.
- *
- * @param parcelUuid
- * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise.
- *
- * @hide
- */
- @UnsupportedAppUsage
- public static boolean is16BitUuid(ParcelUuid parcelUuid) {
- UUID uuid = parcelUuid.getUuid();
- if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
- return false;
- }
- return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L);
- }
-
-
- /**
- * Check whether the given parcelUuid can be converted to 32 bit bluetooth uuid.
- *
- * @param parcelUuid
- * @return true if the parcelUuid can be converted to 32 bit uuid, false otherwise.
- *
- * @hide
- */
- @UnsupportedAppUsage
- public static boolean is32BitUuid(ParcelUuid parcelUuid) {
- UUID uuid = parcelUuid.getUuid();
- if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
- return false;
- }
- if (is16BitUuid(parcelUuid)) {
- return false;
- }
- return ((uuid.getMostSignificantBits() & 0xFFFFFFFFL) == 0x1000L);
- }
-
- private BluetoothUuid() {}
-}
diff --git a/core/java/android/bluetooth/BluetoothVolumeControl.java b/core/java/android/bluetooth/BluetoothVolumeControl.java
deleted file mode 100644
index 27532aa..0000000
--- a/core/java/android/bluetooth/BluetoothVolumeControl.java
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright 2021 HIMSA II K/S - www.himsa.com.
- * Represented by EHIMA - www.ehima.com
- *
- * 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.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the Bluetooth Volume Control service.
- *
- * <p>BluetoothVolumeControl is a proxy object for controlling the Bluetooth VC
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothVolumeControl proxy object.
- * @hide
- */
-@SystemApi
-public final class BluetoothVolumeControl implements BluetoothProfile, AutoCloseable {
- private static final String TAG = "BluetoothVolumeControl";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- private CloseGuard mCloseGuard;
-
- /**
- * Intent used to broadcast the change in connection state of the Volume Control
- * profile.
- *
- * <p>This intent will have 3 extras:
- * <ul>
- * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
- * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
- * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
- * </ul>
- *
- * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
- * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- *
- * @hide
- */
- @SystemApi
- @SuppressLint("ActionValue")
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONNECTION_STATE_CHANGED =
- "android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED";
-
- private BluetoothAdapter mAdapter;
- private final AttributionSource mAttributionSource;
- private final BluetoothProfileConnector<IBluetoothVolumeControl> mProfileConnector =
- new BluetoothProfileConnector(this, BluetoothProfile.VOLUME_CONTROL, TAG,
- IBluetoothVolumeControl.class.getName()) {
- @Override
- public IBluetoothVolumeControl getServiceInterface(IBinder service) {
- return IBluetoothVolumeControl.Stub.asInterface(service);
- }
- };
-
- /**
- * Create a BluetoothVolumeControl proxy object for interacting with the local
- * Bluetooth Volume Control service.
- */
- /*package*/ BluetoothVolumeControl(Context context, ServiceListener listener,
- BluetoothAdapter adapter) {
- mAdapter = adapter;
- mAttributionSource = adapter.getAttributionSource();
- mProfileConnector.connect(context, listener);
- mCloseGuard = new CloseGuard();
- mCloseGuard.open("close");
- }
-
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- protected void finalize() {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
- close();
- }
-
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void close() {
- mProfileConnector.disconnect();
- }
-
- private IBluetoothVolumeControl getService() { return mProfileConnector.getService(); }
-
- /**
- * Get the list of connected devices. Currently at most one.
- *
- * @return list of connected devices
- *
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @NonNull List<BluetoothDevice> getConnectedDevices() {
- if (DBG) log("getConnectedDevices()");
- final IBluetoothVolumeControl service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getConnectedDevices(mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the list of devices matching specified states. Currently at most one.
- *
- * @return list of matching devices
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (DBG) log("getDevicesMatchingStates()");
- final IBluetoothVolumeControl service = getService();
- final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<List<BluetoothDevice>> recv =
- new SynchronousResultReceiver();
- service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
- return Attributable.setAttributionSource(
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
- mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get connection state of device
- *
- * @return device connection state
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
- if (DBG) log("getConnectionState(" + device + ")");
- final IBluetoothVolumeControl service = getService();
- final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionState(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Tells remote device to set an absolute volume.
- *
- * @param volume Absolute volume to be set on remote device.
- * Minimum value is 0 and maximum value is 255
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public void setVolume(@Nullable BluetoothDevice device,
- @IntRange(from = 0, to = 255) int volume) {
- if (DBG) log("setVolume(" + volume + ")");
- final IBluetoothVolumeControl service = getService();
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.setVolume(device, volume, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- }
-
- /**
- * Set connection policy of the profile
- *
- * <p> The device should already be paired.
- * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
- * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Paired bluetooth device
- * @param connectionPolicy is the connection policy to set to for this profile
- * @return true if connectionPolicy is set, false on error
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
- @ConnectionPolicy int connectionPolicy) {
- if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
- final IBluetoothVolumeControl service = getService();
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)
- && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
- || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- /**
- * Get the connection policy of the profile.
- *
- * <p> The connection policy can be any of:
- * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
- * {@link #CONNECTION_POLICY_UNKNOWN}
- *
- * @param device Bluetooth device
- * @return connection policy of the device
- * @hide
- */
- @SystemApi
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
- if (VDBG) log("getConnectionPolicy(" + device + ")");
- final IBluetoothVolumeControl service = getService();
- final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled() && isValidDevice(device)) {
- try {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- service.getConnectionPolicy(device, mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
-
- private boolean isEnabled() {
- return mAdapter.getState() == BluetoothAdapter.STATE_ON;
- }
-
- private static boolean isValidDevice(@Nullable BluetoothDevice device) {
- return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BufferConstraint.java b/core/java/android/bluetooth/BufferConstraint.java
deleted file mode 100644
index cbffc78..0000000
--- a/core/java/android/bluetooth/BufferConstraint.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Stores a codec's constraints on buffering length in milliseconds.
- *
- * {@hide}
- */
-@SystemApi
-public final class BufferConstraint implements Parcelable {
-
- private static final String TAG = "BufferConstraint";
- private int mDefaultMillis;
- private int mMaxMillis;
- private int mMinMillis;
-
- public BufferConstraint(int defaultMillis, int maxMillis,
- int minMillis) {
- mDefaultMillis = defaultMillis;
- mMaxMillis = maxMillis;
- mMinMillis = minMillis;
- }
-
- BufferConstraint(Parcel in) {
- mDefaultMillis = in.readInt();
- mMaxMillis = in.readInt();
- mMinMillis = in.readInt();
- }
-
- public static final @NonNull Parcelable.Creator<BufferConstraint> CREATOR =
- new Parcelable.Creator<BufferConstraint>() {
- public BufferConstraint createFromParcel(Parcel in) {
- return new BufferConstraint(in);
- }
-
- public BufferConstraint[] newArray(int size) {
- return new BufferConstraint[size];
- }
- };
-
- @Override
- public void writeToParcel(@NonNull Parcel out, int flags) {
- out.writeInt(mDefaultMillis);
- out.writeInt(mMaxMillis);
- out.writeInt(mMinMillis);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- /**
- * Get the default buffer millis
- *
- * @return default buffer millis
- * @hide
- */
- @SystemApi
- public int getDefaultMillis() {
- return mDefaultMillis;
- }
-
- /**
- * Get the maximum buffer millis
- *
- * @return maximum buffer millis
- * @hide
- */
- @SystemApi
- public int getMaxMillis() {
- return mMaxMillis;
- }
-
- /**
- * Get the minimum buffer millis
- *
- * @return minimum buffer millis
- * @hide
- */
- @SystemApi
- public int getMinMillis() {
- return mMinMillis;
- }
-}
diff --git a/core/java/android/bluetooth/BufferConstraints.java b/core/java/android/bluetooth/BufferConstraints.java
deleted file mode 100644
index 97d9723..0000000
--- a/core/java/android/bluetooth/BufferConstraints.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-
-/**
- * A parcelable collection of buffer constraints by codec type.
- *
- * {@hide}
- */
-@SystemApi
-public final class BufferConstraints implements Parcelable {
- public static final int BUFFER_CODEC_MAX_NUM = 32;
-
- private static final String TAG = "BufferConstraints";
-
- private Map<Integer, BufferConstraint> mBufferConstraints;
- private List<BufferConstraint> mBufferConstraintList;
-
- public BufferConstraints(@NonNull List<BufferConstraint>
- bufferConstraintList) {
-
- mBufferConstraintList = new ArrayList<BufferConstraint>(bufferConstraintList);
- mBufferConstraints = new HashMap<Integer, BufferConstraint>();
- for (int i = 0; i < BUFFER_CODEC_MAX_NUM; i++) {
- mBufferConstraints.put(i, bufferConstraintList.get(i));
- }
- }
-
- BufferConstraints(Parcel in) {
- mBufferConstraintList = new ArrayList<BufferConstraint>();
- mBufferConstraints = new HashMap<Integer, BufferConstraint>();
- in.readList(mBufferConstraintList, BufferConstraint.class.getClassLoader());
- for (int i = 0; i < mBufferConstraintList.size(); i++) {
- mBufferConstraints.put(i, mBufferConstraintList.get(i));
- }
- }
-
- public static final @NonNull Parcelable.Creator<BufferConstraints> CREATOR =
- new Parcelable.Creator<BufferConstraints>() {
- public BufferConstraints createFromParcel(Parcel in) {
- return new BufferConstraints(in);
- }
-
- public BufferConstraints[] newArray(int size) {
- return new BufferConstraints[size];
- }
- };
-
- @Override
- public void writeToParcel(@NonNull Parcel out, int flags) {
- out.writeList(mBufferConstraintList);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- /**
- * Get the buffer constraints by codec type.
- *
- * @param codec Audio codec
- * @return buffer constraints by codec type.
- * @hide
- */
- @SystemApi
- public @Nullable BufferConstraint forCodec(@BluetoothCodecConfig.SourceCodecType int codec) {
- return mBufferConstraints.get(codec);
- }
-}
diff --git a/core/java/android/bluetooth/OWNERS b/core/java/android/bluetooth/OWNERS
deleted file mode 100644
index 8e9d7b7..0000000
--- a/core/java/android/bluetooth/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 27441
-
-sattiraju@google.com
-baligh@google.com
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
deleted file mode 100644
index bb0b956..0000000
--- a/core/java/android/bluetooth/OobData.java
+++ /dev/null
@@ -1,958 +0,0 @@
-/**
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static java.util.Objects.requireNonNull;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Out Of Band Data for Bluetooth device pairing.
- *
- * <p>This object represents optional data obtained from a remote device through
- * an out-of-band channel (eg. NFC, QR).
- *
- * <p>References:
- * NFC AD Forum SSP 1.1 (AD)
- * {@link https://members.nfc-forum.org//apps/group_public/download.php/24620/NFCForum-AD-BTSSP_1_1.pdf}
- * Core Specification Supplement (CSS) V9
- *
- * <p>There are several BR/EDR Examples
- *
- * <p>Negotiated Handover:
- * Bluetooth Carrier Configuration Record:
- * - OOB Data Length
- * - Device Address
- * - Class of Device
- * - Simple Pairing Hash C
- * - Simple Pairing Randomizer R
- * - Service Class UUID
- * - Bluetooth Local Name
- *
- * <p>Static Handover:
- * Bluetooth Carrier Configuration Record:
- * - OOB Data Length
- * - Device Address
- * - Class of Device
- * - Service Class UUID
- * - Bluetooth Local Name
- *
- * <p>Simplified Tag Format for Single BT Carrier:
- * Bluetooth OOB Data Record:
- * - OOB Data Length
- * - Device Address
- * - Class of Device
- * - Service Class UUID
- * - Bluetooth Local Name
- *
- * @hide
- */
-@SystemApi
-public final class OobData implements Parcelable {
-
- private static final String TAG = "OobData";
- /** The {@link OobData#mClassicLength} may be. (AD 3.1.1) (CSS 1.6.2) @hide */
- @SystemApi
- public static final int OOB_LENGTH_OCTETS = 2;
- /**
- * The length for the {@link OobData#mDeviceAddressWithType}(6) and Address Type(1).
- * (AD 3.1.2) (CSS 1.6.2)
- * @hide
- */
- @SystemApi
- public static final int DEVICE_ADDRESS_OCTETS = 7;
- /** The Class of Device is 3 octets. (AD 3.1.3) (CSS 1.6.2) @hide */
- @SystemApi
- public static final int CLASS_OF_DEVICE_OCTETS = 3;
- /** The Confirmation data must be 16 octets. (AD 3.2.2) (CSS 1.6.2) @hide */
- @SystemApi
- public static final int CONFIRMATION_OCTETS = 16;
- /** The Randomizer data must be 16 octets. (AD 3.2.3) (CSS 1.6.2) @hide */
- @SystemApi
- public static final int RANDOMIZER_OCTETS = 16;
- /** The LE Device Role length is 1 octet. (AD 3.3.2) (CSS 1.17) @hide */
- @SystemApi
- public static final int LE_DEVICE_ROLE_OCTETS = 1;
- /** The {@link OobData#mLeTemporaryKey} length. (3.4.1) @hide */
- @SystemApi
- public static final int LE_TK_OCTETS = 16;
- /** The {@link OobData#mLeAppearance} length. (3.4.1) @hide */
- @SystemApi
- public static final int LE_APPEARANCE_OCTETS = 2;
- /** The {@link OobData#mLeFlags} length. (3.4.1) @hide */
- @SystemApi
- public static final int LE_DEVICE_FLAG_OCTETS = 1; // 1 octet to hold the 0-4 value.
-
- // Le Roles
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- prefix = { "LE_DEVICE_ROLE_" },
- value = {
- LE_DEVICE_ROLE_PERIPHERAL_ONLY,
- LE_DEVICE_ROLE_CENTRAL_ONLY,
- LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL,
- LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL
- }
- )
- public @interface LeRole {}
-
- /** @hide */
- @SystemApi
- public static final int LE_DEVICE_ROLE_PERIPHERAL_ONLY = 0x00;
- /** @hide */
- @SystemApi
- public static final int LE_DEVICE_ROLE_CENTRAL_ONLY = 0x01;
- /** @hide */
- @SystemApi
- public static final int LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL = 0x02;
- /** @hide */
- @SystemApi
- public static final int LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL = 0x03;
-
- // Le Flags
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- prefix = { "LE_FLAG_" },
- value = {
- LE_FLAG_LIMITED_DISCOVERY_MODE,
- LE_FLAG_GENERAL_DISCOVERY_MODE,
- LE_FLAG_BREDR_NOT_SUPPORTED,
- LE_FLAG_SIMULTANEOUS_CONTROLLER,
- LE_FLAG_SIMULTANEOUS_HOST
- }
- )
- public @interface LeFlag {}
-
- /** @hide */
- @SystemApi
- public static final int LE_FLAG_LIMITED_DISCOVERY_MODE = 0x00;
- /** @hide */
- @SystemApi
- public static final int LE_FLAG_GENERAL_DISCOVERY_MODE = 0x01;
- /** @hide */
- @SystemApi
- public static final int LE_FLAG_BREDR_NOT_SUPPORTED = 0x02;
- /** @hide */
- @SystemApi
- public static final int LE_FLAG_SIMULTANEOUS_CONTROLLER = 0x03;
- /** @hide */
- @SystemApi
- public static final int LE_FLAG_SIMULTANEOUS_HOST = 0x04;
-
- /**
- * Builds an {@link OobData} object and validates that the required combination
- * of values are present to create the LE specific OobData type.
- *
- * @hide
- */
- @SystemApi
- public static final class LeBuilder {
-
- /**
- * It is recommended that this Hash C is generated anew for each
- * pairing.
- *
- * <p>It should be noted that on passive NFC this isn't possible as the data is static
- * and immutable.
- */
- private byte[] mConfirmationHash = null;
-
- /**
- * Optional, but adds more validity to the pairing.
- *
- * <p>If not present a value of 0 is assumed.
- */
- private byte[] mRandomizerHash = new byte[] {
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- };
-
- /**
- * The Bluetooth Device user-friendly name presented over Bluetooth Technology.
- *
- * <p>This is the name that may be displayed to the device user as part of the UI.
- */
- private byte[] mDeviceName = null;
-
- /**
- * Sets the Bluetooth Device name to be used for UI purposes.
- *
- * <p>Optional attribute.
- *
- * @param deviceName byte array representing the name, may be 0 in length, not null.
- *
- * @return {@link OobData#ClassicBuilder}
- *
- * @throws NullPointerException if deviceName is null.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public LeBuilder setDeviceName(@NonNull byte[] deviceName) {
- requireNonNull(deviceName);
- this.mDeviceName = deviceName;
- return this;
- }
-
- /**
- * The Bluetooth Device Address is the address to which the OOB data belongs.
- *
- * <p>The length MUST be {@link OobData#DEVICE_ADDRESS_OCTETS} octets.
- *
- * <p> Address is encoded in Little Endian order.
- *
- * <p>e.g. 00:01:02:03:04:05 would be x05x04x03x02x01x00
- */
- private final byte[] mDeviceAddressWithType;
-
- /**
- * During an LE connection establishment, one must be in the Peripheral mode and the other
- * in the Central role.
- *
- * <p>Possible Values:
- * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
- * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
- * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
- * Peripheral Preferred
- * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
- * 0x04 - 0xFF Reserved
- */
- private final @LeRole int mLeDeviceRole;
-
- /**
- * Temporary key value from the Security Manager.
- *
- * <p> Must be {@link LE_TK_OCTETS} in size
- */
- private byte[] mLeTemporaryKey = null;
-
- /**
- * Defines the representation of the external appearance of the device.
- *
- * <p>For example, a mouse, remote control, or keyboard.
- *
- * <p>Used for visual on discovering device to represent icon/string/etc...
- */
- private byte[] mLeAppearance = null;
-
- /**
- * Contains which discoverable mode to use, BR/EDR support and capability.
- *
- * <p>Possible LE Flags:
- * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
- * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
- * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
- * LMP Feature Mask Definitions.
- * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
- * Same Device Capable (Controller).
- * Bit 49 of LMP Feature Mask Definitions.
- * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
- * Same Device Capable (Host).
- * Bit 55 of LMP Feature Mask Definitions.
- * <b>0x05- 0x07 Reserved</b>
- */
- private @LeFlag int mLeFlags = LE_FLAG_GENERAL_DISCOVERY_MODE; // Invalid default
-
- /**
- * Main creation method for creating a LE version of {@link OobData}.
- *
- * <p>This object will allow the caller to call {@link LeBuilder#build()}
- * to build the data object or add any option information to the builder.
- *
- * @param deviceAddressWithType the LE device address plus the address type (7 octets);
- * not null.
- * @param leDeviceRole whether the device supports Peripheral, Central,
- * Both including preference; not null. (1 octet)
- * @param confirmationHash Array consisting of {@link OobData#CONFIRMATION_OCTETS} octets
- * of data. Data is derived from controller/host stack and is
- * required for pairing OOB.
- *
- * <p>Possible Values:
- * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
- * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
- * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
- * Peripheral Preferred
- * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
- * 0x04 - 0xFF Reserved
- *
- * @throws IllegalArgumentException if any of the values fail to be set.
- * @throws NullPointerException if any argument is null.
- *
- * @hide
- */
- @SystemApi
- public LeBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] deviceAddressWithType,
- @LeRole int leDeviceRole) {
- requireNonNull(confirmationHash);
- requireNonNull(deviceAddressWithType);
- if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
- throw new IllegalArgumentException("confirmationHash must be "
- + OobData.CONFIRMATION_OCTETS + " octets in length.");
- }
- this.mConfirmationHash = confirmationHash;
- if (deviceAddressWithType.length != OobData.DEVICE_ADDRESS_OCTETS) {
- throw new IllegalArgumentException("confirmationHash must be "
- + OobData.DEVICE_ADDRESS_OCTETS+ " octets in length.");
- }
- this.mDeviceAddressWithType = deviceAddressWithType;
- if (leDeviceRole < LE_DEVICE_ROLE_PERIPHERAL_ONLY
- || leDeviceRole > LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL) {
- throw new IllegalArgumentException("leDeviceRole must be a valid value.");
- }
- this.mLeDeviceRole = leDeviceRole;
- }
-
- /**
- * Sets the Temporary Key value to be used by the LE Security Manager during
- * LE pairing.
- *
- * @param leTemporaryKey byte array that shall be 16 bytes. Please see Bluetooth CSSv6,
- * Part A 1.8 for a detailed description.
- *
- * @return {@link OobData#Builder}
- *
- * @throws IllegalArgumentException if the leTemporaryKey is an invalid format.
- * @throws NullinterException if leTemporaryKey is null.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public LeBuilder setLeTemporaryKey(@NonNull byte[] leTemporaryKey) {
- requireNonNull(leTemporaryKey);
- if (leTemporaryKey.length != LE_TK_OCTETS) {
- throw new IllegalArgumentException("leTemporaryKey must be "
- + LE_TK_OCTETS + " octets in length.");
- }
- this.mLeTemporaryKey = leTemporaryKey;
- return this;
- }
-
- /**
- * @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets
- * of data. Data is derived from controller/host stack and is required for pairing OOB.
- * Also, randomizerHash may be all 0s or null in which case it becomes all 0s.
- *
- * @throws IllegalArgumentException if null or incorrect length randomizerHash was passed.
- * @throws NullPointerException if randomizerHash is null.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public LeBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
- requireNonNull(randomizerHash);
- if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
- throw new IllegalArgumentException("randomizerHash must be "
- + OobData.RANDOMIZER_OCTETS + " octets in length.");
- }
- this.mRandomizerHash = randomizerHash;
- return this;
- }
-
- /**
- * Sets the LE Flags necessary for the pairing scenario or discovery mode.
- *
- * @param leFlags enum value representing the 1 octet of data about discovery modes.
- *
- * <p>Possible LE Flags:
- * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
- * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
- * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
- * LMP Feature Mask Definitions.
- * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
- * Same Device Capable (Controller) Bit 49 of LMP Feature Mask Definitions.
- * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
- * Same Device Capable (Host).
- * Bit 55 of LMP Feature Mask Definitions.
- * 0x05- 0x07 Reserved
- *
- * @throws IllegalArgumentException for invalid flag
- * @hide
- */
- @NonNull
- @SystemApi
- public LeBuilder setLeFlags(@LeFlag int leFlags) {
- if (leFlags < LE_FLAG_LIMITED_DISCOVERY_MODE || leFlags > LE_FLAG_SIMULTANEOUS_HOST) {
- throw new IllegalArgumentException("leFlags must be a valid value.");
- }
- this.mLeFlags = leFlags;
- return this;
- }
-
- /**
- * Validates and builds the {@link OobData} object for LE Security.
- *
- * @return {@link OobData} with given builder values
- *
- * @throws IllegalStateException if either of the 2 required fields were not set.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public OobData build() {
- final OobData oob =
- new OobData(this.mDeviceAddressWithType, this.mLeDeviceRole,
- this.mConfirmationHash);
-
- // If we have values, set them, otherwise use default
- oob.mLeTemporaryKey =
- (this.mLeTemporaryKey != null) ? this.mLeTemporaryKey : oob.mLeTemporaryKey;
- oob.mLeAppearance = (this.mLeAppearance != null)
- ? this.mLeAppearance : oob.mLeAppearance;
- oob.mLeFlags = (this.mLeFlags != 0xF) ? this.mLeFlags : oob.mLeFlags;
- oob.mDeviceName = (this.mDeviceName != null) ? this.mDeviceName : oob.mDeviceName;
- oob.mRandomizerHash = this.mRandomizerHash;
- return oob;
- }
- }
-
- /**
- * Builds an {@link OobData} object and validates that the required combination
- * of values are present to create the Classic specific OobData type.
- *
- * @hide
- */
- @SystemApi
- public static final class ClassicBuilder {
- // Used by both Classic and LE
- /**
- * It is recommended that this Hash C is generated anew for each
- * pairing.
- *
- * <p>It should be noted that on passive NFC this isn't possible as the data is static
- * and immutable.
- *
- * @hide
- */
- private byte[] mConfirmationHash = null;
-
- /**
- * Optional, but adds more validity to the pairing.
- *
- * <p>If not present a value of 0 is assumed.
- *
- * @hide
- */
- private byte[] mRandomizerHash = new byte[] {
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- };
-
- /**
- * The Bluetooth Device user-friendly name presented over Bluetooth Technology.
- *
- * <p>This is the name that may be displayed to the device user as part of the UI.
- *
- * @hide
- */
- private byte[] mDeviceName = null;
-
- /**
- * This length value provides the absolute length of total OOB data block used for
- * Bluetooth BR/EDR
- *
- * <p>OOB communication, which includes the length field itself and the Bluetooth
- * Device Address.
- *
- * <p>The minimum length that may be represented in this field is 8.
- *
- * @hide
- */
- private final byte[] mClassicLength;
-
- /**
- * The Bluetooth Device Address is the address to which the OOB data belongs.
- *
- * <p>The length MUST be {@link OobData#DEVICE_ADDRESS_OCTETS} octets.
- *
- * <p> Address is encoded in Little Endian order.
- *
- * <p>e.g. 00:01:02:03:04:05 would be x05x04x03x02x01x00
- *
- * @hide
- */
- private final byte[] mDeviceAddressWithType;
-
- /**
- * Class of Device information is to be used to provide a graphical representation
- * to the user as part of UI involving operations.
- *
- * <p>This is not to be used to determine a particular service can be used.
- *
- * <p>The length MUST be {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
- *
- * @hide
- */
- private byte[] mClassOfDevice = null;
-
- /**
- * Main creation method for creating a Classic version of {@link OobData}.
- *
- * <p>This object will allow the caller to call {@link ClassicBuilder#build()}
- * to build the data object or add any option information to the builder.
- *
- * @param confirmationHash byte array consisting of {@link OobData#CONFIRMATION_OCTETS}
- * octets of data. Data is derived from controller/host stack and is required for pairing
- * OOB.
- * @param classicLength byte array representing the length of data from 8-65535 across 2
- * octets (0xXXXX).
- * @param deviceAddressWithType byte array representing the Bluetooth Address of the device
- * that owns the OOB data. (i.e. the originator) [6 octets]
- *
- * @throws IllegalArgumentException if any of the values fail to be set.
- * @throws NullPointerException if any argument is null.
- *
- * @hide
- */
- @SystemApi
- public ClassicBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] classicLength,
- @NonNull byte[] deviceAddressWithType) {
- requireNonNull(confirmationHash);
- requireNonNull(classicLength);
- requireNonNull(deviceAddressWithType);
- if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
- throw new IllegalArgumentException("confirmationHash must be "
- + OobData.CONFIRMATION_OCTETS + " octets in length.");
- }
- this.mConfirmationHash = confirmationHash;
- if (classicLength.length != OOB_LENGTH_OCTETS) {
- throw new IllegalArgumentException("classicLength must be "
- + OOB_LENGTH_OCTETS + " octets in length.");
- }
- this.mClassicLength = classicLength;
- if (deviceAddressWithType.length != DEVICE_ADDRESS_OCTETS) {
- throw new IllegalArgumentException("deviceAddressWithType must be "
- + DEVICE_ADDRESS_OCTETS + " octets in length.");
- }
- this.mDeviceAddressWithType = deviceAddressWithType;
- }
-
- /**
- * @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets
- * of data. Data is derived from controller/host stack and is required for pairing OOB.
- * Also, randomizerHash may be all 0s or null in which case it becomes all 0s.
- *
- * @throws IllegalArgumentException if null or incorrect length randomizerHash was passed.
- * @throws NullPointerException if randomizerHash is null.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public ClassicBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
- requireNonNull(randomizerHash);
- if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
- throw new IllegalArgumentException("randomizerHash must be "
- + OobData.RANDOMIZER_OCTETS + " octets in length.");
- }
- this.mRandomizerHash = randomizerHash;
- return this;
- }
-
- /**
- * Sets the Bluetooth Device name to be used for UI purposes.
- *
- * <p>Optional attribute.
- *
- * @param deviceName byte array representing the name, may be 0 in length, not null.
- *
- * @return {@link OobData#ClassicBuilder}
- *
- * @throws NullPointerException if deviceName is null
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public ClassicBuilder setDeviceName(@NonNull byte[] deviceName) {
- requireNonNull(deviceName);
- this.mDeviceName = deviceName;
- return this;
- }
-
- /**
- * Sets the Bluetooth Class of Device; used for UI purposes only.
- *
- * <p>Not an indicator of available services!
- *
- * <p>Optional attribute.
- *
- * @param classOfDevice byte array of {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
- *
- * @return {@link OobData#ClassicBuilder}
- *
- * @throws IllegalArgumentException if length is not equal to
- * {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
- * @throws NullPointerException if classOfDevice is null.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public ClassicBuilder setClassOfDevice(@NonNull byte[] classOfDevice) {
- requireNonNull(classOfDevice);
- if (classOfDevice.length != OobData.CLASS_OF_DEVICE_OCTETS) {
- throw new IllegalArgumentException("classOfDevice must be "
- + OobData.CLASS_OF_DEVICE_OCTETS + " octets in length.");
- }
- this.mClassOfDevice = classOfDevice;
- return this;
- }
-
- /**
- * Validates and builds the {@link OobDat object for Classic Security.
- *
- * @return {@link OobData} with previously given builder values.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public OobData build() {
- final OobData oob =
- new OobData(this.mClassicLength, this.mDeviceAddressWithType,
- this.mConfirmationHash);
- // If we have values, set them, otherwise use default
- oob.mDeviceName = (this.mDeviceName != null) ? this.mDeviceName : oob.mDeviceName;
- oob.mClassOfDevice = (this.mClassOfDevice != null)
- ? this.mClassOfDevice : oob.mClassOfDevice;
- oob.mRandomizerHash = this.mRandomizerHash;
- return oob;
- }
- }
-
- // Members (Defaults for Optionals must be set or Parceling fails on NPE)
- // Both
- private final byte[] mDeviceAddressWithType;
- private final byte[] mConfirmationHash;
- private byte[] mRandomizerHash = new byte[] {
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
- };
- // Default the name to "Bluetooth Device"
- private byte[] mDeviceName = new byte[] {
- // Bluetooth
- 0x42, 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68,
- // <space>Device
- 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65
- };
-
- // Classic
- private final byte[] mClassicLength;
- private byte[] mClassOfDevice = new byte[CLASS_OF_DEVICE_OCTETS];
-
- // LE
- private final @LeRole int mLeDeviceRole;
- private byte[] mLeTemporaryKey = new byte[LE_TK_OCTETS];
- private byte[] mLeAppearance = new byte[LE_APPEARANCE_OCTETS];
- private @LeFlag int mLeFlags = LE_FLAG_LIMITED_DISCOVERY_MODE;
-
- /**
- * @return byte array representing the MAC address of a bluetooth device.
- * The Address is 6 octets long with a 1 octet address type associated with the address.
- *
- * <p>For classic this will be 6 byte address plus the default of PUBLIC_ADDRESS Address Type.
- * For LE there are more choices for Address Type.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public byte[] getDeviceAddressWithType() {
- return mDeviceAddressWithType;
- }
-
- /**
- * @return byte array representing the confirmationHash value
- * which is used to confirm the identity to the controller.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public byte[] getConfirmationHash() {
- return mConfirmationHash;
- }
-
- /**
- * @return byte array representing the randomizerHash value
- * which is used to verify the identity of the controller.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public byte[] getRandomizerHash() {
- return mRandomizerHash;
- }
-
- /**
- * @return Device Name used for displaying name in UI.
- *
- * <p>Also, this will be populated with the LE Local Name if the data is for LE.
- *
- * @hide
- */
- @Nullable
- @SystemApi
- public byte[] getDeviceName() {
- return mDeviceName;
- }
-
- /**
- * @return byte array representing the oob data length which is the length
- * of all of the data including these octets.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public byte[] getClassicLength() {
- return mClassicLength;
- }
-
- /**
- * @return byte array representing the class of device for UI display.
- *
- * <p>Does not indicate services available; for display only.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public byte[] getClassOfDevice() {
- return mClassOfDevice;
- }
-
- /**
- * @return Temporary Key used for LE pairing.
- *
- * @hide
- */
- @Nullable
- @SystemApi
- public byte[] getLeTemporaryKey() {
- return mLeTemporaryKey;
- }
-
- /**
- * @return Appearance used for LE pairing. For use in UI situations
- * when determining what sort of icons or text to display regarding
- * the device.
- *
- * @hide
- */
- @Nullable
- @SystemApi
- public byte[] getLeAppearance() {
- return mLeAppearance;
- }
-
- /**
- * @return Flags used to determing discoverable mode to use, BR/EDR Support, and Capability.
- *
- * <p>Possible LE Flags:
- * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
- * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
- * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
- * LMP Feature Mask Definitions.
- * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
- * Same Device Capable (Controller).
- * Bit 49 of LMP Feature Mask Definitions.
- * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
- * Same Device Capable (Host).
- * Bit 55 of LMP Feature Mask Definitions.
- * <b>0x05- 0x07 Reserved</b>
- *
- * @hide
- */
- @NonNull
- @SystemApi
- @LeFlag
- public int getLeFlags() {
- return mLeFlags;
- }
-
- /**
- * @return the supported and preferred roles of the LE device.
- *
- * <p>Possible Values:
- * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
- * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
- * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
- * Peripheral Preferred
- * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
- * 0x04 - 0xFF Reserved
- *
- * @hide
- */
- @NonNull
- @SystemApi
- @LeRole
- public int getLeDeviceRole() {
- return mLeDeviceRole;
- }
-
- /**
- * Classic Security Constructor
- */
- private OobData(@NonNull byte[] classicLength, @NonNull byte[] deviceAddressWithType,
- @NonNull byte[] confirmationHash) {
- mClassicLength = classicLength;
- mDeviceAddressWithType = deviceAddressWithType;
- mConfirmationHash = confirmationHash;
- mLeDeviceRole = -1; // Satisfy final
- }
-
- /**
- * LE Security Constructor
- */
- private OobData(@NonNull byte[] deviceAddressWithType, @LeRole int leDeviceRole,
- @NonNull byte[] confirmationHash) {
- mDeviceAddressWithType = deviceAddressWithType;
- mLeDeviceRole = leDeviceRole;
- mConfirmationHash = confirmationHash;
- mClassicLength = new byte[OOB_LENGTH_OCTETS]; // Satisfy final
- }
-
- private OobData(Parcel in) {
- // Both
- mDeviceAddressWithType = in.createByteArray();
- mConfirmationHash = in.createByteArray();
- mRandomizerHash = in.createByteArray();
- mDeviceName = in.createByteArray();
-
- // Classic
- mClassicLength = in.createByteArray();
- mClassOfDevice = in.createByteArray();
-
- // LE
- mLeDeviceRole = in.readInt();
- mLeTemporaryKey = in.createByteArray();
- mLeAppearance = in.createByteArray();
- mLeFlags = in.readInt();
- }
-
- /**
- * @hide
- */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /**
- * @hide
- */
- @Override
- public void writeToParcel(@NonNull Parcel out, int flags) {
- // Both
- // Required
- out.writeByteArray(mDeviceAddressWithType);
- // Required
- out.writeByteArray(mConfirmationHash);
- // Optional
- out.writeByteArray(mRandomizerHash);
- // Optional
- out.writeByteArray(mDeviceName);
-
- // Classic
- // Required
- out.writeByteArray(mClassicLength);
- // Optional
- out.writeByteArray(mClassOfDevice);
-
- // LE
- // Required
- out.writeInt(mLeDeviceRole);
- // Required
- out.writeByteArray(mLeTemporaryKey);
- // Optional
- out.writeByteArray(mLeAppearance);
- // Optional
- out.writeInt(mLeFlags);
- }
-
- // For Parcelable
- public static final @android.annotation.NonNull Parcelable.Creator<OobData> CREATOR =
- new Parcelable.Creator<OobData>() {
- public OobData createFromParcel(Parcel in) {
- return new OobData(in);
- }
-
- public OobData[] newArray(int size) {
- return new OobData[size];
- }
- };
-
- /**
- * @return a {@link String} representation of the OobData object.
- *
- * @hide
- */
- @Override
- @NonNull
- public String toString() {
- return "OobData: \n\t"
- // Both
- + "Device Address With Type: " + toHexString(mDeviceAddressWithType) + "\n\t"
- + "Confirmation: " + toHexString(mConfirmationHash) + "\n\t"
- + "Randomizer: " + toHexString(mRandomizerHash) + "\n\t"
- + "Device Name: " + toHexString(mDeviceName) + "\n\t"
- // Classic
- + "OobData Length: " + toHexString(mClassicLength) + "\n\t"
- + "Class of Device: " + toHexString(mClassOfDevice) + "\n\t"
- // LE
- + "LE Device Role: " + toHexString(mLeDeviceRole) + "\n\t"
- + "LE Temporary Key: " + toHexString(mLeTemporaryKey) + "\n\t"
- + "LE Appearance: " + toHexString(mLeAppearance) + "\n\t"
- + "LE Flags: " + toHexString(mLeFlags) + "\n\t";
- }
-
- @NonNull
- private String toHexString(int b) {
- return toHexString(new byte[] {(byte) b});
- }
-
- @NonNull
- private String toHexString(byte b) {
- return toHexString(new byte[] {b});
- }
-
- @NonNull
- private String toHexString(byte[] array) {
- if (array == null) return "null";
- StringBuilder builder = new StringBuilder(array.length * 2);
- for (byte b: array) {
- builder.append(String.format("%02x", b));
- }
- return builder.toString();
- }
-}
diff --git a/core/java/android/bluetooth/SdpDipRecord.java b/core/java/android/bluetooth/SdpDipRecord.java
deleted file mode 100644
index 84b0eef..0000000
--- a/core/java/android/bluetooth/SdpDipRecord.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* 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.bluetooth;
-
-import java.util.Arrays;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Data representation of a Object Push Profile Server side SDP record.
- */
-/** @hide */
-public class SdpDipRecord implements Parcelable {
- private final int mSpecificationId;
- private final int mVendorId;
- private final int mVendorIdSource;
- private final int mProductId;
- private final int mVersion;
- private final boolean mPrimaryRecord;
-
- public SdpDipRecord(int specificationId,
- int vendorId, int vendorIdSource,
- int productId, int version,
- boolean primaryRecord) {
- super();
- this.mSpecificationId = specificationId;
- this.mVendorId = vendorId;
- this.mVendorIdSource = vendorIdSource;
- this.mProductId = productId;
- this.mVersion = version;
- this.mPrimaryRecord = primaryRecord;
- }
-
- public SdpDipRecord(Parcel in) {
- this.mSpecificationId = in.readInt();
- this.mVendorId = in.readInt();
- this.mVendorIdSource = in.readInt();
- this.mProductId = in.readInt();
- this.mVersion = in.readInt();
- this.mPrimaryRecord = in.readBoolean();
- }
-
- public int getSpecificationId() {
- return mSpecificationId;
- }
-
- public int getVendorId() {
- return mVendorId;
- }
-
- public int getVendorIdSource() {
- return mVendorIdSource;
- }
-
- public int getProductId() {
- return mProductId;
- }
-
- public int getVersion() {
- return mVersion;
- }
-
- public boolean getPrimaryRecord() {
- return mPrimaryRecord;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mSpecificationId);
- dest.writeInt(mVendorId);
- dest.writeInt(mVendorIdSource);
- dest.writeInt(mProductId);
- dest.writeInt(mVersion);
- dest.writeBoolean(mPrimaryRecord);
- }
-
- @Override
- public int describeContents() {
- /* No special objects */
- return 0;
- }
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- public SdpDipRecord createFromParcel(Parcel in) {
- return new SdpDipRecord(in);
- }
- public SdpDipRecord[] newArray(int size) {
- return new SdpDipRecord[size];
- }
- };
-}
diff --git a/core/java/android/bluetooth/SdpMasRecord.java b/core/java/android/bluetooth/SdpMasRecord.java
deleted file mode 100644
index 72d4938..0000000
--- a/core/java/android/bluetooth/SdpMasRecord.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* 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.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public class SdpMasRecord implements Parcelable {
- private final int mMasInstanceId;
- private final int mL2capPsm;
- private final int mRfcommChannelNumber;
- private final int mProfileVersion;
- private final int mSupportedFeatures;
- private final int mSupportedMessageTypes;
- private final String mServiceName;
-
- /** Message type */
- public static final class MessageType {
- public static final int EMAIL = 0x01;
- public static final int SMS_GSM = 0x02;
- public static final int SMS_CDMA = 0x04;
- public static final int MMS = 0x08;
- }
-
- public SdpMasRecord(int masInstanceId,
- int l2capPsm,
- int rfcommChannelNumber,
- int profileVersion,
- int supportedFeatures,
- int supportedMessageTypes,
- String serviceName) {
- mMasInstanceId = masInstanceId;
- mL2capPsm = l2capPsm;
- mRfcommChannelNumber = rfcommChannelNumber;
- mProfileVersion = profileVersion;
- mSupportedFeatures = supportedFeatures;
- mSupportedMessageTypes = supportedMessageTypes;
- mServiceName = serviceName;
- }
-
- public SdpMasRecord(Parcel in) {
- mMasInstanceId = in.readInt();
- mL2capPsm = in.readInt();
- mRfcommChannelNumber = in.readInt();
- mProfileVersion = in.readInt();
- mSupportedFeatures = in.readInt();
- mSupportedMessageTypes = in.readInt();
- mServiceName = in.readString();
- }
-
- @Override
- public int describeContents() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- public int getMasInstanceId() {
- return mMasInstanceId;
- }
-
- public int getL2capPsm() {
- return mL2capPsm;
- }
-
- public int getRfcommCannelNumber() {
- return mRfcommChannelNumber;
- }
-
- public int getProfileVersion() {
- return mProfileVersion;
- }
-
- public int getSupportedFeatures() {
- return mSupportedFeatures;
- }
-
- public int getSupportedMessageTypes() {
- return mSupportedMessageTypes;
- }
-
- public boolean msgSupported(int msg) {
- return (mSupportedMessageTypes & msg) != 0;
- }
-
- public String getServiceName() {
- return mServiceName;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mMasInstanceId);
- dest.writeInt(mL2capPsm);
- dest.writeInt(mRfcommChannelNumber);
- dest.writeInt(mProfileVersion);
- dest.writeInt(mSupportedFeatures);
- dest.writeInt(mSupportedMessageTypes);
- dest.writeString(mServiceName);
- }
-
- @Override
- public String toString() {
- String ret = "Bluetooth MAS SDP Record:\n";
-
- if (mMasInstanceId != -1) {
- ret += "Mas Instance Id: " + mMasInstanceId + "\n";
- }
- if (mRfcommChannelNumber != -1) {
- ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n";
- }
- if (mL2capPsm != -1) {
- ret += "L2CAP PSM: " + mL2capPsm + "\n";
- }
- if (mServiceName != null) {
- ret += "Service Name: " + mServiceName + "\n";
- }
- if (mProfileVersion != -1) {
- ret += "Profile version: " + mProfileVersion + "\n";
- }
- if (mSupportedMessageTypes != -1) {
- ret += "Supported msg types: " + mSupportedMessageTypes + "\n";
- }
- if (mSupportedFeatures != -1) {
- ret += "Supported features: " + mSupportedFeatures + "\n";
- }
- return ret;
- }
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- public SdpMasRecord createFromParcel(Parcel in) {
- return new SdpMasRecord(in);
- }
-
- public SdpRecord[] newArray(int size) {
- return new SdpRecord[size];
- }
- };
-}
diff --git a/core/java/android/bluetooth/SdpMnsRecord.java b/core/java/android/bluetooth/SdpMnsRecord.java
deleted file mode 100644
index a781d5d..0000000
--- a/core/java/android/bluetooth/SdpMnsRecord.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* 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.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public class SdpMnsRecord implements Parcelable {
- private final int mL2capPsm;
- private final int mRfcommChannelNumber;
- private final int mSupportedFeatures;
- private final int mProfileVersion;
- private final String mServiceName;
-
- public SdpMnsRecord(int l2capPsm,
- int rfcommChannelNumber,
- int profileVersion,
- int supportedFeatures,
- String serviceName) {
- mL2capPsm = l2capPsm;
- mRfcommChannelNumber = rfcommChannelNumber;
- mSupportedFeatures = supportedFeatures;
- mServiceName = serviceName;
- mProfileVersion = profileVersion;
- }
-
- public SdpMnsRecord(Parcel in) {
- mRfcommChannelNumber = in.readInt();
- mL2capPsm = in.readInt();
- mServiceName = in.readString();
- mSupportedFeatures = in.readInt();
- mProfileVersion = in.readInt();
- }
-
- @Override
- public int describeContents() {
- // TODO Auto-generated method stub
- return 0;
- }
-
-
- public int getL2capPsm() {
- return mL2capPsm;
- }
-
- public int getRfcommChannelNumber() {
- return mRfcommChannelNumber;
- }
-
- public int getSupportedFeatures() {
- return mSupportedFeatures;
- }
-
- public String getServiceName() {
- return mServiceName;
- }
-
- public int getProfileVersion() {
- return mProfileVersion;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mRfcommChannelNumber);
- dest.writeInt(mL2capPsm);
- dest.writeString(mServiceName);
- dest.writeInt(mSupportedFeatures);
- dest.writeInt(mProfileVersion);
- }
-
- public String toString() {
- String ret = "Bluetooth MNS SDP Record:\n";
-
- if (mRfcommChannelNumber != -1) {
- ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n";
- }
- if (mL2capPsm != -1) {
- ret += "L2CAP PSM: " + mL2capPsm + "\n";
- }
- if (mServiceName != null) {
- ret += "Service Name: " + mServiceName + "\n";
- }
- if (mSupportedFeatures != -1) {
- ret += "Supported features: " + mSupportedFeatures + "\n";
- }
- if (mProfileVersion != -1) {
- ret += "Profile_version: " + mProfileVersion + "\n";
- }
- return ret;
- }
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- public SdpMnsRecord createFromParcel(Parcel in) {
- return new SdpMnsRecord(in);
- }
-
- public SdpMnsRecord[] newArray(int size) {
- return new SdpMnsRecord[size];
- }
- };
-}
diff --git a/core/java/android/bluetooth/SdpOppOpsRecord.java b/core/java/android/bluetooth/SdpOppOpsRecord.java
deleted file mode 100644
index e30745b8..0000000
--- a/core/java/android/bluetooth/SdpOppOpsRecord.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* 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.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-
-/**
- * Data representation of a Object Push Profile Server side SDP record.
- */
-
-/** @hide */
-public class SdpOppOpsRecord implements Parcelable {
-
- private final String mServiceName;
- private final int mRfcommChannel;
- private final int mL2capPsm;
- private final int mProfileVersion;
- private final byte[] mFormatsList;
-
- public SdpOppOpsRecord(String serviceName, int rfcommChannel,
- int l2capPsm, int version, byte[] formatsList) {
- super();
- mServiceName = serviceName;
- mRfcommChannel = rfcommChannel;
- mL2capPsm = l2capPsm;
- mProfileVersion = version;
- mFormatsList = formatsList;
- }
-
- public String getServiceName() {
- return mServiceName;
- }
-
- public int getRfcommChannel() {
- return mRfcommChannel;
- }
-
- public int getL2capPsm() {
- return mL2capPsm;
- }
-
- public int getProfileVersion() {
- return mProfileVersion;
- }
-
- public byte[] getFormatsList() {
- return mFormatsList;
- }
-
- @Override
- public int describeContents() {
- /* No special objects */
- return 0;
- }
-
- public SdpOppOpsRecord(Parcel in) {
- mRfcommChannel = in.readInt();
- mL2capPsm = in.readInt();
- mProfileVersion = in.readInt();
- mServiceName = in.readString();
- int arrayLength = in.readInt();
- if (arrayLength > 0) {
- byte[] bytes = new byte[arrayLength];
- in.readByteArray(bytes);
- mFormatsList = bytes;
- } else {
- mFormatsList = null;
- }
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mRfcommChannel);
- dest.writeInt(mL2capPsm);
- dest.writeInt(mProfileVersion);
- dest.writeString(mServiceName);
- if (mFormatsList != null && mFormatsList.length > 0) {
- dest.writeInt(mFormatsList.length);
- dest.writeByteArray(mFormatsList);
- } else {
- dest.writeInt(0);
- }
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder("Bluetooth OPP Server SDP Record:\n");
- sb.append(" RFCOMM Chan Number: ").append(mRfcommChannel);
- sb.append("\n L2CAP PSM: ").append(mL2capPsm);
- sb.append("\n Profile version: ").append(mProfileVersion);
- sb.append("\n Service Name: ").append(mServiceName);
- sb.append("\n Formats List: ").append(Arrays.toString(mFormatsList));
- return sb.toString();
- }
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- public SdpOppOpsRecord createFromParcel(Parcel in) {
- return new SdpOppOpsRecord(in);
- }
-
- public SdpOppOpsRecord[] newArray(int size) {
- return new SdpOppOpsRecord[size];
- }
- };
-
-}
diff --git a/core/java/android/bluetooth/SdpPseRecord.java b/core/java/android/bluetooth/SdpPseRecord.java
deleted file mode 100644
index 72249d0..0000000
--- a/core/java/android/bluetooth/SdpPseRecord.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* 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.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public class SdpPseRecord implements Parcelable {
- private final int mL2capPsm;
- private final int mRfcommChannelNumber;
- private final int mProfileVersion;
- private final int mSupportedFeatures;
- private final int mSupportedRepositories;
- private final String mServiceName;
-
- public SdpPseRecord(int l2capPsm,
- int rfcommChannelNumber,
- int profileVersion,
- int supportedFeatures,
- int supportedRepositories,
- String serviceName) {
- mL2capPsm = l2capPsm;
- mRfcommChannelNumber = rfcommChannelNumber;
- mProfileVersion = profileVersion;
- mSupportedFeatures = supportedFeatures;
- mSupportedRepositories = supportedRepositories;
- mServiceName = serviceName;
- }
-
- public SdpPseRecord(Parcel in) {
- mRfcommChannelNumber = in.readInt();
- mL2capPsm = in.readInt();
- mProfileVersion = in.readInt();
- mSupportedFeatures = in.readInt();
- mSupportedRepositories = in.readInt();
- mServiceName = in.readString();
- }
-
- @Override
- public int describeContents() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- public int getL2capPsm() {
- return mL2capPsm;
- }
-
- public int getRfcommChannelNumber() {
- return mRfcommChannelNumber;
- }
-
- public int getSupportedFeatures() {
- return mSupportedFeatures;
- }
-
- public String getServiceName() {
- return mServiceName;
- }
-
- public int getProfileVersion() {
- return mProfileVersion;
- }
-
- public int getSupportedRepositories() {
- return mSupportedRepositories;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mRfcommChannelNumber);
- dest.writeInt(mL2capPsm);
- dest.writeInt(mProfileVersion);
- dest.writeInt(mSupportedFeatures);
- dest.writeInt(mSupportedRepositories);
- dest.writeString(mServiceName);
-
- }
-
- @Override
- public String toString() {
- String ret = "Bluetooth MNS SDP Record:\n";
-
- if (mRfcommChannelNumber != -1) {
- ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n";
- }
- if (mL2capPsm != -1) {
- ret += "L2CAP PSM: " + mL2capPsm + "\n";
- }
- if (mProfileVersion != -1) {
- ret += "profile version: " + mProfileVersion + "\n";
- }
- if (mServiceName != null) {
- ret += "Service Name: " + mServiceName + "\n";
- }
- if (mSupportedFeatures != -1) {
- ret += "Supported features: " + mSupportedFeatures + "\n";
- }
- if (mSupportedRepositories != -1) {
- ret += "Supported repositories: " + mSupportedRepositories + "\n";
- }
-
- return ret;
- }
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- public SdpPseRecord createFromParcel(Parcel in) {
- return new SdpPseRecord(in);
- }
-
- public SdpPseRecord[] newArray(int size) {
- return new SdpPseRecord[size];
- }
- };
-}
diff --git a/core/java/android/bluetooth/SdpRecord.java b/core/java/android/bluetooth/SdpRecord.java
deleted file mode 100644
index 730862e..0000000
--- a/core/java/android/bluetooth/SdpRecord.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* 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.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-
-/** @hide */
-public class SdpRecord implements Parcelable {
-
- private final byte[] mRawData;
- private final int mRawSize;
-
- @Override
- public String toString() {
- return "BluetoothSdpRecord [rawData=" + Arrays.toString(mRawData)
- + ", rawSize=" + mRawSize + "]";
- }
-
- public SdpRecord(int sizeRecord, byte[] record) {
- mRawData = record;
- mRawSize = sizeRecord;
- }
-
- public SdpRecord(Parcel in) {
- mRawSize = in.readInt();
- mRawData = new byte[mRawSize];
- in.readByteArray(mRawData);
-
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mRawSize);
- dest.writeByteArray(mRawData);
-
-
- }
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- public SdpRecord createFromParcel(Parcel in) {
- return new SdpRecord(in);
- }
-
- public SdpRecord[] newArray(int size) {
- return new SdpRecord[size];
- }
- };
-
- public byte[] getRawData() {
- return mRawData;
- }
-
- public int getRawSize() {
- return mRawSize;
- }
-}
diff --git a/core/java/android/bluetooth/SdpSapsRecord.java b/core/java/android/bluetooth/SdpSapsRecord.java
deleted file mode 100644
index a1e2f7b..0000000
--- a/core/java/android/bluetooth/SdpSapsRecord.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2015 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.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public class SdpSapsRecord implements Parcelable {
- private final int mRfcommChannelNumber;
- private final int mProfileVersion;
- private final String mServiceName;
-
- public SdpSapsRecord(int rfcommChannelNumber, int profileVersion, String serviceName) {
- mRfcommChannelNumber = rfcommChannelNumber;
- mProfileVersion = profileVersion;
- mServiceName = serviceName;
- }
-
- public SdpSapsRecord(Parcel in) {
- mRfcommChannelNumber = in.readInt();
- mProfileVersion = in.readInt();
- mServiceName = in.readString();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public int getRfcommCannelNumber() {
- return mRfcommChannelNumber;
- }
-
- public int getProfileVersion() {
- return mProfileVersion;
- }
-
- public String getServiceName() {
- return mServiceName;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mRfcommChannelNumber);
- dest.writeInt(mProfileVersion);
- dest.writeString(mServiceName);
-
- }
-
- @Override
- public String toString() {
- String ret = "Bluetooth MAS SDP Record:\n";
-
- if (mRfcommChannelNumber != -1) {
- ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n";
- }
- if (mServiceName != null) {
- ret += "Service Name: " + mServiceName + "\n";
- }
- if (mProfileVersion != -1) {
- ret += "Profile version: " + mProfileVersion + "\n";
- }
- return ret;
- }
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- public SdpSapsRecord createFromParcel(Parcel in) {
- return new SdpSapsRecord(in);
- }
-
- public SdpRecord[] newArray(int size) {
- return new SdpRecord[size];
- }
- };
-}
diff --git a/core/java/android/bluetooth/UidTraffic.java b/core/java/android/bluetooth/UidTraffic.java
deleted file mode 100644
index 9982fa6..0000000
--- a/core/java/android/bluetooth/UidTraffic.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2015 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.bluetooth;
-
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Record of data traffic (in bytes) by an application identified by its UID.
- *
- * @hide
- */
-@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
-public final class UidTraffic implements Cloneable, Parcelable {
- private final int mAppUid;
- private long mRxBytes;
- private long mTxBytes;
-
- /** @hide */
- public UidTraffic(int appUid, long rx, long tx) {
- mAppUid = appUid;
- mRxBytes = rx;
- mTxBytes = tx;
- }
-
- /** @hide */
- private UidTraffic(Parcel in) {
- mAppUid = in.readInt();
- mRxBytes = in.readLong();
- mTxBytes = in.readLong();
- }
-
- /** @hide */
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mAppUid);
- dest.writeLong(mRxBytes);
- dest.writeLong(mTxBytes);
- }
-
- /** @hide */
- public void setRxBytes(long bytes) {
- mRxBytes = bytes;
- }
-
- /** @hide */
- public void setTxBytes(long bytes) {
- mTxBytes = bytes;
- }
-
- /** @hide */
- public void addRxBytes(long bytes) {
- mRxBytes += bytes;
- }
-
- /** @hide */
- public void addTxBytes(long bytes) {
- mTxBytes += bytes;
- }
-
- /**
- * @return corresponding app Uid
- */
- public int getUid() {
- return mAppUid;
- }
-
- /**
- * @return rx bytes count
- */
- public long getRxBytes() {
- return mRxBytes;
- }
-
- /**
- * @return tx bytes count
- */
- public long getTxBytes() {
- return mTxBytes;
- }
-
- /** @hide */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** @hide */
- @Override
- public UidTraffic clone() {
- return new UidTraffic(mAppUid, mRxBytes, mTxBytes);
- }
-
- /** @hide */
- @Override
- public String toString() {
- return "UidTraffic{mAppUid=" + mAppUid + ", mRxBytes=" + mRxBytes + ", mTxBytes="
- + mTxBytes + '}';
- }
-
- public static final @android.annotation.NonNull Creator<UidTraffic> CREATOR = new Creator<UidTraffic>() {
- @Override
- public UidTraffic createFromParcel(Parcel source) {
- return new UidTraffic(source);
- }
-
- @Override
- public UidTraffic[] newArray(int size) {
- return new UidTraffic[size];
- }
- };
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresBluetoothAdvertisePermission.java b/core/java/android/bluetooth/annotations/RequiresBluetoothAdvertisePermission.java
deleted file mode 100644
index c508c2c..0000000
--- a/core/java/android/bluetooth/annotations/RequiresBluetoothAdvertisePermission.java
+++ /dev/null
@@ -1,39 +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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc For apps targeting {@link Build.VERSION_CODES#S} or or higher,
- * this requires the {@link Manifest.permission#BLUETOOTH_ADVERTISE}
- * permission which can be gained with
- * {@link android.app.Activity#requestPermissions(String[], int)}.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresBluetoothAdvertisePermission {
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresBluetoothConnectPermission.java b/core/java/android/bluetooth/annotations/RequiresBluetoothConnectPermission.java
deleted file mode 100644
index e159eaa..0000000
--- a/core/java/android/bluetooth/annotations/RequiresBluetoothConnectPermission.java
+++ /dev/null
@@ -1,39 +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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc For apps targeting {@link Build.VERSION_CODES#S} or or higher,
- * this requires the {@link Manifest.permission#BLUETOOTH_CONNECT}
- * permission which can be gained with
- * {@link android.app.Activity#requestPermissions(String[], int)}.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresBluetoothConnectPermission {
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresBluetoothLocationPermission.java b/core/java/android/bluetooth/annotations/RequiresBluetoothLocationPermission.java
deleted file mode 100644
index 2bb3204..0000000
--- a/core/java/android/bluetooth/annotations/RequiresBluetoothLocationPermission.java
+++ /dev/null
@@ -1,41 +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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc In addition, this requires either the
- * {@link Manifest.permission#ACCESS_FINE_LOCATION}
- * permission or a strong assertion that you will never derive the
- * physical location of the device. You can make this assertion by
- * declaring {@code usesPermissionFlags="neverForLocation"} on the
- * relevant {@code <uses-permission>} manifest tag, but it may
- * restrict the types of Bluetooth devices you can interact with.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresBluetoothLocationPermission {
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresBluetoothScanPermission.java b/core/java/android/bluetooth/annotations/RequiresBluetoothScanPermission.java
deleted file mode 100644
index 800ff39..0000000
--- a/core/java/android/bluetooth/annotations/RequiresBluetoothScanPermission.java
+++ /dev/null
@@ -1,39 +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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc For apps targeting {@link Build.VERSION_CODES#S} or or higher,
- * this requires the {@link Manifest.permission#BLUETOOTH_SCAN}
- * permission which can be gained with
- * {@link android.app.Activity#requestPermissions(String[], int)}.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresBluetoothScanPermission {
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothAdminPermission.java b/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothAdminPermission.java
deleted file mode 100644
index 9adf695..0000000
--- a/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothAdminPermission.java
+++ /dev/null
@@ -1,39 +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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc For apps targeting {@link Build.VERSION_CODES#R} or lower, this
- * requires the {@link Manifest.permission#BLUETOOTH_ADMIN}
- * permission which can be gained with a simple
- * {@code <uses-permission>} manifest tag.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresLegacyBluetoothAdminPermission {
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothPermission.java b/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothPermission.java
deleted file mode 100644
index 79621c3..0000000
--- a/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothPermission.java
+++ /dev/null
@@ -1,39 +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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc For apps targeting {@link Build.VERSION_CODES#R} or lower, this
- * requires the {@link Manifest.permission#BLUETOOTH} permission
- * which can be gained with a simple {@code <uses-permission>}
- * manifest tag.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresLegacyBluetoothPermission {
-}
diff --git a/core/java/android/bluetooth/le/AdvertiseCallback.java b/core/java/android/bluetooth/le/AdvertiseCallback.java
deleted file mode 100644
index 4fa8c4f..0000000
--- a/core/java/android/bluetooth/le/AdvertiseCallback.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-/**
- * Bluetooth LE advertising callbacks, used to deliver advertising operation status.
- */
-public abstract class AdvertiseCallback {
-
- /**
- * The requested operation was successful.
- *
- * @hide
- */
- public static final int ADVERTISE_SUCCESS = 0;
-
- /**
- * Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes.
- */
- public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1;
-
- /**
- * Failed to start advertising because no advertising instance is available.
- */
- public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2;
-
- /**
- * Failed to start advertising as the advertising is already started.
- */
- public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3;
-
- /**
- * Operation failed due to an internal error.
- */
- public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4;
-
- /**
- * This feature is not supported on this platform.
- */
- public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5;
-
- /**
- * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertising} indicating
- * that the advertising has been started successfully.
- *
- * @param settingsInEffect The actual settings used for advertising, which may be different from
- * what has been requested.
- */
- public void onStartSuccess(AdvertiseSettings settingsInEffect) {
- }
-
- /**
- * Callback when advertising could not be started.
- *
- * @param errorCode Error code (see ADVERTISE_FAILED_* constants) for advertising start
- * failures.
- */
- public void onStartFailure(int errorCode) {
- }
-}
diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java
deleted file mode 100644
index fdf62ec..0000000
--- a/core/java/android/bluetooth/le/AdvertiseData.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-import android.util.ArrayMap;
-import android.util.SparseArray;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Advertise data packet container for Bluetooth LE advertising. This represents the data to be
- * advertised as well as the scan response data for active scans.
- * <p>
- * Use {@link AdvertiseData.Builder} to create an instance of {@link AdvertiseData} to be
- * advertised.
- *
- * @see BluetoothLeAdvertiser
- * @see ScanRecord
- */
-public final class AdvertiseData implements Parcelable {
-
- @Nullable
- private final List<ParcelUuid> mServiceUuids;
-
- @NonNull
- private final List<ParcelUuid> mServiceSolicitationUuids;
-
- @Nullable
- private final List<TransportDiscoveryData> mTransportDiscoveryData;
-
- private final SparseArray<byte[]> mManufacturerSpecificData;
- private final Map<ParcelUuid, byte[]> mServiceData;
- private final boolean mIncludeTxPowerLevel;
- private final boolean mIncludeDeviceName;
-
- private AdvertiseData(List<ParcelUuid> serviceUuids,
- List<ParcelUuid> serviceSolicitationUuids,
- List<TransportDiscoveryData> transportDiscoveryData,
- SparseArray<byte[]> manufacturerData,
- Map<ParcelUuid, byte[]> serviceData,
- boolean includeTxPowerLevel,
- boolean includeDeviceName) {
- mServiceUuids = serviceUuids;
- mServiceSolicitationUuids = serviceSolicitationUuids;
- mTransportDiscoveryData = transportDiscoveryData;
- mManufacturerSpecificData = manufacturerData;
- mServiceData = serviceData;
- mIncludeTxPowerLevel = includeTxPowerLevel;
- mIncludeDeviceName = includeDeviceName;
- }
-
- /**
- * Returns a list of service UUIDs within the advertisement that are used to identify the
- * Bluetooth GATT services.
- */
- public List<ParcelUuid> getServiceUuids() {
- return mServiceUuids;
- }
-
- /**
- * Returns a list of service solicitation UUIDs within the advertisement that we invite to connect.
- */
- @NonNull
- public List<ParcelUuid> getServiceSolicitationUuids() {
- return mServiceSolicitationUuids;
- }
-
- /**
- * Returns a list of {@link TransportDiscoveryData} within the advertisement.
- */
- @NonNull
- public List<TransportDiscoveryData> getTransportDiscoveryData() {
- if (mTransportDiscoveryData == null) {
- return Collections.emptyList();
- }
- return mTransportDiscoveryData;
- }
-
- /**
- * Returns an array of manufacturer Id and the corresponding manufacturer specific data. The
- * manufacturer id is a non-negative number assigned by Bluetooth SIG.
- */
- public SparseArray<byte[]> getManufacturerSpecificData() {
- return mManufacturerSpecificData;
- }
-
- /**
- * Returns a map of 16-bit UUID and its corresponding service data.
- */
- public Map<ParcelUuid, byte[]> getServiceData() {
- return mServiceData;
- }
-
- /**
- * Whether the transmission power level will be included in the advertisement packet.
- */
- public boolean getIncludeTxPowerLevel() {
- return mIncludeTxPowerLevel;
- }
-
- /**
- * Whether the device name will be included in the advertisement packet.
- */
- public boolean getIncludeDeviceName() {
- return mIncludeDeviceName;
- }
-
- /**
- * @hide
- */
- @Override
- public int hashCode() {
- return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mTransportDiscoveryData,
- mManufacturerSpecificData, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel);
- }
-
- /**
- * @hide
- */
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- AdvertiseData other = (AdvertiseData) obj;
- return Objects.equals(mServiceUuids, other.mServiceUuids)
- && Objects.equals(mServiceSolicitationUuids, other.mServiceSolicitationUuids)
- && Objects.equals(mTransportDiscoveryData, other.mTransportDiscoveryData)
- && BluetoothLeUtils.equals(mManufacturerSpecificData,
- other.mManufacturerSpecificData)
- && BluetoothLeUtils.equals(mServiceData, other.mServiceData)
- && mIncludeDeviceName == other.mIncludeDeviceName
- && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel;
- }
-
- @Override
- public String toString() {
- return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mServiceSolicitationUuids="
- + mServiceSolicitationUuids + ", mTransportDiscoveryData="
- + mTransportDiscoveryData + ", mManufacturerSpecificData="
- + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData="
- + BluetoothLeUtils.toString(mServiceData)
- + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName="
- + mIncludeDeviceName + "]";
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeTypedArray(mServiceUuids.toArray(new ParcelUuid[mServiceUuids.size()]), flags);
- dest.writeTypedArray(mServiceSolicitationUuids.toArray(
- new ParcelUuid[mServiceSolicitationUuids.size()]), flags);
-
- dest.writeTypedList(mTransportDiscoveryData);
-
- // mManufacturerSpecificData could not be null.
- dest.writeInt(mManufacturerSpecificData.size());
- for (int i = 0; i < mManufacturerSpecificData.size(); ++i) {
- dest.writeInt(mManufacturerSpecificData.keyAt(i));
- dest.writeByteArray(mManufacturerSpecificData.valueAt(i));
- }
- dest.writeInt(mServiceData.size());
- for (ParcelUuid uuid : mServiceData.keySet()) {
- dest.writeTypedObject(uuid, flags);
- dest.writeByteArray(mServiceData.get(uuid));
- }
- dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0));
- dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0));
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<AdvertiseData> CREATOR =
- new Creator<AdvertiseData>() {
- @Override
- public AdvertiseData[] newArray(int size) {
- return new AdvertiseData[size];
- }
-
- @Override
- public AdvertiseData createFromParcel(Parcel in) {
- Builder builder = new Builder();
- ArrayList<ParcelUuid> uuids = in.createTypedArrayList(ParcelUuid.CREATOR);
- for (ParcelUuid uuid : uuids) {
- builder.addServiceUuid(uuid);
- }
-
- ArrayList<ParcelUuid> solicitationUuids = in.createTypedArrayList(ParcelUuid.CREATOR);
- for (ParcelUuid uuid : solicitationUuids) {
- builder.addServiceSolicitationUuid(uuid);
- }
-
- List<TransportDiscoveryData> transportDiscoveryData =
- in.createTypedArrayList(TransportDiscoveryData.CREATOR);
- for (TransportDiscoveryData tdd : transportDiscoveryData) {
- builder.addTransportDiscoveryData(tdd);
- }
-
- int manufacturerSize = in.readInt();
- for (int i = 0; i < manufacturerSize; ++i) {
- int manufacturerId = in.readInt();
- byte[] manufacturerData = in.createByteArray();
- builder.addManufacturerData(manufacturerId, manufacturerData);
- }
- int serviceDataSize = in.readInt();
- for (int i = 0; i < serviceDataSize; ++i) {
- ParcelUuid serviceDataUuid = in.readTypedObject(ParcelUuid.CREATOR);
- byte[] serviceData = in.createByteArray();
- builder.addServiceData(serviceDataUuid, serviceData);
- }
- builder.setIncludeTxPowerLevel(in.readByte() == 1);
- builder.setIncludeDeviceName(in.readByte() == 1);
- return builder.build();
- }
- };
-
- /**
- * Builder for {@link AdvertiseData}.
- */
- public static final class Builder {
- @Nullable
- private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>();
- @NonNull
- private List<ParcelUuid> mServiceSolicitationUuids = new ArrayList<ParcelUuid>();
- @Nullable
- private List<TransportDiscoveryData> mTransportDiscoveryData =
- new ArrayList<TransportDiscoveryData>();
- private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>();
- private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>();
- private boolean mIncludeTxPowerLevel;
- private boolean mIncludeDeviceName;
-
- /**
- * Add a service UUID to advertise data.
- *
- * @param serviceUuid A service UUID to be advertised.
- * @throws IllegalArgumentException If the {@code serviceUuid} is null.
- */
- public Builder addServiceUuid(ParcelUuid serviceUuid) {
- if (serviceUuid == null) {
- throw new IllegalArgumentException("serviceUuid is null");
- }
- mServiceUuids.add(serviceUuid);
- return this;
- }
-
- /**
- * Add a service solicitation UUID to advertise data.
- *
- * @param serviceSolicitationUuid A service solicitation UUID to be advertised.
- * @throws IllegalArgumentException If the {@code serviceSolicitationUuid} is null.
- */
- @NonNull
- public Builder addServiceSolicitationUuid(@NonNull ParcelUuid serviceSolicitationUuid) {
- if (serviceSolicitationUuid == null) {
- throw new IllegalArgumentException("serviceSolicitationUuid is null");
- }
- mServiceSolicitationUuids.add(serviceSolicitationUuid);
- return this;
- }
-
- /**
- * Add service data to advertise data.
- *
- * @param serviceDataUuid 16-bit UUID of the service the data is associated with
- * @param serviceData Service data
- * @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is
- * empty.
- */
- public Builder addServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) {
- if (serviceDataUuid == null || serviceData == null) {
- throw new IllegalArgumentException(
- "serviceDataUuid or serviceDataUuid is null");
- }
- mServiceData.put(serviceDataUuid, serviceData);
- return this;
- }
-
- /**
- * Add Transport Discovery Data to advertise data.
- *
- * @param transportDiscoveryData Transport Discovery Data, consisting of one or more
- * Transport Blocks. Transport Discovery Data AD Type Code is already included.
- * @throws IllegalArgumentException If the {@code transportDiscoveryData} is empty
- */
- @NonNull
- public Builder addTransportDiscoveryData(
- @NonNull TransportDiscoveryData transportDiscoveryData) {
- if (transportDiscoveryData == null) {
- throw new IllegalArgumentException("transportDiscoveryData is null");
- }
- mTransportDiscoveryData.add(transportDiscoveryData);
- return this;
- }
-
- /**
- * Add manufacturer specific data.
- * <p>
- * Please refer to the Bluetooth Assigned Numbers document provided by the <a
- * href="https://www.bluetooth.org">Bluetooth SIG</a> for a list of existing company
- * identifiers.
- *
- * @param manufacturerId Manufacturer ID assigned by Bluetooth SIG.
- * @param manufacturerSpecificData Manufacturer specific data
- * @throws IllegalArgumentException If the {@code manufacturerId} is negative or {@code
- * manufacturerSpecificData} is null.
- */
- public Builder addManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) {
- if (manufacturerId < 0) {
- throw new IllegalArgumentException(
- "invalid manufacturerId - " + manufacturerId);
- }
- if (manufacturerSpecificData == null) {
- throw new IllegalArgumentException("manufacturerSpecificData is null");
- }
- mManufacturerSpecificData.put(manufacturerId, manufacturerSpecificData);
- return this;
- }
-
- /**
- * Whether the transmission power level should be included in the advertise packet. Tx power
- * level field takes 3 bytes in advertise packet.
- */
- public Builder setIncludeTxPowerLevel(boolean includeTxPowerLevel) {
- mIncludeTxPowerLevel = includeTxPowerLevel;
- return this;
- }
-
- /**
- * Set whether the device name should be included in advertise packet.
- */
- public Builder setIncludeDeviceName(boolean includeDeviceName) {
- mIncludeDeviceName = includeDeviceName;
- return this;
- }
-
- /**
- * Build the {@link AdvertiseData}.
- */
- public AdvertiseData build() {
- return new AdvertiseData(mServiceUuids, mServiceSolicitationUuids,
- mTransportDiscoveryData, mManufacturerSpecificData, mServiceData,
- mIncludeTxPowerLevel, mIncludeDeviceName);
- }
- }
-}
diff --git a/core/java/android/bluetooth/le/AdvertiseSettings.java b/core/java/android/bluetooth/le/AdvertiseSettings.java
deleted file mode 100644
index c52a6ee..0000000
--- a/core/java/android/bluetooth/le/AdvertiseSettings.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.bluetooth.le.AdvertisingSetParameters.AddressTypeStatus;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * The {@link AdvertiseSettings} provide a way to adjust advertising preferences for each
- * Bluetooth LE advertisement instance. Use {@link AdvertiseSettings.Builder} to create an
- * instance of this class.
- */
-public final class AdvertiseSettings implements Parcelable {
- /**
- * Perform Bluetooth LE advertising in low power mode. This is the default and preferred
- * advertising mode as it consumes the least power.
- */
- public static final int ADVERTISE_MODE_LOW_POWER = 0;
-
- /**
- * Perform Bluetooth LE advertising in balanced power mode. This is balanced between advertising
- * frequency and power consumption.
- */
- public static final int ADVERTISE_MODE_BALANCED = 1;
-
- /**
- * Perform Bluetooth LE advertising in low latency, high power mode. This has the highest power
- * consumption and should not be used for continuous background advertising.
- */
- public static final int ADVERTISE_MODE_LOW_LATENCY = 2;
-
- /**
- * Advertise using the lowest transmission (TX) power level. Low transmission power can be used
- * to restrict the visibility range of advertising packets.
- */
- public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0;
-
- /**
- * Advertise using low TX power level.
- */
- public static final int ADVERTISE_TX_POWER_LOW = 1;
-
- /**
- * Advertise using medium TX power level.
- */
- public static final int ADVERTISE_TX_POWER_MEDIUM = 2;
-
- /**
- * Advertise using high TX power level. This corresponds to largest visibility range of the
- * advertising packet.
- */
- public static final int ADVERTISE_TX_POWER_HIGH = 3;
-
- /**
- * The maximum limited advertisement duration as specified by the Bluetooth SIG
- */
- private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000;
-
-
- private final int mAdvertiseMode;
- private final int mAdvertiseTxPowerLevel;
- private final int mAdvertiseTimeoutMillis;
- private final boolean mAdvertiseConnectable;
- private final int mOwnAddressType;
-
- private AdvertiseSettings(int advertiseMode, int advertiseTxPowerLevel,
- boolean advertiseConnectable, int advertiseTimeout,
- @AddressTypeStatus int ownAddressType) {
- mAdvertiseMode = advertiseMode;
- mAdvertiseTxPowerLevel = advertiseTxPowerLevel;
- mAdvertiseConnectable = advertiseConnectable;
- mAdvertiseTimeoutMillis = advertiseTimeout;
- mOwnAddressType = ownAddressType;
- }
-
- private AdvertiseSettings(Parcel in) {
- mAdvertiseMode = in.readInt();
- mAdvertiseTxPowerLevel = in.readInt();
- mAdvertiseConnectable = in.readInt() != 0;
- mAdvertiseTimeoutMillis = in.readInt();
- mOwnAddressType = in.readInt();
- }
-
- /**
- * Returns the advertise mode.
- */
- public int getMode() {
- return mAdvertiseMode;
- }
-
- /**
- * Returns the TX power level for advertising.
- */
- public int getTxPowerLevel() {
- return mAdvertiseTxPowerLevel;
- }
-
- /**
- * Returns whether the advertisement will indicate connectable.
- */
- public boolean isConnectable() {
- return mAdvertiseConnectable;
- }
-
- /**
- * Returns the advertising time limit in milliseconds.
- */
- public int getTimeout() {
- return mAdvertiseTimeoutMillis;
- }
-
- /**
- * @return the own address type for advertising
- *
- * @hide
- */
- @SystemApi
- public @AddressTypeStatus int getOwnAddressType() {
- return mOwnAddressType;
- }
-
- @Override
- public String toString() {
- return "Settings [mAdvertiseMode=" + mAdvertiseMode
- + ", mAdvertiseTxPowerLevel=" + mAdvertiseTxPowerLevel
- + ", mAdvertiseConnectable=" + mAdvertiseConnectable
- + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis
- + ", mOwnAddressType=" + mOwnAddressType + "]";
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mAdvertiseMode);
- dest.writeInt(mAdvertiseTxPowerLevel);
- dest.writeInt(mAdvertiseConnectable ? 1 : 0);
- dest.writeInt(mAdvertiseTimeoutMillis);
- dest.writeInt(mOwnAddressType);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<AdvertiseSettings> CREATOR =
- new Creator<AdvertiseSettings>() {
- @Override
- public AdvertiseSettings[] newArray(int size) {
- return new AdvertiseSettings[size];
- }
-
- @Override
- public AdvertiseSettings createFromParcel(Parcel in) {
- return new AdvertiseSettings(in);
- }
- };
-
- /**
- * Builder class for {@link AdvertiseSettings}.
- */
- public static final class Builder {
- private int mMode = ADVERTISE_MODE_LOW_POWER;
- private int mTxPowerLevel = ADVERTISE_TX_POWER_MEDIUM;
- private int mTimeoutMillis = 0;
- private boolean mConnectable = true;
- private int mOwnAddressType = AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT;
-
- /**
- * Set advertise mode to control the advertising power and latency.
- *
- * @param advertiseMode Bluetooth LE Advertising mode, can only be one of {@link
- * AdvertiseSettings#ADVERTISE_MODE_LOW_POWER},
- * {@link AdvertiseSettings#ADVERTISE_MODE_BALANCED},
- * or {@link AdvertiseSettings#ADVERTISE_MODE_LOW_LATENCY}.
- * @throws IllegalArgumentException If the advertiseMode is invalid.
- */
- public Builder setAdvertiseMode(int advertiseMode) {
- if (advertiseMode < ADVERTISE_MODE_LOW_POWER
- || advertiseMode > ADVERTISE_MODE_LOW_LATENCY) {
- throw new IllegalArgumentException("unknown mode " + advertiseMode);
- }
- mMode = advertiseMode;
- return this;
- }
-
- /**
- * Set advertise TX power level to control the transmission power level for the advertising.
- *
- * @param txPowerLevel Transmission power of Bluetooth LE Advertising, can only be one of
- * {@link AdvertiseSettings#ADVERTISE_TX_POWER_ULTRA_LOW}, {@link
- * AdvertiseSettings#ADVERTISE_TX_POWER_LOW},
- * {@link AdvertiseSettings#ADVERTISE_TX_POWER_MEDIUM}
- * or {@link AdvertiseSettings#ADVERTISE_TX_POWER_HIGH}.
- * @throws IllegalArgumentException If the {@code txPowerLevel} is invalid.
- */
- public Builder setTxPowerLevel(int txPowerLevel) {
- if (txPowerLevel < ADVERTISE_TX_POWER_ULTRA_LOW
- || txPowerLevel > ADVERTISE_TX_POWER_HIGH) {
- throw new IllegalArgumentException("unknown tx power level " + txPowerLevel);
- }
- mTxPowerLevel = txPowerLevel;
- return this;
- }
-
- /**
- * Set whether the advertisement type should be connectable or non-connectable.
- *
- * @param connectable Controls whether the advertisment type will be connectable (true) or
- * non-connectable (false).
- */
- public Builder setConnectable(boolean connectable) {
- mConnectable = connectable;
- return this;
- }
-
- /**
- * Limit advertising to a given amount of time.
- *
- * @param timeoutMillis Advertising time limit. May not exceed 180000 milliseconds. A value
- * of 0 will disable the time limit.
- * @throws IllegalArgumentException If the provided timeout is over 180000 ms.
- */
- public Builder setTimeout(int timeoutMillis) {
- if (timeoutMillis < 0 || timeoutMillis > LIMITED_ADVERTISING_MAX_MILLIS) {
- throw new IllegalArgumentException("timeoutMillis invalid (must be 0-"
- + LIMITED_ADVERTISING_MAX_MILLIS + " milliseconds)");
- }
- mTimeoutMillis = timeoutMillis;
- return this;
- }
-
- /**
- * Set own address type for advertising to control public or privacy mode. If used to set
- * address type anything other than {@link AdvertisingSetParameters#ADDRESS_TYPE_DEFAULT},
- * then it will require BLUETOOTH_PRIVILEGED permission and will be checked at the
- * time of starting advertising.
- *
- * @throws IllegalArgumentException If the {@code ownAddressType} is invalid
- *
- * @hide
- */
- @SystemApi
- public @NonNull Builder setOwnAddressType(@AddressTypeStatus int ownAddressType) {
- if (ownAddressType < AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT
- || ownAddressType > AdvertisingSetParameters.ADDRESS_TYPE_RANDOM) {
- throw new IllegalArgumentException("unknown address type " + ownAddressType);
- }
- mOwnAddressType = ownAddressType;
- return this;
- }
-
- /**
- * Build the {@link AdvertiseSettings} object.
- */
- public AdvertiseSettings build() {
- return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutMillis,
- mOwnAddressType);
- }
- }
-}
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
deleted file mode 100644
index bbdb695..0000000
--- a/core/java/android/bluetooth/le/AdvertisingSet.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothManager;
-import android.bluetooth.annotations.RequiresBluetoothAdvertisePermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.content.AttributionSource;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * This class provides a way to control single Bluetooth LE advertising instance.
- * <p>
- * To get an instance of {@link AdvertisingSet}, call the
- * {@link BluetoothLeAdvertiser#startAdvertisingSet} method.
- *
- * @see AdvertiseData
- */
-public final class AdvertisingSet {
- private static final String TAG = "AdvertisingSet";
-
- private final IBluetoothGatt mGatt;
- private int mAdvertiserId;
- private AttributionSource mAttributionSource;
-
- /* package */ AdvertisingSet(int advertiserId, IBluetoothManager bluetoothManager,
- AttributionSource attributionSource) {
- mAdvertiserId = advertiserId;
- mAttributionSource = attributionSource;
- try {
- mGatt = bluetoothManager.getBluetoothGatt();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
- throw new IllegalStateException("Failed to get Bluetooth");
- }
- }
-
- /* package */ void setAdvertiserId(int advertiserId) {
- mAdvertiserId = advertiserId;
- }
-
- /**
- * Enables Advertising. This method returns immediately, the operation status is
- * delivered through {@code callback.onAdvertisingEnabled()}.
- *
- * @param enable whether the advertising should be enabled (true), or disabled (false)
- * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535
- * (655,350 ms)
- * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
- * controller shall attempt to send prior to terminating the extended advertising, even if the
- * duration has not expired. Valid range is from 1 to 255.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void enableAdvertising(boolean enable, int duration,
- int maxExtendedAdvertisingEvents) {
- try {
- mGatt.enableAdvertisingSet(mAdvertiserId, enable, duration,
- maxExtendedAdvertisingEvents, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception - ", e);
- }
- }
-
- /**
- * Set/update data being Advertised. Make sure that data doesn't exceed the size limit for
- * specified AdvertisingSetParameters. This method returns immediately, the operation status is
- * delivered through {@code callback.onAdvertisingDataSet()}.
- * <p>
- * Advertising data must be empty if non-legacy scannable advertising is used.
- *
- * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
- * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
- * three bytes will be added for flags. If the update takes place when the advertising set is
- * enabled, the data can be maximum 251 bytes long.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void setAdvertisingData(AdvertiseData advertiseData) {
- try {
- mGatt.setAdvertisingData(mAdvertiserId, advertiseData, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception - ", e);
- }
- }
-
- /**
- * Set/update scan response data. Make sure that data doesn't exceed the size limit for
- * specified AdvertisingSetParameters. This method returns immediately, the operation status
- * is delivered through {@code callback.onScanResponseDataSet()}.
- *
- * @param scanResponse Scan response associated with the advertisement data. Size must not
- * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the update takes place
- * when the advertising set is enabled, the data can be maximum 251 bytes long.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void setScanResponseData(AdvertiseData scanResponse) {
- try {
- mGatt.setScanResponseData(mAdvertiserId, scanResponse, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception - ", e);
- }
- }
-
- /**
- * Update advertising parameters associated with this AdvertisingSet. Must be called when
- * advertising is not active. This method returns immediately, the operation status is delivered
- * through {@code callback.onAdvertisingParametersUpdated}.
- *
- * @param parameters advertising set parameters.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void setAdvertisingParameters(AdvertisingSetParameters parameters) {
- try {
- mGatt.setAdvertisingParameters(mAdvertiserId, parameters, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception - ", e);
- }
- }
-
- /**
- * Update periodic advertising parameters associated with this set. Must be called when
- * periodic advertising is not enabled. This method returns immediately, the operation
- * status is delivered through {@code callback.onPeriodicAdvertisingParametersUpdated()}.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void setPeriodicAdvertisingParameters(PeriodicAdvertisingParameters parameters) {
- try {
- mGatt.setPeriodicAdvertisingParameters(mAdvertiserId, parameters, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception - ", e);
- }
- }
-
- /**
- * Used to set periodic advertising data, must be called after setPeriodicAdvertisingParameters,
- * or after advertising was started with periodic advertising data set. This method returns
- * immediately, the operation status is delivered through
- * {@code callback.onPeriodicAdvertisingDataSet()}.
- *
- * @param periodicData Periodic advertising data. Size must not exceed {@link
- * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the update takes place when the
- * periodic advertising is enabled for this set, the data can be maximum 251 bytes long.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void setPeriodicAdvertisingData(AdvertiseData periodicData) {
- try {
- mGatt.setPeriodicAdvertisingData(mAdvertiserId, periodicData, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception - ", e);
- }
- }
-
- /**
- * Used to enable/disable periodic advertising. This method returns immediately, the operation
- * status is delivered through {@code callback.onPeriodicAdvertisingEnable()}.
- *
- * @param enable whether the periodic advertising should be enabled (true), or disabled
- * (false).
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void setPeriodicAdvertisingEnabled(boolean enable) {
- try {
- mGatt.setPeriodicAdvertisingEnable(mAdvertiserId, enable, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception - ", e);
- }
- }
-
- /**
- * Returns address associated with this advertising set.
- * This method is exposed only for Bluetooth PTS tests, no app or system service
- * should ever use it.
- *
- * @hide
- */
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_ADVERTISE,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public void getOwnAddress() {
- try {
- mGatt.getOwnAddress(mAdvertiserId, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "remote exception - ", e);
- }
- }
-
- /**
- * Returns advertiserId associated with this advertising set.
- *
- * @hide
- */
- @RequiresNoPermission
- public int getAdvertiserId() {
- return mAdvertiserId;
- }
-}
diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
deleted file mode 100644
index 51324fd..0000000
--- a/core/java/android/bluetooth/le/AdvertisingSetCallback.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-/**
- * Bluetooth LE advertising set callbacks, used to deliver advertising operation
- * status.
- */
-public abstract class AdvertisingSetCallback {
-
- /**
- * The requested operation was successful.
- */
- public static final int ADVERTISE_SUCCESS = 0;
-
- /**
- * Failed to start advertising as the advertise data to be broadcasted is too
- * large.
- */
- public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1;
-
- /**
- * Failed to start advertising because no advertising instance is available.
- */
- public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2;
-
- /**
- * Failed to start advertising as the advertising is already started.
- */
- public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3;
-
- /**
- * Operation failed due to an internal error.
- */
- public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4;
-
- /**
- * This feature is not supported on this platform.
- */
- public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5;
-
- /**
- * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet}
- * indicating result of the operation. If status is ADVERTISE_SUCCESS, then advertisingSet
- * contains the started set and it is advertising. If error occurred, advertisingSet is
- * null, and status will be set to proper error code.
- *
- * @param advertisingSet The advertising set that was started or null if error.
- * @param txPower tx power that will be used for this set.
- * @param status Status of the operation.
- */
- public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {
- }
-
- /**
- * Callback triggered in response to {@link BluetoothLeAdvertiser#stopAdvertisingSet}
- * indicating advertising set is stopped.
- *
- * @param advertisingSet The advertising set.
- */
- public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {
- }
-
- /**
- * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet}
- * indicating result of the operation. If status is ADVERTISE_SUCCESS, then advertising set is
- * advertising.
- *
- * @param advertisingSet The advertising set.
- * @param status Status of the operation.
- */
- public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable, int status) {
- }
-
- /**
- * Callback triggered in response to {@link AdvertisingSet#setAdvertisingData} indicating
- * result of the operation. If status is ADVERTISE_SUCCESS, then data was changed.
- *
- * @param advertisingSet The advertising set.
- * @param status Status of the operation.
- */
- public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) {
- }
-
- /**
- * Callback triggered in response to {@link AdvertisingSet#setAdvertisingData} indicating
- * result of the operation.
- *
- * @param advertisingSet The advertising set.
- * @param status Status of the operation.
- */
- public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) {
- }
-
- /**
- * Callback triggered in response to {@link AdvertisingSet#setAdvertisingParameters}
- * indicating result of the operation.
- *
- * @param advertisingSet The advertising set.
- * @param txPower tx power that will be used for this set.
- * @param status Status of the operation.
- */
- public void onAdvertisingParametersUpdated(AdvertisingSet advertisingSet,
- int txPower, int status) {
- }
-
- /**
- * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingParameters}
- * indicating result of the operation.
- *
- * @param advertisingSet The advertising set.
- * @param status Status of the operation.
- */
- public void onPeriodicAdvertisingParametersUpdated(AdvertisingSet advertisingSet, int status) {
- }
-
- /**
- * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingData}
- * indicating result of the operation.
- *
- * @param advertisingSet The advertising set.
- * @param status Status of the operation.
- */
- public void onPeriodicAdvertisingDataSet(AdvertisingSet advertisingSet,
- int status) {
- }
-
- /**
- * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingEnabled}
- * indicating result of the operation.
- *
- * @param advertisingSet The advertising set.
- * @param status Status of the operation.
- */
- public void onPeriodicAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable,
- int status) {
- }
-
- /**
- * Callback triggered in response to {@link AdvertisingSet#getOwnAddress()}
- * indicating result of the operation.
- *
- * @param advertisingSet The advertising set.
- * @param addressType type of address.
- * @param address advertising set bluetooth address.
- * @hide
- */
- public void onOwnAddressRead(AdvertisingSet advertisingSet, int addressType, String address) {
- }
-}
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
deleted file mode 100644
index 5c8fae6..0000000
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * The {@link AdvertisingSetParameters} provide a way to adjust advertising
- * preferences for each
- * Bluetooth LE advertising set. Use {@link AdvertisingSetParameters.Builder} to
- * create an
- * instance of this class.
- */
-public final class AdvertisingSetParameters implements Parcelable {
-
- /**
- * Advertise on low frequency, around every 1000ms. This is the default and
- * preferred advertising mode as it consumes the least power.
- */
- public static final int INTERVAL_HIGH = 1600;
-
- /**
- * Advertise on medium frequency, around every 250ms. This is balanced
- * between advertising frequency and power consumption.
- */
- public static final int INTERVAL_MEDIUM = 400;
-
- /**
- * Perform high frequency, low latency advertising, around every 100ms. This
- * has the highest power consumption and should not be used for continuous
- * background advertising.
- */
- public static final int INTERVAL_LOW = 160;
-
- /**
- * Minimum value for advertising interval.
- */
- public static final int INTERVAL_MIN = 160;
-
- /**
- * Maximum value for advertising interval.
- */
- public static final int INTERVAL_MAX = 16777215;
-
- /**
- * Advertise using the lowest transmission (TX) power level. Low transmission
- * power can be used to restrict the visibility range of advertising packets.
- */
- public static final int TX_POWER_ULTRA_LOW = -21;
-
- /**
- * Advertise using low TX power level.
- */
- public static final int TX_POWER_LOW = -15;
-
- /**
- * Advertise using medium TX power level.
- */
- public static final int TX_POWER_MEDIUM = -7;
-
- /**
- * Advertise using high TX power level. This corresponds to largest visibility
- * range of the advertising packet.
- */
- public static final int TX_POWER_HIGH = 1;
-
- /**
- * Minimum value for TX power.
- */
- public static final int TX_POWER_MIN = -127;
-
- /**
- * Maximum value for TX power.
- */
- public static final int TX_POWER_MAX = 1;
-
- /**
- * The maximum limited advertisement duration as specified by the Bluetooth
- * SIG
- */
- private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000;
-
- /** @hide */
- @IntDef(prefix = "ADDRESS_TYPE_", value = {
- ADDRESS_TYPE_DEFAULT,
- ADDRESS_TYPE_PUBLIC,
- ADDRESS_TYPE_RANDOM
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface AddressTypeStatus {}
-
- /**
- * Advertise own address type that corresponds privacy settings of the device.
- *
- * @hide
- */
- @SystemApi
- public static final int ADDRESS_TYPE_DEFAULT = -1;
-
- /**
- * Advertise own public address type.
- *
- * @hide
- */
- @SystemApi
- public static final int ADDRESS_TYPE_PUBLIC = 0;
-
- /**
- * Generate and adverise own resolvable private address.
- *
- * @hide
- */
- @SystemApi
- public static final int ADDRESS_TYPE_RANDOM = 1;
-
- private final boolean mIsLegacy;
- private final boolean mIsAnonymous;
- private final boolean mIncludeTxPower;
- private final int mPrimaryPhy;
- private final int mSecondaryPhy;
- private final boolean mConnectable;
- private final boolean mScannable;
- private final int mInterval;
- private final int mTxPowerLevel;
- private final int mOwnAddressType;
-
- private AdvertisingSetParameters(boolean connectable, boolean scannable, boolean isLegacy,
- boolean isAnonymous, boolean includeTxPower,
- int primaryPhy, int secondaryPhy,
- int interval, int txPowerLevel, @AddressTypeStatus int ownAddressType) {
- mConnectable = connectable;
- mScannable = scannable;
- mIsLegacy = isLegacy;
- mIsAnonymous = isAnonymous;
- mIncludeTxPower = includeTxPower;
- mPrimaryPhy = primaryPhy;
- mSecondaryPhy = secondaryPhy;
- mInterval = interval;
- mTxPowerLevel = txPowerLevel;
- mOwnAddressType = ownAddressType;
- }
-
- private AdvertisingSetParameters(Parcel in) {
- mConnectable = in.readInt() != 0;
- mScannable = in.readInt() != 0;
- mIsLegacy = in.readInt() != 0;
- mIsAnonymous = in.readInt() != 0;
- mIncludeTxPower = in.readInt() != 0;
- mPrimaryPhy = in.readInt();
- mSecondaryPhy = in.readInt();
- mInterval = in.readInt();
- mTxPowerLevel = in.readInt();
- mOwnAddressType = in.readInt();
- }
-
- /**
- * Returns whether the advertisement will be connectable.
- */
- public boolean isConnectable() {
- return mConnectable;
- }
-
- /**
- * Returns whether the advertisement will be scannable.
- */
- public boolean isScannable() {
- return mScannable;
- }
-
- /**
- * Returns whether the legacy advertisement will be used.
- */
- public boolean isLegacy() {
- return mIsLegacy;
- }
-
- /**
- * Returns whether the advertisement will be anonymous.
- */
- public boolean isAnonymous() {
- return mIsAnonymous;
- }
-
- /**
- * Returns whether the TX Power will be included.
- */
- public boolean includeTxPower() {
- return mIncludeTxPower;
- }
-
- /**
- * Returns the primary advertising phy.
- */
- public int getPrimaryPhy() {
- return mPrimaryPhy;
- }
-
- /**
- * Returns the secondary advertising phy.
- */
- public int getSecondaryPhy() {
- return mSecondaryPhy;
- }
-
- /**
- * Returns the advertising interval.
- */
- public int getInterval() {
- return mInterval;
- }
-
- /**
- * Returns the TX power level for advertising.
- */
- public int getTxPowerLevel() {
- return mTxPowerLevel;
- }
-
- /**
- * @return the own address type for advertising
- *
- * @hide
- */
- @SystemApi
- public @AddressTypeStatus int getOwnAddressType() {
- return mOwnAddressType;
- }
-
- @Override
- public String toString() {
- return "AdvertisingSetParameters [connectable=" + mConnectable
- + ", isLegacy=" + mIsLegacy
- + ", isAnonymous=" + mIsAnonymous
- + ", includeTxPower=" + mIncludeTxPower
- + ", primaryPhy=" + mPrimaryPhy
- + ", secondaryPhy=" + mSecondaryPhy
- + ", interval=" + mInterval
- + ", txPowerLevel=" + mTxPowerLevel
- + ", ownAddressType=" + mOwnAddressType + "]";
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mConnectable ? 1 : 0);
- dest.writeInt(mScannable ? 1 : 0);
- dest.writeInt(mIsLegacy ? 1 : 0);
- dest.writeInt(mIsAnonymous ? 1 : 0);
- dest.writeInt(mIncludeTxPower ? 1 : 0);
- dest.writeInt(mPrimaryPhy);
- dest.writeInt(mSecondaryPhy);
- dest.writeInt(mInterval);
- dest.writeInt(mTxPowerLevel);
- dest.writeInt(mOwnAddressType);
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<AdvertisingSetParameters> CREATOR =
- new Creator<AdvertisingSetParameters>() {
- @Override
- public AdvertisingSetParameters[] newArray(int size) {
- return new AdvertisingSetParameters[size];
- }
-
- @Override
- public AdvertisingSetParameters createFromParcel(Parcel in) {
- return new AdvertisingSetParameters(in);
- }
- };
-
- /**
- * Builder class for {@link AdvertisingSetParameters}.
- */
- public static final class Builder {
- private boolean mConnectable = false;
- private boolean mScannable = false;
- private boolean mIsLegacy = false;
- private boolean mIsAnonymous = false;
- private boolean mIncludeTxPower = false;
- private int mPrimaryPhy = BluetoothDevice.PHY_LE_1M;
- private int mSecondaryPhy = BluetoothDevice.PHY_LE_1M;
- private int mInterval = INTERVAL_LOW;
- private int mTxPowerLevel = TX_POWER_MEDIUM;
- private int mOwnAddressType = ADDRESS_TYPE_DEFAULT;
-
- /**
- * Set whether the advertisement type should be connectable or
- * non-connectable.
- * Legacy advertisements can be both connectable and scannable. Non-legacy
- * advertisements can be only scannable or only connectable.
- *
- * @param connectable Controls whether the advertisement type will be connectable (true) or
- * non-connectable (false).
- */
- public Builder setConnectable(boolean connectable) {
- mConnectable = connectable;
- return this;
- }
-
- /**
- * Set whether the advertisement type should be scannable.
- * Legacy advertisements can be both connectable and scannable. Non-legacy
- * advertisements can be only scannable or only connectable.
- *
- * @param scannable Controls whether the advertisement type will be scannable (true) or
- * non-scannable (false).
- */
- public Builder setScannable(boolean scannable) {
- mScannable = scannable;
- return this;
- }
-
- /**
- * When set to true, advertising set will advertise 4.x Spec compliant
- * advertisements.
- *
- * @param isLegacy whether legacy advertising mode should be used.
- */
- public Builder setLegacyMode(boolean isLegacy) {
- mIsLegacy = isLegacy;
- return this;
- }
-
- /**
- * Set whether advertiser address should be ommited from all packets. If this
- * mode is used, periodic advertising can't be enabled for this set.
- *
- * This is used only if legacy mode is not used.
- *
- * @param isAnonymous whether anonymous advertising should be used.
- */
- public Builder setAnonymous(boolean isAnonymous) {
- mIsAnonymous = isAnonymous;
- return this;
- }
-
- /**
- * Set whether TX power should be included in the extended header.
- *
- * This is used only if legacy mode is not used.
- *
- * @param includeTxPower whether TX power should be included in extended header
- */
- public Builder setIncludeTxPower(boolean includeTxPower) {
- mIncludeTxPower = includeTxPower;
- return this;
- }
-
- /**
- * Set the primary physical channel used for this advertising set.
- *
- * This is used only if legacy mode is not used.
- *
- * Use {@link BluetoothAdapter#isLeCodedPhySupported} to determine if LE Coded PHY is
- * supported on this device.
- *
- * @param primaryPhy Primary advertising physical channel, can only be {@link
- * BluetoothDevice#PHY_LE_1M} or {@link BluetoothDevice#PHY_LE_CODED}.
- * @throws IllegalArgumentException If the primaryPhy is invalid.
- */
- public Builder setPrimaryPhy(int primaryPhy) {
- if (primaryPhy != BluetoothDevice.PHY_LE_1M
- && primaryPhy != BluetoothDevice.PHY_LE_CODED) {
- throw new IllegalArgumentException("bad primaryPhy " + primaryPhy);
- }
- mPrimaryPhy = primaryPhy;
- return this;
- }
-
- /**
- * Set the secondary physical channel used for this advertising set.
- *
- * This is used only if legacy mode is not used.
- *
- * Use {@link BluetoothAdapter#isLeCodedPhySupported} and
- * {@link BluetoothAdapter#isLe2MPhySupported} to determine if LE Coded PHY or 2M PHY is
- * supported on this device.
- *
- * @param secondaryPhy Secondary advertising physical channel, can only be one of {@link
- * BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M} or {@link
- * BluetoothDevice#PHY_LE_CODED}.
- * @throws IllegalArgumentException If the secondaryPhy is invalid.
- */
- public Builder setSecondaryPhy(int secondaryPhy) {
- if (secondaryPhy != BluetoothDevice.PHY_LE_1M
- && secondaryPhy != BluetoothDevice.PHY_LE_2M
- && secondaryPhy != BluetoothDevice.PHY_LE_CODED) {
- throw new IllegalArgumentException("bad secondaryPhy " + secondaryPhy);
- }
- mSecondaryPhy = secondaryPhy;
- return this;
- }
-
- /**
- * Set advertising interval.
- *
- * @param interval Bluetooth LE Advertising interval, in 0.625ms unit. Valid range is from
- * 160 (100ms) to 16777215 (10,485.759375 s). Recommended values are: {@link
- * AdvertisingSetParameters#INTERVAL_LOW}, {@link AdvertisingSetParameters#INTERVAL_MEDIUM},
- * or {@link AdvertisingSetParameters#INTERVAL_HIGH}.
- * @throws IllegalArgumentException If the interval is invalid.
- */
- public Builder setInterval(int interval) {
- if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) {
- throw new IllegalArgumentException("unknown interval " + interval);
- }
- mInterval = interval;
- return this;
- }
-
- /**
- * Set the transmission power level for the advertising.
- *
- * @param txPowerLevel Transmission power of Bluetooth LE Advertising, in dBm. The valid
- * range is [-127, 1] Recommended values are:
- * {@link AdvertisingSetParameters#TX_POWER_ULTRA_LOW},
- * {@link AdvertisingSetParameters#TX_POWER_LOW},
- * {@link AdvertisingSetParameters#TX_POWER_MEDIUM},
- * or {@link AdvertisingSetParameters#TX_POWER_HIGH}.
- * @throws IllegalArgumentException If the {@code txPowerLevel} is invalid.
- */
- public Builder setTxPowerLevel(int txPowerLevel) {
- if (txPowerLevel < TX_POWER_MIN || txPowerLevel > TX_POWER_MAX) {
- throw new IllegalArgumentException("unknown txPowerLevel " + txPowerLevel);
- }
- mTxPowerLevel = txPowerLevel;
- return this;
- }
-
- /**
- * Set own address type for advertising to control public or privacy mode. If used to set
- * address type anything other than {@link AdvertisingSetParameters#ADDRESS_TYPE_DEFAULT},
- * then it will require BLUETOOTH_PRIVILEGED permission and will be checked at the
- * time of starting advertising.
- *
- * @throws IllegalArgumentException If the {@code ownAddressType} is invalid
- *
- * @hide
- */
- @SystemApi
- public @NonNull Builder setOwnAddressType(@AddressTypeStatus int ownAddressType) {
- if (ownAddressType < AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT
- || ownAddressType > AdvertisingSetParameters.ADDRESS_TYPE_RANDOM) {
- throw new IllegalArgumentException("unknown address type " + ownAddressType);
- }
- mOwnAddressType = ownAddressType;
- return this;
- }
-
- /**
- * Build the {@link AdvertisingSetParameters} object.
- *
- * @throws IllegalStateException if invalid combination of parameters is used.
- */
- public AdvertisingSetParameters build() {
- if (mIsLegacy) {
- if (mIsAnonymous) {
- throw new IllegalArgumentException("Legacy advertising can't be anonymous");
- }
-
- if (mConnectable && !mScannable) {
- throw new IllegalStateException(
- "Legacy advertisement can't be connectable and non-scannable");
- }
-
- if (mIncludeTxPower) {
- throw new IllegalStateException(
- "Legacy advertising can't include TX power level in header");
- }
- } else {
- if (mConnectable && mScannable) {
- throw new IllegalStateException(
- "Advertising can't be both connectable and scannable");
- }
-
- if (mIsAnonymous && mConnectable) {
- throw new IllegalStateException(
- "Advertising can't be both connectable and anonymous");
- }
- }
-
- return new AdvertisingSetParameters(mConnectable, mScannable, mIsLegacy, mIsAnonymous,
- mIncludeTxPower, mPrimaryPhy, mSecondaryPhy, mInterval, mTxPowerLevel,
- mOwnAddressType);
- }
- }
-}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
deleted file mode 100644
index 879dcee..0000000
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothManager;
-import android.bluetooth.annotations.RequiresBluetoothAdvertisePermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.content.AttributionSource;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * This class provides a way to perform Bluetooth LE advertise operations, such as starting and
- * stopping advertising. An advertiser can broadcast up to 31 bytes of advertisement data
- * represented by {@link AdvertiseData}.
- * <p>
- * To get an instance of {@link BluetoothLeAdvertiser}, call the
- * {@link BluetoothAdapter#getBluetoothLeAdvertiser()} method.
- *
- * @see AdvertiseData
- */
-public final class BluetoothLeAdvertiser {
-
- private static final String TAG = "BluetoothLeAdvertiser";
-
- private static final int MAX_ADVERTISING_DATA_BYTES = 1650;
- private static final int MAX_LEGACY_ADVERTISING_DATA_BYTES = 31;
- // Each fields need one byte for field length and another byte for field type.
- private static final int OVERHEAD_BYTES_PER_FIELD = 2;
- // Flags field will be set by system.
- private static final int FLAGS_FIELD_BYTES = 3;
- private static final int MANUFACTURER_SPECIFIC_DATA_LENGTH = 2;
-
- private final BluetoothAdapter mBluetoothAdapter;
- private final IBluetoothManager mBluetoothManager;
- private final AttributionSource mAttributionSource;
-
- private final Handler mHandler;
- private final Map<AdvertiseCallback, AdvertisingSetCallback>
- mLegacyAdvertisers = new HashMap<>();
- private final Map<AdvertisingSetCallback, IAdvertisingSetCallback>
- mCallbackWrappers = Collections.synchronizedMap(new HashMap<>());
- private final Map<Integer, AdvertisingSet>
- mAdvertisingSets = Collections.synchronizedMap(new HashMap<>());
-
- /**
- * Use BluetoothAdapter.getLeAdvertiser() instead.
- *
- * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management
- * @hide
- */
- public BluetoothLeAdvertiser(BluetoothAdapter bluetoothAdapter) {
- mBluetoothAdapter = Objects.requireNonNull(bluetoothAdapter);
- mBluetoothManager = mBluetoothAdapter.getBluetoothManager();
- mAttributionSource = mBluetoothAdapter.getAttributionSource();
- mHandler = new Handler(Looper.getMainLooper());
- }
-
- /**
- * Start Bluetooth LE Advertising. On success, the {@code advertiseData} will be broadcasted.
- * Returns immediately, the operation status is delivered through {@code callback}.
- *
- * @param settings Settings for Bluetooth LE advertising.
- * @param advertiseData Advertisement data to be broadcasted.
- * @param callback Callback for advertising status.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void startAdvertising(AdvertiseSettings settings,
- AdvertiseData advertiseData, final AdvertiseCallback callback) {
- startAdvertising(settings, advertiseData, null, callback);
- }
-
- /**
- * Start Bluetooth LE Advertising. The {@code advertiseData} will be broadcasted if the
- * operation succeeds. The {@code scanResponse} is returned when a scanning device sends an
- * active scan request. This method returns immediately, the operation status is delivered
- * through {@code callback}.
- *
- * @param settings Settings for Bluetooth LE advertising.
- * @param advertiseData Advertisement data to be advertised in advertisement packet.
- * @param scanResponse Scan response associated with the advertisement data.
- * @param callback Callback for advertising status.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void startAdvertising(AdvertiseSettings settings,
- AdvertiseData advertiseData, AdvertiseData scanResponse,
- final AdvertiseCallback callback) {
- synchronized (mLegacyAdvertisers) {
- BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
- if (callback == null) {
- throw new IllegalArgumentException("callback cannot be null");
- }
- boolean isConnectable = settings.isConnectable();
- if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES
- || totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
- postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
- return;
- }
- if (mLegacyAdvertisers.containsKey(callback)) {
- postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
- return;
- }
-
- AdvertisingSetParameters.Builder parameters = new AdvertisingSetParameters.Builder();
- parameters.setLegacyMode(true);
- parameters.setConnectable(isConnectable);
- parameters.setScannable(true); // legacy advertisements we support are always scannable
- parameters.setOwnAddressType(settings.getOwnAddressType());
- if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_POWER) {
- parameters.setInterval(1600); // 1s
- } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_BALANCED) {
- parameters.setInterval(400); // 250ms
- } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) {
- parameters.setInterval(160); // 100ms
- }
-
- if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW) {
- parameters.setTxPowerLevel(-21);
- } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_LOW) {
- parameters.setTxPowerLevel(-15);
- } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM) {
- parameters.setTxPowerLevel(-7);
- } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) {
- parameters.setTxPowerLevel(1);
- }
-
- int duration = 0;
- int timeoutMillis = settings.getTimeout();
- if (timeoutMillis > 0) {
- duration = (timeoutMillis < 10) ? 1 : timeoutMillis / 10;
- }
-
- AdvertisingSetCallback wrapped = wrapOldCallback(callback, settings);
- mLegacyAdvertisers.put(callback, wrapped);
- startAdvertisingSet(parameters.build(), advertiseData, scanResponse, null, null,
- duration, 0, wrapped);
- }
- }
-
- @SuppressLint({
- "AndroidFrameworkBluetoothPermission",
- "AndroidFrameworkRequiresPermission",
- })
- AdvertisingSetCallback wrapOldCallback(AdvertiseCallback callback, AdvertiseSettings settings) {
- return new AdvertisingSetCallback() {
- @Override
- public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower,
- int status) {
- if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
- postStartFailure(callback, status);
- return;
- }
-
- postStartSuccess(callback, settings);
- }
-
- /* Legacy advertiser is disabled on timeout */
- @Override
- public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enabled,
- int status) {
- if (enabled) {
- Log.e(TAG, "Legacy advertiser should be only disabled on timeout,"
- + " but was enabled!");
- return;
- }
-
- stopAdvertising(callback);
- }
-
- };
- }
-
- /**
- * Stop Bluetooth LE advertising. The {@code callback} must be the same one use in
- * {@link BluetoothLeAdvertiser#startAdvertising}.
- *
- * @param callback {@link AdvertiseCallback} identifies the advertising instance to stop.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void stopAdvertising(final AdvertiseCallback callback) {
- synchronized (mLegacyAdvertisers) {
- if (callback == null) {
- throw new IllegalArgumentException("callback cannot be null");
- }
- AdvertisingSetCallback wrapper = mLegacyAdvertisers.get(callback);
- if (wrapper == null) return;
-
- stopAdvertisingSet(wrapper);
-
- mLegacyAdvertisers.remove(callback);
- }
- }
-
- /**
- * Creates a new advertising set. If operation succeed, device will start advertising. This
- * method returns immediately, the operation status is delivered through
- * {@code callback.onAdvertisingSetStarted()}.
- * <p>
- *
- * @param parameters advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
- * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
- * three bytes will be added for flags.
- * @param scanResponse Scan response associated with the advertisement data. Size must not
- * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
- * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
- * not be started.
- * @param periodicData Periodic advertising data. Size must not exceed {@link
- * BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
- * @param callback Callback for advertising set.
- * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
- * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
- * feature is made when it's not supported by the controller.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void startAdvertisingSet(AdvertisingSetParameters parameters,
- AdvertiseData advertiseData, AdvertiseData scanResponse,
- PeriodicAdvertisingParameters periodicParameters,
- AdvertiseData periodicData, AdvertisingSetCallback callback) {
- startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
- periodicData, 0, 0, callback, new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Creates a new advertising set. If operation succeed, device will start advertising. This
- * method returns immediately, the operation status is delivered through
- * {@code callback.onAdvertisingSetStarted()}.
- * <p>
- *
- * @param parameters advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
- * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
- * three bytes will be added for flags.
- * @param scanResponse Scan response associated with the advertisement data. Size must not
- * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
- * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
- * not be started.
- * @param periodicData Periodic advertising data. Size must not exceed {@link
- * BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
- * @param callback Callback for advertising set.
- * @param handler thread upon which the callbacks will be invoked.
- * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
- * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
- * feature is made when it's not supported by the controller.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void startAdvertisingSet(AdvertisingSetParameters parameters,
- AdvertiseData advertiseData, AdvertiseData scanResponse,
- PeriodicAdvertisingParameters periodicParameters,
- AdvertiseData periodicData, AdvertisingSetCallback callback,
- Handler handler) {
- startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
- periodicData, 0, 0, callback, handler);
- }
-
- /**
- * Creates a new advertising set. If operation succeed, device will start advertising. This
- * method returns immediately, the operation status is delivered through
- * {@code callback.onAdvertisingSetStarted()}.
- * <p>
- *
- * @param parameters advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
- * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
- * three bytes will be added for flags.
- * @param scanResponse Scan response associated with the advertisement data. Size must not
- * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
- * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
- * not be started.
- * @param periodicData Periodic advertising data. Size must not exceed {@link
- * BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
- * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535
- * (655,350 ms). 0 means advertising should continue until stopped.
- * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
- * controller shall attempt to send prior to terminating the extended advertising, even if the
- * duration has not expired. Valid range is from 1 to 255. 0 means no maximum.
- * @param callback Callback for advertising set.
- * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
- * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
- * feature is made when it's not supported by the controller.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void startAdvertisingSet(AdvertisingSetParameters parameters,
- AdvertiseData advertiseData, AdvertiseData scanResponse,
- PeriodicAdvertisingParameters periodicParameters,
- AdvertiseData periodicData, int duration,
- int maxExtendedAdvertisingEvents,
- AdvertisingSetCallback callback) {
- startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
- periodicData, duration, maxExtendedAdvertisingEvents, callback,
- new Handler(Looper.getMainLooper()));
- }
-
- /**
- * Creates a new advertising set. If operation succeed, device will start advertising. This
- * method returns immediately, the operation status is delivered through
- * {@code callback.onAdvertisingSetStarted()}.
- * <p>
- *
- * @param parameters Advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
- * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
- * three bytes will be added for flags.
- * @param scanResponse Scan response associated with the advertisement data. Size must not
- * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
- * @param periodicParameters Periodic advertisng parameters. If null, periodic advertising will
- * not be started.
- * @param periodicData Periodic advertising data. Size must not exceed {@link
- * BluetoothAdapter#getLeMaximumAdvertisingDataLength}
- * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535
- * (655,350 ms). 0 means advertising should continue until stopped.
- * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
- * controller shall attempt to send prior to terminating the extended advertising, even if the
- * duration has not expired. Valid range is from 1 to 255. 0 means no maximum.
- * @param callback Callback for advertising set.
- * @param handler Thread upon which the callbacks will be invoked.
- * @throws IllegalArgumentException When any of the data parameter exceed the maximum allowable
- * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
- * feature is made when it's not supported by the controller, or when
- * maxExtendedAdvertisingEvents is used on a controller that doesn't support the LE Extended
- * Advertising
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void startAdvertisingSet(AdvertisingSetParameters parameters,
- AdvertiseData advertiseData, AdvertiseData scanResponse,
- PeriodicAdvertisingParameters periodicParameters,
- AdvertiseData periodicData, int duration,
- int maxExtendedAdvertisingEvents, AdvertisingSetCallback callback,
- Handler handler) {
- BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
- if (callback == null) {
- throw new IllegalArgumentException("callback cannot be null");
- }
-
- boolean isConnectable = parameters.isConnectable();
- if (parameters.isLegacy()) {
- if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
- throw new IllegalArgumentException("Legacy advertising data too big");
- }
-
- if (totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
- throw new IllegalArgumentException("Legacy scan response data too big");
- }
- } else {
- boolean supportCodedPhy = mBluetoothAdapter.isLeCodedPhySupported();
- boolean support2MPhy = mBluetoothAdapter.isLe2MPhySupported();
- int pphy = parameters.getPrimaryPhy();
- int sphy = parameters.getSecondaryPhy();
- if (pphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy) {
- throw new IllegalArgumentException("Unsupported primary PHY selected");
- }
-
- if ((sphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy)
- || (sphy == BluetoothDevice.PHY_LE_2M && !support2MPhy)) {
- throw new IllegalArgumentException("Unsupported secondary PHY selected");
- }
-
- int maxData = mBluetoothAdapter.getLeMaximumAdvertisingDataLength();
- if (totalBytes(advertiseData, isConnectable) > maxData) {
- throw new IllegalArgumentException("Advertising data too big");
- }
-
- if (totalBytes(scanResponse, false) > maxData) {
- throw new IllegalArgumentException("Scan response data too big");
- }
-
- if (totalBytes(periodicData, false) > maxData) {
- throw new IllegalArgumentException("Periodic advertising data too big");
- }
-
- boolean supportPeriodic = mBluetoothAdapter.isLePeriodicAdvertisingSupported();
- if (periodicParameters != null && !supportPeriodic) {
- throw new IllegalArgumentException(
- "Controller does not support LE Periodic Advertising");
- }
- }
-
- if (maxExtendedAdvertisingEvents < 0 || maxExtendedAdvertisingEvents > 255) {
- throw new IllegalArgumentException(
- "maxExtendedAdvertisingEvents out of range: " + maxExtendedAdvertisingEvents);
- }
-
- if (maxExtendedAdvertisingEvents != 0
- && !mBluetoothAdapter.isLePeriodicAdvertisingSupported()) {
- throw new IllegalArgumentException(
- "Can't use maxExtendedAdvertisingEvents with controller that don't support "
- + "LE Extended Advertising");
- }
-
- if (duration < 0 || duration > 65535) {
- throw new IllegalArgumentException("duration out of range: " + duration);
- }
-
- IBluetoothGatt gatt;
- try {
- gatt = mBluetoothManager.getBluetoothGatt();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get Bluetooth GATT - ", e);
- postStartSetFailure(handler, callback,
- AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
- return;
- }
-
- if (gatt == null) {
- Log.e(TAG, "Bluetooth GATT is null");
- postStartSetFailure(handler, callback,
- AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
- return;
- }
-
- IAdvertisingSetCallback wrapped = wrap(callback, handler);
- if (mCallbackWrappers.putIfAbsent(callback, wrapped) != null) {
- throw new IllegalArgumentException(
- "callback instance already associated with advertising");
- }
-
- try {
- gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
- periodicData, duration, maxExtendedAdvertisingEvents, wrapped,
- mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to start advertising set - ", e);
- postStartSetFailure(handler, callback,
- AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
- return;
- }
- }
-
- /**
- * Used to dispose of a {@link AdvertisingSet} object, obtained with {@link
- * BluetoothLeAdvertiser#startAdvertisingSet}.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- public void stopAdvertisingSet(AdvertisingSetCallback callback) {
- if (callback == null) {
- throw new IllegalArgumentException("callback cannot be null");
- }
-
- IAdvertisingSetCallback wrapped = mCallbackWrappers.remove(callback);
- if (wrapped == null) {
- return;
- }
-
- IBluetoothGatt gatt;
- try {
- gatt = mBluetoothManager.getBluetoothGatt();
- gatt.stopAdvertisingSet(wrapped, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to stop advertising - ", e);
- }
- }
-
- /**
- * Cleans up advertisers. Should be called when bluetooth is down.
- *
- * @hide
- */
- @RequiresNoPermission
- public void cleanup() {
- mLegacyAdvertisers.clear();
- mCallbackWrappers.clear();
- mAdvertisingSets.clear();
- }
-
- // Compute the size of advertisement data or scan resp
- @RequiresBluetoothAdvertisePermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
- private int totalBytes(AdvertiseData data, boolean isFlagsIncluded) {
- if (data == null) return 0;
- // Flags field is omitted if the advertising is not connectable.
- int size = (isFlagsIncluded) ? FLAGS_FIELD_BYTES : 0;
- if (data.getServiceUuids() != null) {
- int num16BitUuids = 0;
- int num32BitUuids = 0;
- int num128BitUuids = 0;
- for (ParcelUuid uuid : data.getServiceUuids()) {
- if (BluetoothUuid.is16BitUuid(uuid)) {
- ++num16BitUuids;
- } else if (BluetoothUuid.is32BitUuid(uuid)) {
- ++num32BitUuids;
- } else {
- ++num128BitUuids;
- }
- }
- // 16 bit service uuids are grouped into one field when doing advertising.
- if (num16BitUuids != 0) {
- size += OVERHEAD_BYTES_PER_FIELD + num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT;
- }
- // 32 bit service uuids are grouped into one field when doing advertising.
- if (num32BitUuids != 0) {
- size += OVERHEAD_BYTES_PER_FIELD + num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT;
- }
- // 128 bit service uuids are grouped into one field when doing advertising.
- if (num128BitUuids != 0) {
- size += OVERHEAD_BYTES_PER_FIELD
- + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
- }
- }
- if (data.getServiceSolicitationUuids() != null) {
- int num16BitUuids = 0;
- int num32BitUuids = 0;
- int num128BitUuids = 0;
- for (ParcelUuid uuid : data.getServiceSolicitationUuids()) {
- if (BluetoothUuid.is16BitUuid(uuid)) {
- ++num16BitUuids;
- } else if (BluetoothUuid.is32BitUuid(uuid)) {
- ++num32BitUuids;
- } else {
- ++num128BitUuids;
- }
- }
- // 16 bit service uuids are grouped into one field when doing advertising.
- if (num16BitUuids != 0) {
- size += OVERHEAD_BYTES_PER_FIELD + num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT;
- }
- // 32 bit service uuids are grouped into one field when doing advertising.
- if (num32BitUuids != 0) {
- size += OVERHEAD_BYTES_PER_FIELD + num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT;
- }
- // 128 bit service uuids are grouped into one field when doing advertising.
- if (num128BitUuids != 0) {
- size += OVERHEAD_BYTES_PER_FIELD
- + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
- }
- }
- for (TransportDiscoveryData transportDiscoveryData : data.getTransportDiscoveryData()) {
- size += OVERHEAD_BYTES_PER_FIELD + transportDiscoveryData.totalBytes();
- }
- for (ParcelUuid uuid : data.getServiceData().keySet()) {
- int uuidLen = BluetoothUuid.uuidToBytes(uuid).length;
- size += OVERHEAD_BYTES_PER_FIELD + uuidLen
- + byteLength(data.getServiceData().get(uuid));
- }
- for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) {
- size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH
- + byteLength(data.getManufacturerSpecificData().valueAt(i));
- }
- if (data.getIncludeTxPowerLevel()) {
- size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte.
- }
- if (data.getIncludeDeviceName()) {
- final int length = mBluetoothAdapter.getNameLengthForAdvertise();
- if (length >= 0) {
- size += OVERHEAD_BYTES_PER_FIELD + length;
- }
- }
- return size;
- }
-
- private int byteLength(byte[] array) {
- return array == null ? 0 : array.length;
- }
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- IAdvertisingSetCallback wrap(AdvertisingSetCallback callback, Handler handler) {
- return new IAdvertisingSetCallback.Stub() {
- @Override
- public void onAdvertisingSetStarted(int advertiserId, int txPower, int status) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
- callback.onAdvertisingSetStarted(null, 0, status);
- mCallbackWrappers.remove(callback);
- return;
- }
-
- AdvertisingSet advertisingSet = new AdvertisingSet(
- advertiserId, mBluetoothManager, mAttributionSource);
- mAdvertisingSets.put(advertiserId, advertisingSet);
- callback.onAdvertisingSetStarted(advertisingSet, txPower, status);
- }
- });
- }
-
- @Override
- public void onOwnAddressRead(int advertiserId, int addressType, String address) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
- callback.onOwnAddressRead(advertisingSet, addressType, address);
- }
- });
- }
-
- @Override
- public void onAdvertisingSetStopped(int advertiserId) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
- callback.onAdvertisingSetStopped(advertisingSet);
- mAdvertisingSets.remove(advertiserId);
- mCallbackWrappers.remove(callback);
- }
- });
- }
-
- @Override
- public void onAdvertisingEnabled(int advertiserId, boolean enabled, int status) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
- callback.onAdvertisingEnabled(advertisingSet, enabled, status);
- }
- });
- }
-
- @Override
- public void onAdvertisingDataSet(int advertiserId, int status) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
- callback.onAdvertisingDataSet(advertisingSet, status);
- }
- });
- }
-
- @Override
- public void onScanResponseDataSet(int advertiserId, int status) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
- callback.onScanResponseDataSet(advertisingSet, status);
- }
- });
- }
-
- @Override
- public void onAdvertisingParametersUpdated(int advertiserId, int txPower, int status) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
- callback.onAdvertisingParametersUpdated(advertisingSet, txPower, status);
- }
- });
- }
-
- @Override
- public void onPeriodicAdvertisingParametersUpdated(int advertiserId, int status) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
- callback.onPeriodicAdvertisingParametersUpdated(advertisingSet, status);
- }
- });
- }
-
- @Override
- public void onPeriodicAdvertisingDataSet(int advertiserId, int status) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
- callback.onPeriodicAdvertisingDataSet(advertisingSet, status);
- }
- });
- }
-
- @Override
- public void onPeriodicAdvertisingEnabled(int advertiserId, boolean enable, int status) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
- callback.onPeriodicAdvertisingEnabled(advertisingSet, enable, status);
- }
- });
- }
- };
- }
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private void postStartSetFailure(Handler handler, final AdvertisingSetCallback callback,
- final int error) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- callback.onAdvertisingSetStarted(null, 0, error);
- }
- });
- }
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private void postStartFailure(final AdvertiseCallback callback, final int error) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- callback.onStartFailure(error);
- }
- });
- }
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private void postStartSuccess(final AdvertiseCallback callback,
- final AdvertiseSettings settings) {
- mHandler.post(new Runnable() {
-
- @Override
- public void run() {
- callback.onStartSuccess(settings);
- }
- });
- }
-}
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
deleted file mode 100644
index 540e5a7..0000000
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.app.PendingIntent;
-import android.bluetooth.Attributable;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothManager;
-import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
-import android.bluetooth.annotations.RequiresBluetoothScanPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.content.AttributionSource;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.WorkSource;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * This class provides methods to perform scan related operations for Bluetooth LE devices. An
- * application can scan for a particular type of Bluetooth LE devices using {@link ScanFilter}. It
- * can also request different types of callbacks for delivering the result.
- * <p>
- * Use {@link BluetoothAdapter#getBluetoothLeScanner()} to get an instance of
- * {@link BluetoothLeScanner}.
- *
- * @see ScanFilter
- */
-public final class BluetoothLeScanner {
-
- private static final String TAG = "BluetoothLeScanner";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- /**
- * Extra containing a list of ScanResults. It can have one or more results if there was no
- * error. In case of error, {@link #EXTRA_ERROR_CODE} will contain the error code and this
- * extra will not be available.
- */
- public static final String EXTRA_LIST_SCAN_RESULT =
- "android.bluetooth.le.extra.LIST_SCAN_RESULT";
-
- /**
- * Optional extra indicating the error code, if any. The error code will be one of the
- * SCAN_FAILED_* codes in {@link ScanCallback}.
- */
- public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
-
- /**
- * Optional extra indicating the callback type, which will be one of
- * CALLBACK_TYPE_* constants in {@link ScanSettings}.
- *
- * @see ScanCallback#onScanResult(int, ScanResult)
- */
- public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
-
- private final BluetoothAdapter mBluetoothAdapter;
- private final IBluetoothManager mBluetoothManager;
- private final AttributionSource mAttributionSource;
-
- private final Handler mHandler;
- private final Map<ScanCallback, BleScanCallbackWrapper> mLeScanClients;
-
- /**
- * Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead.
- *
- * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management.
- * @param opPackageName The opPackageName of the context this object was created from
- * @param featureId The featureId of the context this object was created from
- * @hide
- */
- public BluetoothLeScanner(BluetoothAdapter bluetoothAdapter) {
- mBluetoothAdapter = Objects.requireNonNull(bluetoothAdapter);
- mBluetoothManager = mBluetoothAdapter.getBluetoothManager();
- mAttributionSource = mBluetoothAdapter.getAttributionSource();
- mHandler = new Handler(Looper.getMainLooper());
- mLeScanClients = new HashMap<ScanCallback, BleScanCallbackWrapper>();
- }
-
- /**
- * Start Bluetooth LE scan with default parameters and no filters. The scan results will be
- * delivered through {@code callback}. For unfiltered scans, scanning is stopped on screen
- * off to save power. Scanning is resumed when screen is turned on again. To avoid this, use
- * {@link #startScan(List, ScanSettings, ScanCallback)} with desired {@link ScanFilter}.
- * <p>
- * An app must have
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission
- * in order to get results. An App targeting Android Q or later must have
- * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
- * in order to get results.
- *
- * @param callback Callback used to deliver scan results.
- * @throws IllegalArgumentException If {@code callback} is null.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void startScan(final ScanCallback callback) {
- startScan(null, new ScanSettings.Builder().build(), callback);
- }
-
- /**
- * Start Bluetooth LE scan. The scan results will be delivered through {@code callback}.
- * For unfiltered scans, scanning is stopped on screen off to save power. Scanning is
- * resumed when screen is turned on again. To avoid this, do filetered scanning by
- * using proper {@link ScanFilter}.
- * <p>
- * An app must have
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission
- * in order to get results. An App targeting Android Q or later must have
- * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
- * in order to get results.
- *
- * @param filters {@link ScanFilter}s for finding exact BLE devices.
- * @param settings Settings for the scan.
- * @param callback Callback used to deliver scan results.
- * @throws IllegalArgumentException If {@code settings} or {@code callback} is null.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void startScan(List<ScanFilter> filters, ScanSettings settings,
- final ScanCallback callback) {
- startScan(filters, settings, null, callback, /*callbackIntent=*/ null);
- }
-
- /**
- * Start Bluetooth LE scan using a {@link PendingIntent}. The scan results will be delivered via
- * the PendingIntent. Use this method of scanning if your process is not always running and it
- * should be started when scan results are available.
- * <p>
- * An app must have
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission
- * in order to get results. An App targeting Android Q or later must have
- * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
- * in order to get results.
- * <p>
- * When the PendingIntent is delivered, the Intent passed to the receiver or activity
- * will contain one or more of the extras {@link #EXTRA_CALLBACK_TYPE},
- * {@link #EXTRA_ERROR_CODE} and {@link #EXTRA_LIST_SCAN_RESULT} to indicate the result of
- * the scan.
- *
- * @param filters Optional list of ScanFilters for finding exact BLE devices.
- * @param settings Optional settings for the scan.
- * @param callbackIntent The PendingIntent to deliver the result to.
- * @return Returns 0 for success or an error code from {@link ScanCallback} if the scan request
- * could not be sent.
- * @see #stopScan(PendingIntent)
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public int startScan(@Nullable List<ScanFilter> filters, @Nullable ScanSettings settings,
- @NonNull PendingIntent callbackIntent) {
- return startScan(filters,
- settings != null ? settings : new ScanSettings.Builder().build(),
- null, null, callbackIntent);
- }
-
- /**
- * Start Bluetooth LE scan. Same as {@link #startScan(ScanCallback)} but allows the caller to
- * specify on behalf of which application(s) the work is being done.
- *
- * @param workSource {@link WorkSource} identifying the application(s) for which to blame for
- * the scan.
- * @param callback Callback used to deliver scan results.
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_SCAN,
- android.Manifest.permission.UPDATE_DEVICE_STATS
- })
- public void startScanFromSource(final WorkSource workSource, final ScanCallback callback) {
- startScanFromSource(null, new ScanSettings.Builder().build(), workSource, callback);
- }
-
- /**
- * Start Bluetooth LE scan. Same as {@link #startScan(List, ScanSettings, ScanCallback)} but
- * allows the caller to specify on behalf of which application(s) the work is being done.
- *
- * @param filters {@link ScanFilter}s for finding exact BLE devices.
- * @param settings Settings for the scan.
- * @param workSource {@link WorkSource} identifying the application(s) for which to blame for
- * the scan.
- * @param callback Callback used to deliver scan results.
- * @hide
- */
- @SystemApi
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_SCAN,
- android.Manifest.permission.UPDATE_DEVICE_STATS
- })
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings,
- final WorkSource workSource, final ScanCallback callback) {
- startScan(filters, settings, workSource, callback, null);
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- private int startScan(List<ScanFilter> filters, ScanSettings settings,
- final WorkSource workSource, final ScanCallback callback,
- final PendingIntent callbackIntent) {
- BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
- if (callback == null && callbackIntent == null) {
- throw new IllegalArgumentException("callback is null");
- }
- if (settings == null) {
- throw new IllegalArgumentException("settings is null");
- }
- synchronized (mLeScanClients) {
- if (callback != null && mLeScanClients.containsKey(callback)) {
- return postCallbackErrorOrReturn(callback,
- ScanCallback.SCAN_FAILED_ALREADY_STARTED);
- }
- IBluetoothGatt gatt;
- try {
- gatt = mBluetoothManager.getBluetoothGatt();
- } catch (RemoteException e) {
- gatt = null;
- }
- if (gatt == null) {
- return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
- }
- if (!isSettingsConfigAllowedForScan(settings)) {
- return postCallbackErrorOrReturn(callback,
- ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
- }
- if (!isHardwareResourcesAvailableForScan(settings)) {
- return postCallbackErrorOrReturn(callback,
- ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
- }
- if (!isSettingsAndFilterComboAllowed(settings, filters)) {
- return postCallbackErrorOrReturn(callback,
- ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
- }
- if (callback != null) {
- BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
- settings, workSource, callback);
- wrapper.startRegistration();
- } else {
- try {
- gatt.startScanForIntent(callbackIntent, settings, filters,
- mAttributionSource);
- } catch (RemoteException e) {
- return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
- }
- }
- }
- return ScanCallback.NO_ERROR;
- }
-
- /**
- * Stops an ongoing Bluetooth LE scan.
- *
- * @param callback
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void stopScan(ScanCallback callback) {
- BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
- synchronized (mLeScanClients) {
- BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback);
- if (wrapper == null) {
- if (DBG) Log.d(TAG, "could not find callback wrapper");
- return;
- }
- wrapper.stopLeScan();
- }
- }
-
- /**
- * Stops an ongoing Bluetooth LE scan started using a PendingIntent. When creating the
- * PendingIntent parameter, please do not use the FLAG_CANCEL_CURRENT flag. Otherwise, the stop
- * scan may have no effect.
- *
- * @param callbackIntent The PendingIntent that was used to start the scan.
- * @see #startScan(List, ScanSettings, PendingIntent)
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void stopScan(PendingIntent callbackIntent) {
- BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
- IBluetoothGatt gatt;
- try {
- gatt = mBluetoothManager.getBluetoothGatt();
- gatt.stopScanForIntent(callbackIntent, mAttributionSource);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Flush pending batch scan results stored in Bluetooth controller. This will return Bluetooth
- * LE scan results batched on bluetooth controller. Returns immediately, batch scan results data
- * will be delivered through the {@code callback}.
- *
- * @param callback Callback of the Bluetooth LE Scan, it has to be the same instance as the one
- * used to start scan.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void flushPendingScanResults(ScanCallback callback) {
- BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
- if (callback == null) {
- throw new IllegalArgumentException("callback cannot be null!");
- }
- synchronized (mLeScanClients) {
- BleScanCallbackWrapper wrapper = mLeScanClients.get(callback);
- if (wrapper == null) {
- return;
- }
- wrapper.flushPendingBatchResults();
- }
- }
-
- /**
- * Start truncated scan.
- *
- * @deprecated this is not used anywhere
- *
- * @hide
- */
- @Deprecated
- @SystemApi
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void startTruncatedScan(List<TruncatedFilter> truncatedFilters, ScanSettings settings,
- final ScanCallback callback) {
- int filterSize = truncatedFilters.size();
- List<ScanFilter> scanFilters = new ArrayList<ScanFilter>(filterSize);
- for (TruncatedFilter filter : truncatedFilters) {
- scanFilters.add(filter.getFilter());
- }
- startScan(scanFilters, settings, null, callback, null);
- }
-
- /**
- * Cleans up scan clients. Should be called when bluetooth is down.
- *
- * @hide
- */
- @RequiresNoPermission
- public void cleanup() {
- mLeScanClients.clear();
- }
-
- /**
- * Bluetooth GATT interface callbacks
- */
- @SuppressLint("AndroidFrameworkRequiresPermission")
- private class BleScanCallbackWrapper extends IScannerCallback.Stub {
- private static final int REGISTRATION_CALLBACK_TIMEOUT_MILLIS = 2000;
-
- private final ScanCallback mScanCallback;
- private final List<ScanFilter> mFilters;
- private final WorkSource mWorkSource;
- private ScanSettings mSettings;
- private IBluetoothGatt mBluetoothGatt;
-
- // mLeHandle 0: not registered
- // -2: registration failed because app is scanning to frequently
- // -1: scan stopped or registration failed
- // > 0: registered and scan started
- private int mScannerId;
-
- public BleScanCallbackWrapper(IBluetoothGatt bluetoothGatt,
- List<ScanFilter> filters, ScanSettings settings,
- WorkSource workSource, ScanCallback scanCallback) {
- mBluetoothGatt = bluetoothGatt;
- mFilters = filters;
- mSettings = settings;
- mWorkSource = workSource;
- mScanCallback = scanCallback;
- mScannerId = 0;
- }
-
- public void startRegistration() {
- synchronized (this) {
- // Scan stopped.
- if (mScannerId == -1 || mScannerId == -2) return;
- try {
- mBluetoothGatt.registerScanner(this, mWorkSource, mAttributionSource);
- wait(REGISTRATION_CALLBACK_TIMEOUT_MILLIS);
- } catch (InterruptedException | RemoteException e) {
- Log.e(TAG, "application registeration exception", e);
- postCallbackError(mScanCallback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
- }
- if (mScannerId > 0) {
- mLeScanClients.put(mScanCallback, this);
- } else {
- // Registration timed out or got exception, reset RscannerId to -1 so no
- // subsequent operations can proceed.
- if (mScannerId == 0) mScannerId = -1;
-
- // If scanning too frequently, don't report anything to the app.
- if (mScannerId == -2) return;
-
- postCallbackError(mScanCallback,
- ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED);
- }
- }
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void stopLeScan() {
- synchronized (this) {
- if (mScannerId <= 0) {
- Log.e(TAG, "Error state, mLeHandle: " + mScannerId);
- return;
- }
- try {
- mBluetoothGatt.stopScan(mScannerId, mAttributionSource);
- mBluetoothGatt.unregisterScanner(mScannerId, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to stop scan and unregister", e);
- }
- mScannerId = -1;
- }
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- void flushPendingBatchResults() {
- synchronized (this) {
- if (mScannerId <= 0) {
- Log.e(TAG, "Error state, mLeHandle: " + mScannerId);
- return;
- }
- try {
- mBluetoothGatt.flushPendingBatchResults(mScannerId, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get pending scan results", e);
- }
- }
- }
-
- /**
- * Application interface registered - app is ready to go
- */
- @Override
- public void onScannerRegistered(int status, int scannerId) {
- Log.d(TAG, "onScannerRegistered() - status=" + status
- + " scannerId=" + scannerId + " mScannerId=" + mScannerId);
- synchronized (this) {
- if (status == BluetoothGatt.GATT_SUCCESS) {
- try {
- if (mScannerId == -1) {
- // Registration succeeds after timeout, unregister scanner.
- mBluetoothGatt.unregisterScanner(scannerId, mAttributionSource);
- } else {
- mScannerId = scannerId;
- mBluetoothGatt.startScan(mScannerId, mSettings, mFilters,
- mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "fail to start le scan: " + e);
- mScannerId = -1;
- }
- } else if (status == ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY) {
- // applicaiton was scanning too frequently
- mScannerId = -2;
- } else {
- // registration failed
- mScannerId = -1;
- }
- notifyAll();
- }
- }
-
- /**
- * Callback reporting an LE scan result.
- *
- * @hide
- */
- @Override
- public void onScanResult(final ScanResult scanResult) {
- Attributable.setAttributionSource(scanResult, mAttributionSource);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onScanResult() - mScannerId=" + mScannerId);
- }
- if (VDBG) Log.d(TAG, "onScanResult() - " + scanResult.toString());
-
- // Check null in case the scan has been stopped
- synchronized (this) {
- if (mScannerId <= 0) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Ignoring result as scan stopped.");
- }
- return;
- };
- }
- Handler handler = new Handler(Looper.getMainLooper());
- handler.post(new Runnable() {
- @Override
- public void run() {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onScanResult() - handler run");
- }
- mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
- }
- });
- }
-
- @Override
- public void onBatchScanResults(final List<ScanResult> results) {
- Attributable.setAttributionSource(results, mAttributionSource);
- Handler handler = new Handler(Looper.getMainLooper());
- handler.post(new Runnable() {
- @Override
- public void run() {
- mScanCallback.onBatchScanResults(results);
- }
- });
- }
-
- @Override
- public void onFoundOrLost(final boolean onFound, final ScanResult scanResult) {
- Attributable.setAttributionSource(scanResult, mAttributionSource);
- if (VDBG) {
- Log.d(TAG, "onFoundOrLost() - onFound = " + onFound + " " + scanResult.toString());
- }
-
- // Check null in case the scan has been stopped
- synchronized (this) {
- if (mScannerId <= 0) {
- return;
- }
- }
- Handler handler = new Handler(Looper.getMainLooper());
- handler.post(new Runnable() {
- @Override
- public void run() {
- if (onFound) {
- mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_FIRST_MATCH,
- scanResult);
- } else {
- mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_MATCH_LOST,
- scanResult);
- }
- }
- });
- }
-
- @Override
- public void onScanManagerErrorCallback(final int errorCode) {
- if (VDBG) {
- Log.d(TAG, "onScanManagerErrorCallback() - errorCode = " + errorCode);
- }
- synchronized (this) {
- if (mScannerId <= 0) {
- return;
- }
- }
- postCallbackError(mScanCallback, errorCode);
- }
- }
-
- private int postCallbackErrorOrReturn(final ScanCallback callback, final int errorCode) {
- if (callback == null) {
- return errorCode;
- } else {
- postCallbackError(callback, errorCode);
- return ScanCallback.NO_ERROR;
- }
- }
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private void postCallbackError(final ScanCallback callback, final int errorCode) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- callback.onScanFailed(errorCode);
- }
- });
- }
-
- private boolean isSettingsConfigAllowedForScan(ScanSettings settings) {
- if (mBluetoothAdapter.isOffloadedFilteringSupported()) {
- return true;
- }
- final int callbackType = settings.getCallbackType();
- // Only support regular scan if no offloaded filter support.
- if (callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES
- && settings.getReportDelayMillis() == 0) {
- return true;
- }
- return false;
- }
-
- private boolean isSettingsAndFilterComboAllowed(ScanSettings settings,
- List<ScanFilter> filterList) {
- final int callbackType = settings.getCallbackType();
- // If onlost/onfound is requested, a non-empty filter is expected
- if ((callbackType & (ScanSettings.CALLBACK_TYPE_FIRST_MATCH
- | ScanSettings.CALLBACK_TYPE_MATCH_LOST)) != 0) {
- if (filterList == null) {
- return false;
- }
- for (ScanFilter filter : filterList) {
- if (filter.isAllFieldsEmpty()) {
- return false;
- }
- }
- }
- return true;
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private boolean isHardwareResourcesAvailableForScan(ScanSettings settings) {
- final int callbackType = settings.getCallbackType();
- if ((callbackType & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0
- || (callbackType & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0) {
- // For onlost/onfound, we required hw support be available
- return (mBluetoothAdapter.isOffloadedFilteringSupported()
- && mBluetoothAdapter.isHardwareTrackingFiltersAvailable());
- }
- return true;
- }
-}
diff --git a/core/java/android/bluetooth/le/BluetoothLeUtils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java
deleted file mode 100644
index ed50b09..0000000
--- a/core/java/android/bluetooth/le/BluetoothLeUtils.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.bluetooth.BluetoothAdapter;
-import android.util.SparseArray;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Helper class for Bluetooth LE utils.
- *
- * @hide
- */
-public class BluetoothLeUtils {
-
- /**
- * Returns a string composed from a {@link SparseArray}.
- */
- static String toString(SparseArray<byte[]> array) {
- if (array == null) {
- return "null";
- }
- if (array.size() == 0) {
- return "{}";
- }
- StringBuilder buffer = new StringBuilder();
- buffer.append('{');
- for (int i = 0; i < array.size(); ++i) {
- buffer.append(array.keyAt(i)).append("=").append(Arrays.toString(array.valueAt(i)));
- }
- buffer.append('}');
- return buffer.toString();
- }
-
- /**
- * Returns a string composed from a {@link Map}.
- */
- static <T> String toString(Map<T, byte[]> map) {
- if (map == null) {
- return "null";
- }
- if (map.isEmpty()) {
- return "{}";
- }
- StringBuilder buffer = new StringBuilder();
- buffer.append('{');
- Iterator<Map.Entry<T, byte[]>> it = map.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry<T, byte[]> entry = it.next();
- Object key = entry.getKey();
- buffer.append(key).append("=").append(Arrays.toString(map.get(key)));
- if (it.hasNext()) {
- buffer.append(", ");
- }
- }
- buffer.append('}');
- return buffer.toString();
- }
-
- /**
- * Check whether two {@link SparseArray} equal.
- */
- static boolean equals(SparseArray<byte[]> array, SparseArray<byte[]> otherArray) {
- if (array == otherArray) {
- return true;
- }
- if (array == null || otherArray == null) {
- return false;
- }
- if (array.size() != otherArray.size()) {
- return false;
- }
-
- // Keys are guaranteed in ascending order when indices are in ascending order.
- for (int i = 0; i < array.size(); ++i) {
- if (array.keyAt(i) != otherArray.keyAt(i)
- || !Arrays.equals(array.valueAt(i), otherArray.valueAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Check whether two {@link Map} equal.
- */
- static <T> boolean equals(Map<T, byte[]> map, Map<T, byte[]> otherMap) {
- if (map == otherMap) {
- return true;
- }
- if (map == null || otherMap == null) {
- return false;
- }
- if (map.size() != otherMap.size()) {
- return false;
- }
- Set<T> keys = map.keySet();
- if (!keys.equals(otherMap.keySet())) {
- return false;
- }
- for (T key : keys) {
- if (!Objects.deepEquals(map.get(key), otherMap.get(key))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Ensure Bluetooth is turned on.
- *
- * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not {@link
- * BluetoothAdapter#STATE_ON}.
- */
- static void checkAdapterStateOn(BluetoothAdapter adapter) {
- if (adapter == null || !adapter.isLeEnabled()) {
- throw new IllegalStateException("BT Adapter is not turned ON");
- }
- }
-
- /**
- * Compares two UUIDs with a UUID mask.
- *
- * @param data first {@link #UUID} to compare.
- * @param uuid second {@link #UUID} to compare.
- * @param mask mask {@link #UUID}.
- * @return true if both UUIDs are equals when masked, false otherwise.
- */
- static boolean maskedEquals(UUID data, UUID uuid, UUID mask) {
- if (mask == null) {
- return Objects.equals(data, uuid);
- }
- return (data.getLeastSignificantBits() & mask.getLeastSignificantBits())
- == (uuid.getLeastSignificantBits() & mask.getLeastSignificantBits())
- && (data.getMostSignificantBits() & mask.getMostSignificantBits())
- == (uuid.getMostSignificantBits() & mask.getMostSignificantBits());
- }
-}
diff --git a/core/java/android/bluetooth/le/OWNERS b/core/java/android/bluetooth/le/OWNERS
deleted file mode 100644
index 3523ee0..0000000
--- a/core/java/android/bluetooth/le/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 27441
-
-zachoverflow@google.com
-siyuanh@google.com
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
deleted file mode 100644
index 14ac911..0000000
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.bluetooth.BluetoothDevice;
-
-/**
- * Bluetooth LE periodic advertising callbacks, used to deliver periodic
- * advertising operation status.
- *
- * @hide
- * @see PeriodicAdvertisingManager#createSync
- */
-public abstract class PeriodicAdvertisingCallback {
-
- /**
- * The requested operation was successful.
- *
- * @hide
- */
- public static final int SYNC_SUCCESS = 0;
-
- /**
- * Sync failed to be established because remote device did not respond.
- */
- public static final int SYNC_NO_RESPONSE = 1;
-
- /**
- * Sync failed to be established because controller can't support more syncs.
- */
- public static final int SYNC_NO_RESOURCES = 2;
-
-
- /**
- * Callback when synchronization was established.
- *
- * @param syncHandle handle used to identify this synchronization.
- * @param device remote device.
- * @param advertisingSid synchronized advertising set id.
- * @param skip The number of periodic advertising packets that can be skipped after a successful
- * receive in force. @see PeriodicAdvertisingManager#createSync
- * @param timeout Synchronization timeout for the periodic advertising in force. One unit is
- * 10ms. @see PeriodicAdvertisingManager#createSync
- * @param timeout
- * @param status operation status.
- */
- public void onSyncEstablished(int syncHandle, BluetoothDevice device,
- int advertisingSid, int skip, int timeout,
- int status) {
- }
-
- /**
- * Callback when periodic advertising report is received.
- *
- * @param report periodic advertising report.
- */
- public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) {
- }
-
- /**
- * Callback when periodic advertising synchronization was lost.
- *
- * @param syncHandle handle used to identify this synchronization.
- */
- public void onSyncLost(int syncHandle) {
- }
-}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
deleted file mode 100644
index bbd3117..0000000
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.bluetooth.Attributable;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothManager;
-import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
-import android.bluetooth.annotations.RequiresBluetoothScanPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.content.AttributionSource;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.IdentityHashMap;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * This class provides methods to perform periodic advertising related
- * operations. An application can register for periodic advertisements using
- * {@link PeriodicAdvertisingManager#registerSync}.
- * <p>
- * Use {@link BluetoothAdapter#getPeriodicAdvertisingManager()} to get an
- * instance of {@link PeriodicAdvertisingManager}.
- *
- * @hide
- */
-public final class PeriodicAdvertisingManager {
-
- private static final String TAG = "PeriodicAdvertisingManager";
-
- private static final int SKIP_MIN = 0;
- private static final int SKIP_MAX = 499;
- private static final int TIMEOUT_MIN = 10;
- private static final int TIMEOUT_MAX = 16384;
-
- private static final int SYNC_STARTING = -1;
-
- private final BluetoothAdapter mBluetoothAdapter;
- private final IBluetoothManager mBluetoothManager;
- private final AttributionSource mAttributionSource;
-
- /* maps callback, to callback wrapper and sync handle */
- Map<PeriodicAdvertisingCallback,
- IPeriodicAdvertisingCallback /* callbackWrapper */> mCallbackWrappers;
-
- /**
- * Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead.
- *
- * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management.
- * @hide
- */
- public PeriodicAdvertisingManager(BluetoothAdapter bluetoothAdapter) {
- mBluetoothAdapter = Objects.requireNonNull(bluetoothAdapter);
- mBluetoothManager = mBluetoothAdapter.getBluetoothManager();
- mAttributionSource = mBluetoothAdapter.getAttributionSource();
- mCallbackWrappers = new IdentityHashMap<>();
- }
-
- /**
- * Synchronize with periodic advertising pointed to by the {@code scanResult}.
- * The {@code scanResult} used must contain a valid advertisingSid. First
- * call to registerSync will use the {@code skip} and {@code timeout} provided.
- * Subsequent calls from other apps, trying to sync with same set will reuse
- * existing sync, thus {@code skip} and {@code timeout} values will not take
- * effect. The values in effect will be returned in
- * {@link PeriodicAdvertisingCallback#onSyncEstablished}.
- *
- * @param scanResult Scan result containing advertisingSid.
- * @param skip The number of periodic advertising packets that can be skipped after a successful
- * receive. Must be between 0 and 499.
- * @param timeout Synchronization timeout for the periodic advertising. One unit is 10ms. Must
- * be between 10 (100ms) and 16384 (163.84s).
- * @param callback Callback used to deliver all operations status.
- * @throws IllegalArgumentException if {@code scanResult} is null or {@code skip} is invalid or
- * {@code timeout} is invalid or {@code callback} is null.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void registerSync(ScanResult scanResult, int skip, int timeout,
- PeriodicAdvertisingCallback callback) {
- registerSync(scanResult, skip, timeout, callback, null);
- }
-
- /**
- * Synchronize with periodic advertising pointed to by the {@code scanResult}.
- * The {@code scanResult} used must contain a valid advertisingSid. First
- * call to registerSync will use the {@code skip} and {@code timeout} provided.
- * Subsequent calls from other apps, trying to sync with same set will reuse
- * existing sync, thus {@code skip} and {@code timeout} values will not take
- * effect. The values in effect will be returned in
- * {@link PeriodicAdvertisingCallback#onSyncEstablished}.
- *
- * @param scanResult Scan result containing advertisingSid.
- * @param skip The number of periodic advertising packets that can be skipped after a successful
- * receive. Must be between 0 and 499.
- * @param timeout Synchronization timeout for the periodic advertising. One unit is 10ms. Must
- * be between 10 (100ms) and 16384 (163.84s).
- * @param callback Callback used to deliver all operations status.
- * @param handler thread upon which the callbacks will be invoked.
- * @throws IllegalArgumentException if {@code scanResult} is null or {@code skip} is invalid or
- * {@code timeout} is invalid or {@code callback} is null.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresBluetoothLocationPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void registerSync(ScanResult scanResult, int skip, int timeout,
- PeriodicAdvertisingCallback callback, Handler handler) {
- if (callback == null) {
- throw new IllegalArgumentException("callback can't be null");
- }
-
- if (scanResult == null) {
- throw new IllegalArgumentException("scanResult can't be null");
- }
-
- if (scanResult.getAdvertisingSid() == ScanResult.SID_NOT_PRESENT) {
- throw new IllegalArgumentException("scanResult must contain a valid sid");
- }
-
- if (skip < SKIP_MIN || skip > SKIP_MAX) {
- throw new IllegalArgumentException(
- "timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX);
- }
-
- if (timeout < TIMEOUT_MIN || timeout > TIMEOUT_MAX) {
- throw new IllegalArgumentException(
- "timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX);
- }
-
- IBluetoothGatt gatt;
- try {
- gatt = mBluetoothManager.getBluetoothGatt();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
- callback.onSyncEstablished(0, scanResult.getDevice(), scanResult.getAdvertisingSid(),
- skip, timeout,
- PeriodicAdvertisingCallback.SYNC_NO_RESOURCES);
- return;
- }
-
- if (handler == null) {
- handler = new Handler(Looper.getMainLooper());
- }
-
- IPeriodicAdvertisingCallback wrapped = wrap(callback, handler);
- mCallbackWrappers.put(callback, wrapped);
-
- try {
- gatt.registerSync(
- scanResult, skip, timeout, wrapped, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to register sync - ", e);
- return;
- }
- }
-
- /**
- * Cancel pending attempt to create sync, or terminate existing sync.
- *
- * @param callback Callback used to deliver all operations status.
- * @throws IllegalArgumentException if {@code callback} is null, or not a properly registered
- * callback.
- */
- @RequiresLegacyBluetoothAdminPermission
- @RequiresBluetoothScanPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
- public void unregisterSync(PeriodicAdvertisingCallback callback) {
- if (callback == null) {
- throw new IllegalArgumentException("callback can't be null");
- }
-
- IBluetoothGatt gatt;
- try {
- gatt = mBluetoothManager.getBluetoothGatt();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
- return;
- }
-
- IPeriodicAdvertisingCallback wrapper = mCallbackWrappers.remove(callback);
- if (wrapper == null) {
- throw new IllegalArgumentException("callback was not properly registered");
- }
-
- try {
- gatt.unregisterSync(wrapper, mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to cancel sync creation - ", e);
- return;
- }
- }
-
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private IPeriodicAdvertisingCallback wrap(PeriodicAdvertisingCallback callback,
- Handler handler) {
- return new IPeriodicAdvertisingCallback.Stub() {
- public void onSyncEstablished(int syncHandle, BluetoothDevice device,
- int advertisingSid, int skip, int timeout, int status) {
- Attributable.setAttributionSource(device, mAttributionSource);
- handler.post(new Runnable() {
- @Override
- public void run() {
- callback.onSyncEstablished(syncHandle, device, advertisingSid, skip,
- timeout,
- status);
-
- if (status != PeriodicAdvertisingCallback.SYNC_SUCCESS) {
- // App can still unregister the sync until notified it failed. Remove
- // callback
- // after app was notifed.
- mCallbackWrappers.remove(callback);
- }
- }
- });
- }
-
- public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- callback.onPeriodicAdvertisingReport(report);
- }
- });
- }
-
- public void onSyncLost(int syncHandle) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- callback.onSyncLost(syncHandle);
- // App can still unregister the sync until notified it's lost.
- // Remove callback after app was notifed.
- mCallbackWrappers.remove(callback);
- }
- });
- }
- };
- }
-}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
deleted file mode 100644
index 4e64dbe..0000000
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * The {@link PeriodicAdvertisingParameters} provide a way to adjust periodic
- * advertising preferences for each Bluetooth LE advertising set. Use {@link
- * PeriodicAdvertisingParameters.Builder} to create an instance of this class.
- */
-public final class PeriodicAdvertisingParameters implements Parcelable {
-
- private static final int INTERVAL_MIN = 80;
- private static final int INTERVAL_MAX = 65519;
-
- private final boolean mIncludeTxPower;
- private final int mInterval;
-
- private PeriodicAdvertisingParameters(boolean includeTxPower, int interval) {
- mIncludeTxPower = includeTxPower;
- mInterval = interval;
- }
-
- private PeriodicAdvertisingParameters(Parcel in) {
- mIncludeTxPower = in.readInt() != 0;
- mInterval = in.readInt();
- }
-
- /**
- * Returns whether the TX Power will be included.
- */
- public boolean getIncludeTxPower() {
- return mIncludeTxPower;
- }
-
- /**
- * Returns the periodic advertising interval, in 1.25ms unit.
- * Valid values are from 80 (100ms) to 65519 (81.89875s).
- */
- public int getInterval() {
- return mInterval;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mIncludeTxPower ? 1 : 0);
- dest.writeInt(mInterval);
- }
-
- public static final Parcelable
- .Creator<PeriodicAdvertisingParameters> CREATOR =
- new Creator<PeriodicAdvertisingParameters>() {
- @Override
- public PeriodicAdvertisingParameters[] newArray(int size) {
- return new PeriodicAdvertisingParameters[size];
- }
-
- @Override
- public PeriodicAdvertisingParameters createFromParcel(Parcel in) {
- return new PeriodicAdvertisingParameters(in);
- }
- };
-
- public static final class Builder {
- private boolean mIncludeTxPower = false;
- private int mInterval = INTERVAL_MAX;
-
- /**
- * Whether the transmission power level should be included in the periodic
- * packet.
- */
- public Builder setIncludeTxPower(boolean includeTxPower) {
- mIncludeTxPower = includeTxPower;
- return this;
- }
-
- /**
- * Set advertising interval for periodic advertising, in 1.25ms unit.
- * Valid values are from 80 (100ms) to 65519 (81.89875s).
- * Value from range [interval, interval+20ms] will be picked as the actual value.
- *
- * @throws IllegalArgumentException If the interval is invalid.
- */
- public Builder setInterval(int interval) {
- if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) {
- throw new IllegalArgumentException("Invalid interval (must be " + INTERVAL_MIN
- + "-" + INTERVAL_MAX + ")");
- }
- mInterval = interval;
- return this;
- }
-
- /**
- * Build the {@link AdvertisingSetParameters} object.
- */
- public PeriodicAdvertisingParameters build() {
- return new PeriodicAdvertisingParameters(mIncludeTxPower, mInterval);
- }
- }
-}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
deleted file mode 100644
index 54b953c..0000000
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * PeriodicAdvertisingReport for Bluetooth LE synchronized advertising.
- *
- * @hide
- */
-public final class PeriodicAdvertisingReport implements Parcelable {
-
- /**
- * The data returned is complete
- */
- public static final int DATA_COMPLETE = 0;
-
- /**
- * The data returned is incomplete. The controller was unsuccessfull to
- * receive all chained packets, returning only partial data.
- */
- public static final int DATA_INCOMPLETE_TRUNCATED = 2;
-
- private int mSyncHandle;
- private int mTxPower;
- private int mRssi;
- private int mDataStatus;
-
- // periodic advertising data.
- @Nullable
- private ScanRecord mData;
-
- // Device timestamp when the result was last seen.
- private long mTimestampNanos;
-
- /**
- * Constructor of periodic advertising result.
- */
- public PeriodicAdvertisingReport(int syncHandle, int txPower, int rssi,
- int dataStatus, ScanRecord data) {
- mSyncHandle = syncHandle;
- mTxPower = txPower;
- mRssi = rssi;
- mDataStatus = dataStatus;
- mData = data;
- }
-
- private PeriodicAdvertisingReport(Parcel in) {
- readFromParcel(in);
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mSyncHandle);
- dest.writeInt(mTxPower);
- dest.writeInt(mRssi);
- dest.writeInt(mDataStatus);
- if (mData != null) {
- dest.writeInt(1);
- dest.writeByteArray(mData.getBytes());
- } else {
- dest.writeInt(0);
- }
- }
-
- private void readFromParcel(Parcel in) {
- mSyncHandle = in.readInt();
- mTxPower = in.readInt();
- mRssi = in.readInt();
- mDataStatus = in.readInt();
- if (in.readInt() == 1) {
- mData = ScanRecord.parseFromBytes(in.createByteArray());
- }
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- /**
- * Returns the synchronization handle.
- */
- public int getSyncHandle() {
- return mSyncHandle;
- }
-
- /**
- * Returns the transmit power in dBm. The valid range is [-127, 126]. Value
- * of 127 means information was not available.
- */
- public int getTxPower() {
- return mTxPower;
- }
-
- /**
- * Returns the received signal strength in dBm. The valid range is [-127, 20].
- */
- public int getRssi() {
- return mRssi;
- }
-
- /**
- * Returns the data status. Can be one of {@link PeriodicAdvertisingReport#DATA_COMPLETE}
- * or {@link PeriodicAdvertisingReport#DATA_INCOMPLETE_TRUNCATED}.
- */
- public int getDataStatus() {
- return mDataStatus;
- }
-
- /**
- * Returns the data contained in this periodic advertising report.
- */
- @Nullable
- public ScanRecord getData() {
- return mData;
- }
-
- /**
- * Returns timestamp since boot when the scan record was observed.
- */
- public long getTimestampNanos() {
- return mTimestampNanos;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mSyncHandle, mTxPower, mRssi, mDataStatus, mData, mTimestampNanos);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- PeriodicAdvertisingReport other = (PeriodicAdvertisingReport) obj;
- return (mSyncHandle == other.mSyncHandle)
- && (mTxPower == other.mTxPower)
- && (mRssi == other.mRssi)
- && (mDataStatus == other.mDataStatus)
- && Objects.equals(mData, other.mData)
- && (mTimestampNanos == other.mTimestampNanos);
- }
-
- @Override
- public String toString() {
- return "PeriodicAdvertisingReport{syncHandle=" + mSyncHandle
- + ", txPower=" + mTxPower + ", rssi=" + mRssi + ", dataStatus=" + mDataStatus
- + ", data=" + Objects.toString(mData) + ", timestampNanos=" + mTimestampNanos + '}';
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<PeriodicAdvertisingReport> CREATOR =
- new Creator<PeriodicAdvertisingReport>() {
- @Override
- public PeriodicAdvertisingReport createFromParcel(Parcel source) {
- return new PeriodicAdvertisingReport(source);
- }
-
- @Override
- public PeriodicAdvertisingReport[] newArray(int size) {
- return new PeriodicAdvertisingReport[size];
- }
- };
-}
diff --git a/core/java/android/bluetooth/le/ResultStorageDescriptor.java b/core/java/android/bluetooth/le/ResultStorageDescriptor.java
deleted file mode 100644
index f650489..0000000
--- a/core/java/android/bluetooth/le/ResultStorageDescriptor.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Describes the way to store scan result.
- *
- * @deprecated this is not used anywhere
- *
- * @hide
- */
-@Deprecated
-@SystemApi
-public final class ResultStorageDescriptor implements Parcelable {
- private int mType;
- private int mOffset;
- private int mLength;
-
- public int getType() {
- return mType;
- }
-
- public int getOffset() {
- return mOffset;
- }
-
- public int getLength() {
- return mLength;
- }
-
- /**
- * Constructor of {@link ResultStorageDescriptor}
- *
- * @param type Type of the data.
- * @param offset Offset from start of the advertise packet payload.
- * @param length Byte length of the data
- */
- public ResultStorageDescriptor(int type, int offset, int length) {
- mType = type;
- mOffset = offset;
- mLength = length;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mType);
- dest.writeInt(mOffset);
- dest.writeInt(mLength);
- }
-
- private ResultStorageDescriptor(Parcel in) {
- ReadFromParcel(in);
- }
-
- private void ReadFromParcel(Parcel in) {
- mType = in.readInt();
- mOffset = in.readInt();
- mLength = in.readInt();
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<ResultStorageDescriptor> CREATOR =
- new Creator<ResultStorageDescriptor>() {
- @Override
- public ResultStorageDescriptor createFromParcel(Parcel source) {
- return new ResultStorageDescriptor(source);
- }
-
- @Override
- public ResultStorageDescriptor[] newArray(int size) {
- return new ResultStorageDescriptor[size];
- }
- };
-}
diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java
deleted file mode 100644
index 53d9310..0000000
--- a/core/java/android/bluetooth/le/ScanCallback.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import java.util.List;
-
-/**
- * Bluetooth LE scan callbacks. Scan results are reported using these callbacks.
- *
- * @see BluetoothLeScanner#startScan
- */
-public abstract class ScanCallback {
- /**
- * Fails to start scan as BLE scan with the same settings is already started by the app.
- */
- public static final int SCAN_FAILED_ALREADY_STARTED = 1;
-
- /**
- * Fails to start scan as app cannot be registered.
- */
- public static final int SCAN_FAILED_APPLICATION_REGISTRATION_FAILED = 2;
-
- /**
- * Fails to start scan due an internal error
- */
- public static final int SCAN_FAILED_INTERNAL_ERROR = 3;
-
- /**
- * Fails to start power optimized scan as this feature is not supported.
- */
- public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4;
-
- /**
- * Fails to start scan as it is out of hardware resources.
- *
- * @hide
- */
- public static final int SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES = 5;
-
- /**
- * Fails to start scan as application tries to scan too frequently.
- * @hide
- */
- public static final int SCAN_FAILED_SCANNING_TOO_FREQUENTLY = 6;
-
- static final int NO_ERROR = 0;
-
- /**
- * Callback when a BLE advertisement has been found.
- *
- * @param callbackType Determines how this callback was triggered. Could be one of {@link
- * ScanSettings#CALLBACK_TYPE_ALL_MATCHES}, {@link ScanSettings#CALLBACK_TYPE_FIRST_MATCH} or
- * {@link ScanSettings#CALLBACK_TYPE_MATCH_LOST}
- * @param result A Bluetooth LE scan result.
- */
- public void onScanResult(int callbackType, ScanResult result) {
- }
-
- /**
- * Callback when batch results are delivered.
- *
- * @param results List of scan results that are previously scanned.
- */
- public void onBatchScanResults(List<ScanResult> results) {
- }
-
- /**
- * Callback when scan could not be started.
- *
- * @param errorCode Error code (one of SCAN_FAILED_*) for scan failure.
- */
- public void onScanFailed(int errorCode) {
- }
-}
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
deleted file mode 100644
index b059193..0000000
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ /dev/null
@@ -1,910 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import static java.util.Objects.requireNonNull;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothDevice.AddressType;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
-
-/**
- * Criteria for filtering result from Bluetooth LE scans. A {@link ScanFilter} allows clients to
- * restrict scan results to only those that are of interest to them.
- * <p>
- * Current filtering on the following fields are supported:
- * <li>Service UUIDs which identify the bluetooth gatt services running on the device.
- * <li>Name of remote Bluetooth LE device.
- * <li>Mac address of the remote device.
- * <li>Service data which is the data associated with a service.
- * <li>Manufacturer specific data which is the data associated with a particular manufacturer.
- *
- * @see ScanResult
- * @see BluetoothLeScanner
- */
-public final class ScanFilter implements Parcelable {
-
- @Nullable
- private final String mDeviceName;
-
- @Nullable
- private final String mDeviceAddress;
-
- private final @AddressType int mAddressType;
-
- @Nullable
- private final byte[] mIrk;
-
- @Nullable
- private final ParcelUuid mServiceUuid;
- @Nullable
- private final ParcelUuid mServiceUuidMask;
-
- @Nullable
- private final ParcelUuid mServiceSolicitationUuid;
- @Nullable
- private final ParcelUuid mServiceSolicitationUuidMask;
-
- @Nullable
- private final ParcelUuid mServiceDataUuid;
- @Nullable
- private final byte[] mServiceData;
- @Nullable
- private final byte[] mServiceDataMask;
-
- private final int mManufacturerId;
- @Nullable
- private final byte[] mManufacturerData;
- @Nullable
- private final byte[] mManufacturerDataMask;
-
- /** @hide */
- public static final ScanFilter EMPTY = new ScanFilter.Builder().build();
-
- private ScanFilter(String name, String deviceAddress, ParcelUuid uuid,
- ParcelUuid uuidMask, ParcelUuid solicitationUuid,
- ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid,
- byte[] serviceData, byte[] serviceDataMask,
- int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask,
- @AddressType int addressType, @Nullable byte[] irk) {
- mDeviceName = name;
- mServiceUuid = uuid;
- mServiceUuidMask = uuidMask;
- mServiceSolicitationUuid = solicitationUuid;
- mServiceSolicitationUuidMask = solicitationUuidMask;
- mDeviceAddress = deviceAddress;
- mServiceDataUuid = serviceDataUuid;
- mServiceData = serviceData;
- mServiceDataMask = serviceDataMask;
- mManufacturerId = manufacturerId;
- mManufacturerData = manufacturerData;
- mManufacturerDataMask = manufacturerDataMask;
- mAddressType = addressType;
- mIrk = irk;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mDeviceName == null ? 0 : 1);
- if (mDeviceName != null) {
- dest.writeString(mDeviceName);
- }
- dest.writeInt(mDeviceAddress == null ? 0 : 1);
- if (mDeviceAddress != null) {
- dest.writeString(mDeviceAddress);
- }
- dest.writeInt(mServiceUuid == null ? 0 : 1);
- if (mServiceUuid != null) {
- dest.writeParcelable(mServiceUuid, flags);
- dest.writeInt(mServiceUuidMask == null ? 0 : 1);
- if (mServiceUuidMask != null) {
- dest.writeParcelable(mServiceUuidMask, flags);
- }
- }
- dest.writeInt(mServiceSolicitationUuid == null ? 0 : 1);
- if (mServiceSolicitationUuid != null) {
- dest.writeParcelable(mServiceSolicitationUuid, flags);
- dest.writeInt(mServiceSolicitationUuidMask == null ? 0 : 1);
- if (mServiceSolicitationUuidMask != null) {
- dest.writeParcelable(mServiceSolicitationUuidMask, flags);
- }
- }
- dest.writeInt(mServiceDataUuid == null ? 0 : 1);
- if (mServiceDataUuid != null) {
- dest.writeParcelable(mServiceDataUuid, flags);
- dest.writeInt(mServiceData == null ? 0 : 1);
- if (mServiceData != null) {
- dest.writeInt(mServiceData.length);
- dest.writeByteArray(mServiceData);
-
- dest.writeInt(mServiceDataMask == null ? 0 : 1);
- if (mServiceDataMask != null) {
- dest.writeInt(mServiceDataMask.length);
- dest.writeByteArray(mServiceDataMask);
- }
- }
- }
- dest.writeInt(mManufacturerId);
- dest.writeInt(mManufacturerData == null ? 0 : 1);
- if (mManufacturerData != null) {
- dest.writeInt(mManufacturerData.length);
- dest.writeByteArray(mManufacturerData);
-
- dest.writeInt(mManufacturerDataMask == null ? 0 : 1);
- if (mManufacturerDataMask != null) {
- dest.writeInt(mManufacturerDataMask.length);
- dest.writeByteArray(mManufacturerDataMask);
- }
- }
-
- // IRK
- if (mDeviceAddress != null) {
- dest.writeInt(mAddressType);
- dest.writeInt(mIrk == null ? 0 : 1);
- if (mIrk != null) {
- dest.writeByteArray(mIrk);
- }
- }
- }
-
- /**
- * A {@link android.os.Parcelable.Creator} to create {@link ScanFilter} from parcel.
- */
- public static final @android.annotation.NonNull Creator<ScanFilter> CREATOR =
- new Creator<ScanFilter>() {
-
- @Override
- public ScanFilter[] newArray(int size) {
- return new ScanFilter[size];
- }
-
- @Override
- public ScanFilter createFromParcel(Parcel in) {
- Builder builder = new Builder();
- if (in.readInt() == 1) {
- builder.setDeviceName(in.readString());
- }
- String address = null;
- // If we have a non-null address
- if (in.readInt() == 1) {
- address = in.readString();
- }
- if (in.readInt() == 1) {
- ParcelUuid uuid = in.readParcelable(ParcelUuid.class.getClassLoader());
- builder.setServiceUuid(uuid);
- if (in.readInt() == 1) {
- ParcelUuid uuidMask = in.readParcelable(
- ParcelUuid.class.getClassLoader());
- builder.setServiceUuid(uuid, uuidMask);
- }
- }
- if (in.readInt() == 1) {
- ParcelUuid solicitationUuid = in.readParcelable(
- ParcelUuid.class.getClassLoader());
- builder.setServiceSolicitationUuid(solicitationUuid);
- if (in.readInt() == 1) {
- ParcelUuid solicitationUuidMask = in.readParcelable(
- ParcelUuid.class.getClassLoader());
- builder.setServiceSolicitationUuid(solicitationUuid,
- solicitationUuidMask);
- }
- }
- if (in.readInt() == 1) {
- ParcelUuid servcieDataUuid =
- in.readParcelable(ParcelUuid.class.getClassLoader());
- if (in.readInt() == 1) {
- int serviceDataLength = in.readInt();
- byte[] serviceData = new byte[serviceDataLength];
- in.readByteArray(serviceData);
- if (in.readInt() == 0) {
- builder.setServiceData(servcieDataUuid, serviceData);
- } else {
- int serviceDataMaskLength = in.readInt();
- byte[] serviceDataMask = new byte[serviceDataMaskLength];
- in.readByteArray(serviceDataMask);
- builder.setServiceData(
- servcieDataUuid, serviceData, serviceDataMask);
- }
- }
- }
-
- int manufacturerId = in.readInt();
- if (in.readInt() == 1) {
- int manufacturerDataLength = in.readInt();
- byte[] manufacturerData = new byte[manufacturerDataLength];
- in.readByteArray(manufacturerData);
- if (in.readInt() == 0) {
- builder.setManufacturerData(manufacturerId, manufacturerData);
- } else {
- int manufacturerDataMaskLength = in.readInt();
- byte[] manufacturerDataMask = new byte[manufacturerDataMaskLength];
- in.readByteArray(manufacturerDataMask);
- builder.setManufacturerData(manufacturerId, manufacturerData,
- manufacturerDataMask);
- }
- }
-
- // IRK
- if (address != null) {
- final int addressType = in.readInt();
- if (in.readInt() == 1) {
- final byte[] irk = new byte[16];
- in.readByteArray(irk);
- builder.setDeviceAddress(address, addressType, irk);
- } else {
- builder.setDeviceAddress(address, addressType);
- }
- }
- return builder.build();
- }
- };
-
- /**
- * Returns the filter set the device name field of Bluetooth advertisement data.
- */
- @Nullable
- public String getDeviceName() {
- return mDeviceName;
- }
-
- /**
- * Returns the filter set on the service uuid.
- */
- @Nullable
- public ParcelUuid getServiceUuid() {
- return mServiceUuid;
- }
-
- @Nullable
- public ParcelUuid getServiceUuidMask() {
- return mServiceUuidMask;
- }
-
- /**
- * Returns the filter set on the service Solicitation uuid.
- */
- @Nullable
- public ParcelUuid getServiceSolicitationUuid() {
- return mServiceSolicitationUuid;
- }
-
- /**
- * Returns the filter set on the service Solicitation uuid mask.
- */
- @Nullable
- public ParcelUuid getServiceSolicitationUuidMask() {
- return mServiceSolicitationUuidMask;
- }
-
- @Nullable
- public String getDeviceAddress() {
- return mDeviceAddress;
- }
-
- /**
- * @hide
- */
- @SystemApi
- public @AddressType int getAddressType() {
- return mAddressType;
- }
-
- /**
- * @hide
- */
- @SystemApi
- @Nullable
- public byte[] getIrk() {
- return mIrk;
- }
-
- @Nullable
- public byte[] getServiceData() {
- return mServiceData;
- }
-
- @Nullable
- public byte[] getServiceDataMask() {
- return mServiceDataMask;
- }
-
- @Nullable
- public ParcelUuid getServiceDataUuid() {
- return mServiceDataUuid;
- }
-
- /**
- * Returns the manufacturer id. -1 if the manufacturer filter is not set.
- */
- public int getManufacturerId() {
- return mManufacturerId;
- }
-
- @Nullable
- public byte[] getManufacturerData() {
- return mManufacturerData;
- }
-
- @Nullable
- public byte[] getManufacturerDataMask() {
- return mManufacturerDataMask;
- }
-
- /**
- * Check if the scan filter matches a {@code scanResult}. A scan result is considered as a match
- * if it matches all the field filters.
- */
- public boolean matches(ScanResult scanResult) {
- if (scanResult == null) {
- return false;
- }
- BluetoothDevice device = scanResult.getDevice();
- // Device match.
- if (mDeviceAddress != null
- && (device == null || !mDeviceAddress.equals(device.getAddress()))) {
- return false;
- }
-
- ScanRecord scanRecord = scanResult.getScanRecord();
-
- // Scan record is null but there exist filters on it.
- if (scanRecord == null
- && (mDeviceName != null || mServiceUuid != null || mManufacturerData != null
- || mServiceData != null || mServiceSolicitationUuid != null)) {
- return false;
- }
-
- // Local name match.
- if (mDeviceName != null && !mDeviceName.equals(scanRecord.getDeviceName())) {
- return false;
- }
-
- // UUID match.
- if (mServiceUuid != null && !matchesServiceUuids(mServiceUuid, mServiceUuidMask,
- scanRecord.getServiceUuids())) {
- return false;
- }
-
- // solicitation UUID match.
- if (mServiceSolicitationUuid != null && !matchesServiceSolicitationUuids(
- mServiceSolicitationUuid, mServiceSolicitationUuidMask,
- scanRecord.getServiceSolicitationUuids())) {
- return false;
- }
-
- // Service data match
- if (mServiceDataUuid != null) {
- if (!matchesPartialData(mServiceData, mServiceDataMask,
- scanRecord.getServiceData(mServiceDataUuid))) {
- return false;
- }
- }
-
- // Manufacturer data match.
- if (mManufacturerId >= 0) {
- if (!matchesPartialData(mManufacturerData, mManufacturerDataMask,
- scanRecord.getManufacturerSpecificData(mManufacturerId))) {
- return false;
- }
- }
- // All filters match.
- return true;
- }
-
- /**
- * Check if the uuid pattern is contained in a list of parcel uuids.
- *
- * @hide
- */
- public static boolean matchesServiceUuids(ParcelUuid uuid, ParcelUuid parcelUuidMask,
- List<ParcelUuid> uuids) {
- if (uuid == null) {
- return true;
- }
- if (uuids == null) {
- return false;
- }
-
- for (ParcelUuid parcelUuid : uuids) {
- UUID uuidMask = parcelUuidMask == null ? null : parcelUuidMask.getUuid();
- if (matchesServiceUuid(uuid.getUuid(), uuidMask, parcelUuid.getUuid())) {
- return true;
- }
- }
- return false;
- }
-
- // Check if the uuid pattern matches the particular service uuid.
- private static boolean matchesServiceUuid(UUID uuid, UUID mask, UUID data) {
- return BluetoothLeUtils.maskedEquals(data, uuid, mask);
- }
-
- /**
- * Check if the solicitation uuid pattern is contained in a list of parcel uuids.
- *
- */
- private static boolean matchesServiceSolicitationUuids(ParcelUuid solicitationUuid,
- ParcelUuid parcelSolicitationUuidMask, List<ParcelUuid> solicitationUuids) {
- if (solicitationUuid == null) {
- return true;
- }
- if (solicitationUuids == null) {
- return false;
- }
-
- for (ParcelUuid parcelSolicitationUuid : solicitationUuids) {
- UUID solicitationUuidMask = parcelSolicitationUuidMask == null
- ? null : parcelSolicitationUuidMask.getUuid();
- if (matchesServiceUuid(solicitationUuid.getUuid(), solicitationUuidMask,
- parcelSolicitationUuid.getUuid())) {
- return true;
- }
- }
- return false;
- }
-
- // Check if the solicitation uuid pattern matches the particular service solicitation uuid.
- private static boolean matchesServiceSolicitationUuid(UUID solicitationUuid,
- UUID solicitationUuidMask, UUID data) {
- return BluetoothLeUtils.maskedEquals(data, solicitationUuid, solicitationUuidMask);
- }
-
- // Check whether the data pattern matches the parsed data.
- private boolean matchesPartialData(byte[] data, byte[] dataMask, byte[] parsedData) {
- if (parsedData == null || parsedData.length < data.length) {
- return false;
- }
- if (dataMask == null) {
- for (int i = 0; i < data.length; ++i) {
- if (parsedData[i] != data[i]) {
- return false;
- }
- }
- return true;
- }
- for (int i = 0; i < data.length; ++i) {
- if ((dataMask[i] & parsedData[i]) != (dataMask[i] & data[i])) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public String toString() {
- return "BluetoothLeScanFilter [mDeviceName=" + mDeviceName + ", mDeviceAddress="
- + mDeviceAddress
- + ", mUuid=" + mServiceUuid + ", mUuidMask=" + mServiceUuidMask
- + ", mServiceSolicitationUuid=" + mServiceSolicitationUuid
- + ", mServiceSolicitationUuidMask=" + mServiceSolicitationUuidMask
- + ", mServiceDataUuid=" + Objects.toString(mServiceDataUuid) + ", mServiceData="
- + Arrays.toString(mServiceData) + ", mServiceDataMask="
- + Arrays.toString(mServiceDataMask) + ", mManufacturerId=" + mManufacturerId
- + ", mManufacturerData=" + Arrays.toString(mManufacturerData)
- + ", mManufacturerDataMask=" + Arrays.toString(mManufacturerDataMask) + "]";
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mDeviceName, mDeviceAddress, mManufacturerId,
- Arrays.hashCode(mManufacturerData),
- Arrays.hashCode(mManufacturerDataMask),
- mServiceDataUuid,
- Arrays.hashCode(mServiceData),
- Arrays.hashCode(mServiceDataMask),
- mServiceUuid, mServiceUuidMask,
- mServiceSolicitationUuid, mServiceSolicitationUuidMask);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- ScanFilter other = (ScanFilter) obj;
- return Objects.equals(mDeviceName, other.mDeviceName)
- && Objects.equals(mDeviceAddress, other.mDeviceAddress)
- && mManufacturerId == other.mManufacturerId
- && Objects.deepEquals(mManufacturerData, other.mManufacturerData)
- && Objects.deepEquals(mManufacturerDataMask, other.mManufacturerDataMask)
- && Objects.equals(mServiceDataUuid, other.mServiceDataUuid)
- && Objects.deepEquals(mServiceData, other.mServiceData)
- && Objects.deepEquals(mServiceDataMask, other.mServiceDataMask)
- && Objects.equals(mServiceUuid, other.mServiceUuid)
- && Objects.equals(mServiceUuidMask, other.mServiceUuidMask)
- && Objects.equals(mServiceSolicitationUuid, other.mServiceSolicitationUuid)
- && Objects.equals(mServiceSolicitationUuidMask,
- other.mServiceSolicitationUuidMask);
- }
-
- /**
- * Checks if the scanfilter is empty
- *
- * @hide
- */
- public boolean isAllFieldsEmpty() {
- return EMPTY.equals(this);
- }
-
- /**
- * Builder class for {@link ScanFilter}.
- */
- public static final class Builder {
-
- /**
- * @hide
- */
- @SystemApi
- public static final int LEN_IRK_OCTETS = 16;
-
- private String mDeviceName;
- private String mDeviceAddress;
- private @AddressType int mAddressType = BluetoothDevice.ADDRESS_TYPE_PUBLIC;
- private byte[] mIrk;
-
- private ParcelUuid mServiceUuid;
- private ParcelUuid mUuidMask;
-
- private ParcelUuid mServiceSolicitationUuid;
- private ParcelUuid mServiceSolicitationUuidMask;
-
- private ParcelUuid mServiceDataUuid;
- private byte[] mServiceData;
- private byte[] mServiceDataMask;
-
- private int mManufacturerId = -1;
- private byte[] mManufacturerData;
- private byte[] mManufacturerDataMask;
-
- /**
- * Set filter on device name.
- */
- public Builder setDeviceName(String deviceName) {
- mDeviceName = deviceName;
- return this;
- }
-
- /**
- * Set filter on device address.
- *
- * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
- * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
- * BluetoothAdapter#checkBluetoothAddress}. The @AddressType is defaulted to {@link
- * BluetoothDevice#ADDRESS_TYPE_PUBLIC}
- * @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
- */
- public Builder setDeviceAddress(String deviceAddress) {
- if (deviceAddress == null) {
- mDeviceAddress = deviceAddress;
- return this;
- }
- return setDeviceAddress(deviceAddress, BluetoothDevice.ADDRESS_TYPE_PUBLIC);
- }
-
- /**
- * Set filter on Address with AddressType
- *
- * <p>This key is used to resolve a private address from a public address.
- *
- * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
- * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
- * BluetoothAdapter#checkBluetoothAddress}. May be any type of address.
- * @param addressType indication of the type of address
- * e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}
- * or {@link BluetoothDevice#ADDRESS_TYPE_RANDOM}
- *
- * @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
- * @throws IllegalArgumentException If the {@code addressType} is invalid length
- * @throws NullPointerException if {@code deviceAddress} is null.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public Builder setDeviceAddress(@NonNull String deviceAddress,
- @AddressType int addressType) {
- return setDeviceAddressInternal(deviceAddress, addressType, null);
- }
-
- /**
- * Set filter on Address with AddressType and the Identity Resolving Key (IRK).
- *
- * <p>The IRK is used to resolve a {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC} from
- * a PRIVATE_ADDRESS type.
- *
- * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
- * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
- * BluetoothAdapter#checkBluetoothAddress}. This Address type must only be PUBLIC OR RANDOM
- * STATIC.
- * @param addressType indication of the type of address
- * e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}
- * or {@link BluetoothDevice#ADDRESS_TYPE_RANDOM}
- * @param irk non-null byte array representing the Identity Resolving Key
- *
- * @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
- * @throws IllegalArgumentException if the {@code irk} is invalid length.
- * @throws IllegalArgumentException If the {@code addressType} is invalid length or is not
- * PUBLIC or RANDOM STATIC when an IRK is present.
- * @throws NullPointerException if {@code deviceAddress} or {@code irk} is null.
- *
- * @hide
- */
- @NonNull
- @SystemApi
- public Builder setDeviceAddress(@NonNull String deviceAddress,
- @AddressType int addressType,
- @NonNull byte[] irk) {
- requireNonNull(irk);
- if (irk.length != LEN_IRK_OCTETS) {
- throw new IllegalArgumentException("'irk' is invalid length!");
- }
- return setDeviceAddressInternal(deviceAddress, addressType, irk);
- }
-
- /**
- * Set filter on Address with AddressType and the Identity Resolving Key (IRK).
- *
- * <p>Internal setter for the device address
- *
- * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
- * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
- * BluetoothAdapter#checkBluetoothAddress}.
- * @param addressType indication of the type of address
- * e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}
- * @param irk non-null byte array representing the Identity Resolving Address; nullable
- * internally.
- *
- * @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
- * @throws IllegalArgumentException If the {@code addressType} is invalid length.
- * @throws NullPointerException if {@code deviceAddress} is null.
- *
- * @hide
- */
- @NonNull
- private Builder setDeviceAddressInternal(@NonNull String deviceAddress,
- @AddressType int addressType,
- @Nullable byte[] irk) {
-
- // Make sure our deviceAddress is valid!
- requireNonNull(deviceAddress);
- if (!BluetoothAdapter.checkBluetoothAddress(deviceAddress)) {
- throw new IllegalArgumentException("invalid device address " + deviceAddress);
- }
-
- // Verify type range
- if (addressType < BluetoothDevice.ADDRESS_TYPE_PUBLIC
- || addressType > BluetoothDevice.ADDRESS_TYPE_RANDOM) {
- throw new IllegalArgumentException("'addressType' is invalid!");
- }
-
- // IRK can only be used for a PUBLIC or RANDOM (STATIC) Address.
- if (addressType == BluetoothDevice.ADDRESS_TYPE_RANDOM) {
- // Don't want a bad combination of address and irk!
- if (irk != null) {
- // Since there are 3 possible RANDOM subtypes we must check to make sure
- // the correct type of address is used.
- if (!BluetoothAdapter.isAddressRandomStatic(deviceAddress)) {
- throw new IllegalArgumentException(
- "Invalid combination: IRK requires either a PUBLIC or "
- + "RANDOM (STATIC) Address");
- }
- }
- }
-
- // PUBLIC doesn't require extra work
- // Without an IRK any address may be accepted
-
- mDeviceAddress = deviceAddress;
- mAddressType = addressType;
- mIrk = irk;
- return this;
- }
-
- /**
- * Set filter on service uuid.
- */
- public Builder setServiceUuid(ParcelUuid serviceUuid) {
- mServiceUuid = serviceUuid;
- mUuidMask = null; // clear uuid mask
- return this;
- }
-
- /**
- * Set filter on partial service uuid. The {@code uuidMask} is the bit mask for the
- * {@code serviceUuid}. Set any bit in the mask to 1 to indicate a match is needed for the
- * bit in {@code serviceUuid}, and 0 to ignore that bit.
- *
- * @throws IllegalArgumentException If {@code serviceUuid} is {@code null} but {@code
- * uuidMask} is not {@code null}.
- */
- public Builder setServiceUuid(ParcelUuid serviceUuid, ParcelUuid uuidMask) {
- if (mUuidMask != null && mServiceUuid == null) {
- throw new IllegalArgumentException("uuid is null while uuidMask is not null!");
- }
- mServiceUuid = serviceUuid;
- mUuidMask = uuidMask;
- return this;
- }
-
-
- /**
- * Set filter on service solicitation uuid.
- */
- public @NonNull Builder setServiceSolicitationUuid(
- @Nullable ParcelUuid serviceSolicitationUuid) {
- mServiceSolicitationUuid = serviceSolicitationUuid;
- if (serviceSolicitationUuid == null) {
- mServiceSolicitationUuidMask = null;
- }
- return this;
- }
-
-
- /**
- * Set filter on partial service Solicitation uuid. The {@code SolicitationUuidMask} is the
- * bit mask for the {@code serviceSolicitationUuid}. Set any bit in the mask to 1 to
- * indicate a match is needed for the bit in {@code serviceSolicitationUuid}, and 0 to
- * ignore that bit.
- *
- * @param serviceSolicitationUuid can only be null if solicitationUuidMask is null.
- * @param solicitationUuidMask can be null or a mask with no restriction.
- *
- * @throws IllegalArgumentException If {@code serviceSolicitationUuid} is {@code null} but
- * {@code serviceSolicitationUuidMask} is not {@code null}.
- */
- public @NonNull Builder setServiceSolicitationUuid(
- @Nullable ParcelUuid serviceSolicitationUuid,
- @Nullable ParcelUuid solicitationUuidMask) {
- if (solicitationUuidMask != null && serviceSolicitationUuid == null) {
- throw new IllegalArgumentException(
- "SolicitationUuid is null while SolicitationUuidMask is not null!");
- }
- mServiceSolicitationUuid = serviceSolicitationUuid;
- mServiceSolicitationUuidMask = solicitationUuidMask;
- return this;
- }
-
- /**
- * Set filtering on service data.
- *
- * @throws IllegalArgumentException If {@code serviceDataUuid} is null.
- */
- public Builder setServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) {
- if (serviceDataUuid == null) {
- throw new IllegalArgumentException("serviceDataUuid is null");
- }
- mServiceDataUuid = serviceDataUuid;
- mServiceData = serviceData;
- mServiceDataMask = null; // clear service data mask
- return this;
- }
-
- /**
- * Set partial filter on service data. For any bit in the mask, set it to 1 if it needs to
- * match the one in service data, otherwise set it to 0 to ignore that bit.
- * <p>
- * The {@code serviceDataMask} must have the same length of the {@code serviceData}.
- *
- * @throws IllegalArgumentException If {@code serviceDataUuid} is null or {@code
- * serviceDataMask} is {@code null} while {@code serviceData} is not or {@code
- * serviceDataMask} and {@code serviceData} has different length.
- */
- public Builder setServiceData(ParcelUuid serviceDataUuid,
- byte[] serviceData, byte[] serviceDataMask) {
- if (serviceDataUuid == null) {
- throw new IllegalArgumentException("serviceDataUuid is null");
- }
- if (mServiceDataMask != null) {
- if (mServiceData == null) {
- throw new IllegalArgumentException(
- "serviceData is null while serviceDataMask is not null");
- }
- // Since the mServiceDataMask is a bit mask for mServiceData, the lengths of the two
- // byte array need to be the same.
- if (mServiceData.length != mServiceDataMask.length) {
- throw new IllegalArgumentException(
- "size mismatch for service data and service data mask");
- }
- }
- mServiceDataUuid = serviceDataUuid;
- mServiceData = serviceData;
- mServiceDataMask = serviceDataMask;
- return this;
- }
-
- /**
- * Set filter on on manufacturerData. A negative manufacturerId is considered as invalid id.
- *
- * @throws IllegalArgumentException If the {@code manufacturerId} is invalid.
- */
- public Builder setManufacturerData(int manufacturerId, byte[] manufacturerData) {
- if (manufacturerData != null && manufacturerId < 0) {
- throw new IllegalArgumentException("invalid manufacture id");
- }
- mManufacturerId = manufacturerId;
- mManufacturerData = manufacturerData;
- mManufacturerDataMask = null; // clear manufacturer data mask
- return this;
- }
-
- /**
- * Set filter on partial manufacture data. For any bit in the mask, set it the 1 if it needs
- * to match the one in manufacturer data, otherwise set it to 0.
- * <p>
- * The {@code manufacturerDataMask} must have the same length of {@code manufacturerData}.
- *
- * @throws IllegalArgumentException If the {@code manufacturerId} is invalid, or {@code
- * manufacturerData} is null while {@code manufacturerDataMask} is not, or {@code
- * manufacturerData} and {@code manufacturerDataMask} have different length.
- */
- public Builder setManufacturerData(int manufacturerId, byte[] manufacturerData,
- byte[] manufacturerDataMask) {
- if (manufacturerData != null && manufacturerId < 0) {
- throw new IllegalArgumentException("invalid manufacture id");
- }
- if (mManufacturerDataMask != null) {
- if (mManufacturerData == null) {
- throw new IllegalArgumentException(
- "manufacturerData is null while manufacturerDataMask is not null");
- }
- // Since the mManufacturerDataMask is a bit mask for mManufacturerData, the lengths
- // of the two byte array need to be the same.
- if (mManufacturerData.length != mManufacturerDataMask.length) {
- throw new IllegalArgumentException(
- "size mismatch for manufacturerData and manufacturerDataMask");
- }
- }
- mManufacturerId = manufacturerId;
- mManufacturerData = manufacturerData;
- mManufacturerDataMask = manufacturerDataMask;
- return this;
- }
-
- /**
- * Build {@link ScanFilter}.
- *
- * @throws IllegalArgumentException If the filter cannot be built.
- */
- public ScanFilter build() {
- return new ScanFilter(mDeviceName, mDeviceAddress,
- mServiceUuid, mUuidMask, mServiceSolicitationUuid,
- mServiceSolicitationUuidMask,
- mServiceDataUuid, mServiceData, mServiceDataMask,
- mManufacturerId, mManufacturerData, mManufacturerDataMask,
- mAddressType, mIrk);
- }
- }
-}
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
deleted file mode 100644
index 9b8c2ea..0000000
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.bluetooth.BluetoothUuid;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.ParcelUuid;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Predicate;
-
-/**
- * Represents a scan record from Bluetooth LE scan.
- */
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-public final class ScanRecord {
-
- private static final String TAG = "ScanRecord";
-
- // The following data type values are assigned by Bluetooth SIG.
- // For more details refer to Bluetooth 4.1 specification, Volume 3, Part C, Section 18.
- private static final int DATA_TYPE_FLAGS = 0x01;
- private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL = 0x02;
- private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03;
- private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL = 0x04;
- private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE = 0x05;
- private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL = 0x06;
- private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE = 0x07;
- private static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08;
- private static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09;
- private static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A;
- private static final int DATA_TYPE_SERVICE_DATA_16_BIT = 0x16;
- private static final int DATA_TYPE_SERVICE_DATA_32_BIT = 0x20;
- private static final int DATA_TYPE_SERVICE_DATA_128_BIT = 0x21;
- private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT = 0x14;
- private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT = 0x1F;
- private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT = 0x15;
- private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
-
- // Flags of the advertising data.
- private final int mAdvertiseFlags;
-
- @Nullable
- private final List<ParcelUuid> mServiceUuids;
- @Nullable
- private final List<ParcelUuid> mServiceSolicitationUuids;
-
- private final SparseArray<byte[]> mManufacturerSpecificData;
-
- private final Map<ParcelUuid, byte[]> mServiceData;
-
- // Transmission power level(in dB).
- private final int mTxPowerLevel;
-
- // Local name of the Bluetooth LE device.
- private final String mDeviceName;
-
- // Raw bytes of scan record.
- private final byte[] mBytes;
-
- /**
- * Returns the advertising flags indicating the discoverable mode and capability of the device.
- * Returns -1 if the flag field is not set.
- */
- public int getAdvertiseFlags() {
- return mAdvertiseFlags;
- }
-
- /**
- * Returns a list of service UUIDs within the advertisement that are used to identify the
- * bluetooth GATT services.
- */
- public List<ParcelUuid> getServiceUuids() {
- return mServiceUuids;
- }
-
- /**
- * Returns a list of service solicitation UUIDs within the advertisement that are used to
- * identify the Bluetooth GATT services.
- */
- @NonNull
- public List<ParcelUuid> getServiceSolicitationUuids() {
- return mServiceSolicitationUuids;
- }
-
- /**
- * Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific
- * data.
- */
- public SparseArray<byte[]> getManufacturerSpecificData() {
- return mManufacturerSpecificData;
- }
-
- /**
- * Returns the manufacturer specific data associated with the manufacturer id. Returns
- * {@code null} if the {@code manufacturerId} is not found.
- */
- @Nullable
- public byte[] getManufacturerSpecificData(int manufacturerId) {
- if (mManufacturerSpecificData == null) {
- return null;
- }
- return mManufacturerSpecificData.get(manufacturerId);
- }
-
- /**
- * Returns a map of service UUID and its corresponding service data.
- */
- public Map<ParcelUuid, byte[]> getServiceData() {
- return mServiceData;
- }
-
- /**
- * Returns the service data byte array associated with the {@code serviceUuid}. Returns
- * {@code null} if the {@code serviceDataUuid} is not found.
- */
- @Nullable
- public byte[] getServiceData(ParcelUuid serviceDataUuid) {
- if (serviceDataUuid == null || mServiceData == null) {
- return null;
- }
- return mServiceData.get(serviceDataUuid);
- }
-
- /**
- * Returns the transmission power level of the packet in dBm. Returns {@link Integer#MIN_VALUE}
- * if the field is not set. This value can be used to calculate the path loss of a received
- * packet using the following equation:
- * <p>
- * <code>pathloss = txPowerLevel - rssi</code>
- */
- public int getTxPowerLevel() {
- return mTxPowerLevel;
- }
-
- /**
- * Returns the local name of the BLE device. This is a UTF-8 encoded string.
- */
- @Nullable
- public String getDeviceName() {
- return mDeviceName;
- }
-
- /**
- * Returns raw bytes of scan record.
- */
- public byte[] getBytes() {
- return mBytes;
- }
-
- /**
- * Test if any fields contained inside this scan record are matched by the
- * given matcher.
- *
- * @hide
- */
- public boolean matchesAnyField(@NonNull Predicate<byte[]> matcher) {
- int pos = 0;
- while (pos < mBytes.length) {
- final int length = mBytes[pos] & 0xFF;
- if (length == 0) {
- break;
- }
- if (matcher.test(Arrays.copyOfRange(mBytes, pos, pos + length + 1))) {
- return true;
- }
- pos += length + 1;
- }
- return false;
- }
-
- private ScanRecord(List<ParcelUuid> serviceUuids,
- List<ParcelUuid> serviceSolicitationUuids,
- SparseArray<byte[]> manufacturerData,
- Map<ParcelUuid, byte[]> serviceData,
- int advertiseFlags, int txPowerLevel,
- String localName, byte[] bytes) {
- mServiceSolicitationUuids = serviceSolicitationUuids;
- mServiceUuids = serviceUuids;
- mManufacturerSpecificData = manufacturerData;
- mServiceData = serviceData;
- mDeviceName = localName;
- mAdvertiseFlags = advertiseFlags;
- mTxPowerLevel = txPowerLevel;
- mBytes = bytes;
- }
-
- /**
- * Parse scan record bytes to {@link ScanRecord}.
- * <p>
- * The format is defined in Bluetooth 4.1 specification, Volume 3, Part C, Section 11 and 18.
- * <p>
- * All numerical multi-byte entities and values shall use little-endian <strong>byte</strong>
- * order.
- *
- * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response.
- * @hide
- */
- @UnsupportedAppUsage
- public static ScanRecord parseFromBytes(byte[] scanRecord) {
- if (scanRecord == null) {
- return null;
- }
-
- int currentPos = 0;
- int advertiseFlag = -1;
- List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
- List<ParcelUuid> serviceSolicitationUuids = new ArrayList<ParcelUuid>();
- String localName = null;
- int txPowerLevel = Integer.MIN_VALUE;
-
- SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>();
- Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>();
-
- try {
- while (currentPos < scanRecord.length) {
- // length is unsigned int.
- int length = scanRecord[currentPos++] & 0xFF;
- if (length == 0) {
- break;
- }
- // Note the length includes the length of the field type itself.
- int dataLength = length - 1;
- // fieldType is unsigned int.
- int fieldType = scanRecord[currentPos++] & 0xFF;
- switch (fieldType) {
- case DATA_TYPE_FLAGS:
- advertiseFlag = scanRecord[currentPos] & 0xFF;
- break;
- case DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL:
- case DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE:
- parseServiceUuid(scanRecord, currentPos,
- dataLength, BluetoothUuid.UUID_BYTES_16_BIT, serviceUuids);
- break;
- case DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL:
- case DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE:
- parseServiceUuid(scanRecord, currentPos, dataLength,
- BluetoothUuid.UUID_BYTES_32_BIT, serviceUuids);
- break;
- case DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL:
- case DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE:
- parseServiceUuid(scanRecord, currentPos, dataLength,
- BluetoothUuid.UUID_BYTES_128_BIT, serviceUuids);
- break;
- case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT:
- parseServiceSolicitationUuid(scanRecord, currentPos, dataLength,
- BluetoothUuid.UUID_BYTES_16_BIT, serviceSolicitationUuids);
- break;
- case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT:
- parseServiceSolicitationUuid(scanRecord, currentPos, dataLength,
- BluetoothUuid.UUID_BYTES_32_BIT, serviceSolicitationUuids);
- break;
- case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT:
- parseServiceSolicitationUuid(scanRecord, currentPos, dataLength,
- BluetoothUuid.UUID_BYTES_128_BIT, serviceSolicitationUuids);
- break;
- case DATA_TYPE_LOCAL_NAME_SHORT:
- case DATA_TYPE_LOCAL_NAME_COMPLETE:
- localName = new String(
- extractBytes(scanRecord, currentPos, dataLength));
- break;
- case DATA_TYPE_TX_POWER_LEVEL:
- txPowerLevel = scanRecord[currentPos];
- break;
- case DATA_TYPE_SERVICE_DATA_16_BIT:
- case DATA_TYPE_SERVICE_DATA_32_BIT:
- case DATA_TYPE_SERVICE_DATA_128_BIT:
- int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT;
- if (fieldType == DATA_TYPE_SERVICE_DATA_32_BIT) {
- serviceUuidLength = BluetoothUuid.UUID_BYTES_32_BIT;
- } else if (fieldType == DATA_TYPE_SERVICE_DATA_128_BIT) {
- serviceUuidLength = BluetoothUuid.UUID_BYTES_128_BIT;
- }
-
- byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos,
- serviceUuidLength);
- ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom(
- serviceDataUuidBytes);
- byte[] serviceDataArray = extractBytes(scanRecord,
- currentPos + serviceUuidLength, dataLength - serviceUuidLength);
- serviceData.put(serviceDataUuid, serviceDataArray);
- break;
- case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
- // The first two bytes of the manufacturer specific data are
- // manufacturer ids in little endian.
- int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8)
- + (scanRecord[currentPos] & 0xFF);
- byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2,
- dataLength - 2);
- manufacturerData.put(manufacturerId, manufacturerDataBytes);
- break;
- default:
- // Just ignore, we don't handle such data type.
- break;
- }
- currentPos += dataLength;
- }
-
- if (serviceUuids.isEmpty()) {
- serviceUuids = null;
- }
- return new ScanRecord(serviceUuids, serviceSolicitationUuids, manufacturerData,
- serviceData, advertiseFlag, txPowerLevel, localName, scanRecord);
- } catch (Exception e) {
- Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord));
- // As the record is invalid, ignore all the parsed results for this packet
- // and return an empty record with raw scanRecord bytes in results
- return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, scanRecord);
- }
- }
-
- @Override
- public String toString() {
- return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids
- + ", mServiceSolicitationUuids=" + mServiceSolicitationUuids
- + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString(
- mManufacturerSpecificData)
- + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData)
- + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]";
- }
-
- // Parse service UUIDs.
- private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength,
- int uuidLength, List<ParcelUuid> serviceUuids) {
- while (dataLength > 0) {
- byte[] uuidBytes = extractBytes(scanRecord, currentPos,
- uuidLength);
- serviceUuids.add(BluetoothUuid.parseUuidFrom(uuidBytes));
- dataLength -= uuidLength;
- currentPos += uuidLength;
- }
- return currentPos;
- }
-
- /**
- * Parse service Solicitation UUIDs.
- */
- private static int parseServiceSolicitationUuid(byte[] scanRecord, int currentPos,
- int dataLength, int uuidLength, List<ParcelUuid> serviceSolicitationUuids) {
- while (dataLength > 0) {
- byte[] uuidBytes = extractBytes(scanRecord, currentPos, uuidLength);
- serviceSolicitationUuids.add(BluetoothUuid.parseUuidFrom(uuidBytes));
- dataLength -= uuidLength;
- currentPos += uuidLength;
- }
- return currentPos;
- }
-
- // Helper method to extract bytes from byte array.
- private static byte[] extractBytes(byte[] scanRecord, int start, int length) {
- byte[] bytes = new byte[length];
- System.arraycopy(scanRecord, start, bytes, 0, length);
- return bytes;
- }
-}
diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java
deleted file mode 100644
index f437d86..0000000
--- a/core/java/android/bluetooth/le/ScanResult.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.bluetooth.Attributable;
-import android.bluetooth.BluetoothDevice;
-import android.content.AttributionSource;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * ScanResult for Bluetooth LE scan.
- */
-public final class ScanResult implements Parcelable, Attributable {
-
- /**
- * For chained advertisements, inidcates tha the data contained in this
- * scan result is complete.
- */
- public static final int DATA_COMPLETE = 0x00;
-
- /**
- * For chained advertisements, indicates that the controller was
- * unable to receive all chained packets and the scan result contains
- * incomplete truncated data.
- */
- public static final int DATA_TRUNCATED = 0x02;
-
- /**
- * Indicates that the secondary physical layer was not used.
- */
- public static final int PHY_UNUSED = 0x00;
-
- /**
- * Advertising Set ID is not present in the packet.
- */
- public static final int SID_NOT_PRESENT = 0xFF;
-
- /**
- * TX power is not present in the packet.
- */
- public static final int TX_POWER_NOT_PRESENT = 0x7F;
-
- /**
- * Periodic advertising interval is not present in the packet.
- */
- public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0x00;
-
- /**
- * Mask for checking whether event type represents legacy advertisement.
- */
- private static final int ET_LEGACY_MASK = 0x10;
-
- /**
- * Mask for checking whether event type represents connectable advertisement.
- */
- private static final int ET_CONNECTABLE_MASK = 0x01;
-
- // Remote Bluetooth device.
- private BluetoothDevice mDevice;
-
- // Scan record, including advertising data and scan response data.
- @Nullable
- private ScanRecord mScanRecord;
-
- // Received signal strength.
- private int mRssi;
-
- // Device timestamp when the result was last seen.
- private long mTimestampNanos;
-
- private int mEventType;
- private int mPrimaryPhy;
- private int mSecondaryPhy;
- private int mAdvertisingSid;
- private int mTxPower;
- private int mPeriodicAdvertisingInterval;
-
- /**
- * Constructs a new ScanResult.
- *
- * @param device Remote Bluetooth device found.
- * @param scanRecord Scan record including both advertising data and scan response data.
- * @param rssi Received signal strength.
- * @param timestampNanos Timestamp at which the scan result was observed.
- * @deprecated use {@link #ScanResult(BluetoothDevice, int, int, int, int, int, int, int,
- * ScanRecord, long)}
- */
- @Deprecated
- public ScanResult(BluetoothDevice device, ScanRecord scanRecord, int rssi,
- long timestampNanos) {
- mDevice = device;
- mScanRecord = scanRecord;
- mRssi = rssi;
- mTimestampNanos = timestampNanos;
- mEventType = (DATA_COMPLETE << 5) | ET_LEGACY_MASK | ET_CONNECTABLE_MASK;
- mPrimaryPhy = BluetoothDevice.PHY_LE_1M;
- mSecondaryPhy = PHY_UNUSED;
- mAdvertisingSid = SID_NOT_PRESENT;
- mTxPower = 127;
- mPeriodicAdvertisingInterval = 0;
- }
-
- /**
- * Constructs a new ScanResult.
- *
- * @param device Remote Bluetooth device found.
- * @param eventType Event type.
- * @param primaryPhy Primary advertising phy.
- * @param secondaryPhy Secondary advertising phy.
- * @param advertisingSid Advertising set ID.
- * @param txPower Transmit power.
- * @param rssi Received signal strength.
- * @param periodicAdvertisingInterval Periodic advertising interval.
- * @param scanRecord Scan record including both advertising data and scan response data.
- * @param timestampNanos Timestamp at which the scan result was observed.
- */
- public ScanResult(BluetoothDevice device, int eventType, int primaryPhy, int secondaryPhy,
- int advertisingSid, int txPower, int rssi, int periodicAdvertisingInterval,
- ScanRecord scanRecord, long timestampNanos) {
- mDevice = device;
- mEventType = eventType;
- mPrimaryPhy = primaryPhy;
- mSecondaryPhy = secondaryPhy;
- mAdvertisingSid = advertisingSid;
- mTxPower = txPower;
- mRssi = rssi;
- mPeriodicAdvertisingInterval = periodicAdvertisingInterval;
- mScanRecord = scanRecord;
- mTimestampNanos = timestampNanos;
- }
-
- private ScanResult(Parcel in) {
- readFromParcel(in);
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- if (mDevice != null) {
- dest.writeInt(1);
- mDevice.writeToParcel(dest, flags);
- } else {
- dest.writeInt(0);
- }
- if (mScanRecord != null) {
- dest.writeInt(1);
- dest.writeByteArray(mScanRecord.getBytes());
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(mRssi);
- dest.writeLong(mTimestampNanos);
- dest.writeInt(mEventType);
- dest.writeInt(mPrimaryPhy);
- dest.writeInt(mSecondaryPhy);
- dest.writeInt(mAdvertisingSid);
- dest.writeInt(mTxPower);
- dest.writeInt(mPeriodicAdvertisingInterval);
- }
-
- private void readFromParcel(Parcel in) {
- if (in.readInt() == 1) {
- mDevice = BluetoothDevice.CREATOR.createFromParcel(in);
- }
- if (in.readInt() == 1) {
- mScanRecord = ScanRecord.parseFromBytes(in.createByteArray());
- }
- mRssi = in.readInt();
- mTimestampNanos = in.readLong();
- mEventType = in.readInt();
- mPrimaryPhy = in.readInt();
- mSecondaryPhy = in.readInt();
- mAdvertisingSid = in.readInt();
- mTxPower = in.readInt();
- mPeriodicAdvertisingInterval = in.readInt();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** {@hide} */
- public void setAttributionSource(@NonNull AttributionSource attributionSource) {
- Attributable.setAttributionSource(mDevice, attributionSource);
- }
-
- /**
- * Returns the remote Bluetooth device identified by the Bluetooth device address.
- */
- public BluetoothDevice getDevice() {
- return mDevice;
- }
-
- /**
- * Returns the scan record, which is a combination of advertisement and scan response.
- */
- @Nullable
- public ScanRecord getScanRecord() {
- return mScanRecord;
- }
-
- /**
- * Returns the received signal strength in dBm. The valid range is [-127, 126].
- */
- public int getRssi() {
- return mRssi;
- }
-
- /**
- * Returns timestamp since boot when the scan record was observed.
- */
- public long getTimestampNanos() {
- return mTimestampNanos;
- }
-
- /**
- * Returns true if this object represents legacy scan result.
- * Legacy scan results do not contain advanced advertising information
- * as specified in the Bluetooth Core Specification v5.
- */
- public boolean isLegacy() {
- return (mEventType & ET_LEGACY_MASK) != 0;
- }
-
- /**
- * Returns true if this object represents connectable scan result.
- */
- public boolean isConnectable() {
- return (mEventType & ET_CONNECTABLE_MASK) != 0;
- }
-
- /**
- * Returns the data status.
- * Can be one of {@link ScanResult#DATA_COMPLETE} or
- * {@link ScanResult#DATA_TRUNCATED}.
- */
- public int getDataStatus() {
- // return bit 5 and 6
- return (mEventType >> 5) & 0x03;
- }
-
- /**
- * Returns the primary Physical Layer
- * on which this advertisment was received.
- * Can be one of {@link BluetoothDevice#PHY_LE_1M} or
- * {@link BluetoothDevice#PHY_LE_CODED}.
- */
- public int getPrimaryPhy() {
- return mPrimaryPhy;
- }
-
- /**
- * Returns the secondary Physical Layer
- * on which this advertisment was received.
- * Can be one of {@link BluetoothDevice#PHY_LE_1M},
- * {@link BluetoothDevice#PHY_LE_2M}, {@link BluetoothDevice#PHY_LE_CODED}
- * or {@link ScanResult#PHY_UNUSED} - if the advertisement
- * was not received on a secondary physical channel.
- */
- public int getSecondaryPhy() {
- return mSecondaryPhy;
- }
-
- /**
- * Returns the advertising set id.
- * May return {@link ScanResult#SID_NOT_PRESENT} if
- * no set id was is present.
- */
- public int getAdvertisingSid() {
- return mAdvertisingSid;
- }
-
- /**
- * Returns the transmit power in dBm.
- * Valid range is [-127, 126]. A value of {@link ScanResult#TX_POWER_NOT_PRESENT}
- * indicates that the TX power is not present.
- */
- public int getTxPower() {
- return mTxPower;
- }
-
- /**
- * Returns the periodic advertising interval in units of 1.25ms.
- * Valid range is 6 (7.5ms) to 65536 (81918.75ms). A value of
- * {@link ScanResult#PERIODIC_INTERVAL_NOT_PRESENT} means periodic
- * advertising interval is not present.
- */
- public int getPeriodicAdvertisingInterval() {
- return mPeriodicAdvertisingInterval;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mDevice, mRssi, mScanRecord, mTimestampNanos,
- mEventType, mPrimaryPhy, mSecondaryPhy,
- mAdvertisingSid, mTxPower,
- mPeriodicAdvertisingInterval);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- ScanResult other = (ScanResult) obj;
- return Objects.equals(mDevice, other.mDevice) && (mRssi == other.mRssi)
- && Objects.equals(mScanRecord, other.mScanRecord)
- && (mTimestampNanos == other.mTimestampNanos)
- && mEventType == other.mEventType
- && mPrimaryPhy == other.mPrimaryPhy
- && mSecondaryPhy == other.mSecondaryPhy
- && mAdvertisingSid == other.mAdvertisingSid
- && mTxPower == other.mTxPower
- && mPeriodicAdvertisingInterval == other.mPeriodicAdvertisingInterval;
- }
-
- @Override
- public String toString() {
- return "ScanResult{" + "device=" + mDevice + ", scanRecord="
- + Objects.toString(mScanRecord) + ", rssi=" + mRssi
- + ", timestampNanos=" + mTimestampNanos + ", eventType=" + mEventType
- + ", primaryPhy=" + mPrimaryPhy + ", secondaryPhy=" + mSecondaryPhy
- + ", advertisingSid=" + mAdvertisingSid + ", txPower=" + mTxPower
- + ", periodicAdvertisingInterval=" + mPeriodicAdvertisingInterval + '}';
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<ScanResult> CREATOR = new Creator<ScanResult>() {
- @Override
- public ScanResult createFromParcel(Parcel source) {
- return new ScanResult(source);
- }
-
- @Override
- public ScanResult[] newArray(int size) {
- return new ScanResult[size];
- }
- };
-
-}
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
deleted file mode 100644
index 1aa7cb5..0000000
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.SystemApi;
-import android.bluetooth.BluetoothDevice;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Bluetooth LE scan settings are passed to {@link BluetoothLeScanner#startScan} to define the
- * parameters for the scan.
- */
-public final class ScanSettings implements Parcelable {
-
- /**
- * A special Bluetooth LE scan mode. Applications using this scan mode will passively listen for
- * other scan results without starting BLE scans themselves.
- */
- public static final int SCAN_MODE_OPPORTUNISTIC = -1;
-
- /**
- * Perform Bluetooth LE scan in low power mode. This is the default scan mode as it consumes the
- * least power. This mode is enforced if the scanning application is not in foreground.
- */
- public static final int SCAN_MODE_LOW_POWER = 0;
-
- /**
- * Perform Bluetooth LE scan in balanced power mode. Scan results are returned at a rate that
- * provides a good trade-off between scan frequency and power consumption.
- */
- public static final int SCAN_MODE_BALANCED = 1;
-
- /**
- * Scan using highest duty cycle. It's recommended to only use this mode when the application is
- * running in the foreground.
- */
- public static final int SCAN_MODE_LOW_LATENCY = 2;
-
- /**
- * Perform Bluetooth LE scan in ambient discovery mode. This mode has lower duty cycle and more
- * aggressive scan interval than balanced mode that provides a good trade-off between scan
- * latency and power consumption.
- *
- * @hide
- */
- @SystemApi
- public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3;
-
- /**
- * Trigger a callback for every Bluetooth advertisement found that matches the filter criteria.
- * If no filter is active, all advertisement packets are reported.
- */
- public static final int CALLBACK_TYPE_ALL_MATCHES = 1;
-
- /**
- * A result callback is only triggered for the first advertisement packet received that matches
- * the filter criteria.
- */
- public static final int CALLBACK_TYPE_FIRST_MATCH = 2;
-
- /**
- * Receive a callback when advertisements are no longer received from a device that has been
- * previously reported by a first match callback.
- */
- public static final int CALLBACK_TYPE_MATCH_LOST = 4;
-
-
- /**
- * Determines how many advertisements to match per filter, as this is scarce hw resource
- */
- /**
- * Match one advertisement per filter
- */
- public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1;
-
- /**
- * Match few advertisement per filter, depends on current capability and availibility of
- * the resources in hw
- */
- public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2;
-
- /**
- * Match as many advertisement per filter as hw could allow, depends on current
- * capability and availibility of the resources in hw
- */
- public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3;
-
-
- /**
- * In Aggressive mode, hw will determine a match sooner even with feeble signal strength
- * and few number of sightings/match in a duration.
- */
- public static final int MATCH_MODE_AGGRESSIVE = 1;
-
- /**
- * For sticky mode, higher threshold of signal strength and sightings is required
- * before reporting by hw
- */
- public static final int MATCH_MODE_STICKY = 2;
-
- /**
- * Request full scan results which contain the device, rssi, advertising data, scan response
- * as well as the scan timestamp.
- *
- * @hide
- */
- @SystemApi
- public static final int SCAN_RESULT_TYPE_FULL = 0;
-
- /**
- * Request abbreviated scan results which contain the device, rssi and scan timestamp.
- * <p>
- * <b>Note:</b> It is possible for an application to get more scan results than it asked for, if
- * there are multiple apps using this type.
- *
- * @hide
- */
- @SystemApi
- public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1;
-
- /**
- * Use all supported PHYs for scanning.
- * This will check the controller capabilities, and start
- * the scan on 1Mbit and LE Coded PHYs if supported, or on
- * the 1Mbit PHY only.
- */
- public static final int PHY_LE_ALL_SUPPORTED = 255;
-
- // Bluetooth LE scan mode.
- private int mScanMode;
-
- // Bluetooth LE scan callback type
- private int mCallbackType;
-
- // Bluetooth LE scan result type
- private int mScanResultType;
-
- // Time of delay for reporting the scan result
- private long mReportDelayMillis;
-
- private int mMatchMode;
-
- private int mNumOfMatchesPerFilter;
-
- // Include only legacy advertising results
- private boolean mLegacy;
-
- private int mPhy;
-
- public int getScanMode() {
- return mScanMode;
- }
-
- public int getCallbackType() {
- return mCallbackType;
- }
-
- public int getScanResultType() {
- return mScanResultType;
- }
-
- /**
- * @hide
- */
- public int getMatchMode() {
- return mMatchMode;
- }
-
- /**
- * @hide
- */
- public int getNumOfMatches() {
- return mNumOfMatchesPerFilter;
- }
-
- /**
- * Returns whether only legacy advertisements will be returned.
- * Legacy advertisements include advertisements as specified
- * by the Bluetooth core specification 4.2 and below.
- */
- public boolean getLegacy() {
- return mLegacy;
- }
-
- /**
- * Returns the physical layer used during a scan.
- */
- public int getPhy() {
- return mPhy;
- }
-
- /**
- * Returns report delay timestamp based on the device clock.
- */
- public long getReportDelayMillis() {
- return mReportDelayMillis;
- }
-
- private ScanSettings(int scanMode, int callbackType, int scanResultType,
- long reportDelayMillis, int matchMode,
- int numOfMatchesPerFilter, boolean legacy, int phy) {
- mScanMode = scanMode;
- mCallbackType = callbackType;
- mScanResultType = scanResultType;
- mReportDelayMillis = reportDelayMillis;
- mNumOfMatchesPerFilter = numOfMatchesPerFilter;
- mMatchMode = matchMode;
- mLegacy = legacy;
- mPhy = phy;
- }
-
- private ScanSettings(Parcel in) {
- mScanMode = in.readInt();
- mCallbackType = in.readInt();
- mScanResultType = in.readInt();
- mReportDelayMillis = in.readLong();
- mMatchMode = in.readInt();
- mNumOfMatchesPerFilter = in.readInt();
- mLegacy = in.readInt() != 0;
- mPhy = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mScanMode);
- dest.writeInt(mCallbackType);
- dest.writeInt(mScanResultType);
- dest.writeLong(mReportDelayMillis);
- dest.writeInt(mMatchMode);
- dest.writeInt(mNumOfMatchesPerFilter);
- dest.writeInt(mLegacy ? 1 : 0);
- dest.writeInt(mPhy);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<ScanSettings> CREATOR =
- new Creator<ScanSettings>() {
- @Override
- public ScanSettings[] newArray(int size) {
- return new ScanSettings[size];
- }
-
- @Override
- public ScanSettings createFromParcel(Parcel in) {
- return new ScanSettings(in);
- }
- };
-
- /**
- * Builder for {@link ScanSettings}.
- */
- public static final class Builder {
- private int mScanMode = SCAN_MODE_LOW_POWER;
- private int mCallbackType = CALLBACK_TYPE_ALL_MATCHES;
- private int mScanResultType = SCAN_RESULT_TYPE_FULL;
- private long mReportDelayMillis = 0;
- private int mMatchMode = MATCH_MODE_AGGRESSIVE;
- private int mNumOfMatchesPerFilter = MATCH_NUM_MAX_ADVERTISEMENT;
- private boolean mLegacy = true;
- private int mPhy = PHY_LE_ALL_SUPPORTED;
-
- /**
- * Set scan mode for Bluetooth LE scan.
- *
- * @param scanMode The scan mode can be one of {@link ScanSettings#SCAN_MODE_LOW_POWER},
- * {@link ScanSettings#SCAN_MODE_BALANCED} or {@link ScanSettings#SCAN_MODE_LOW_LATENCY}.
- * @throws IllegalArgumentException If the {@code scanMode} is invalid.
- */
- public Builder setScanMode(int scanMode) {
- switch (scanMode) {
- case SCAN_MODE_OPPORTUNISTIC:
- case SCAN_MODE_LOW_POWER:
- case SCAN_MODE_BALANCED:
- case SCAN_MODE_LOW_LATENCY:
- case SCAN_MODE_AMBIENT_DISCOVERY:
- mScanMode = scanMode;
- break;
- default:
- throw new IllegalArgumentException("invalid scan mode " + scanMode);
- }
- return this;
- }
-
- /**
- * Set callback type for Bluetooth LE scan.
- *
- * @param callbackType The callback type flags for the scan.
- * @throws IllegalArgumentException If the {@code callbackType} is invalid.
- */
- public Builder setCallbackType(int callbackType) {
-
- if (!isValidCallbackType(callbackType)) {
- throw new IllegalArgumentException("invalid callback type - " + callbackType);
- }
- mCallbackType = callbackType;
- return this;
- }
-
- // Returns true if the callbackType is valid.
- private boolean isValidCallbackType(int callbackType) {
- if (callbackType == CALLBACK_TYPE_ALL_MATCHES
- || callbackType == CALLBACK_TYPE_FIRST_MATCH
- || callbackType == CALLBACK_TYPE_MATCH_LOST) {
- return true;
- }
- return callbackType == (CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST);
- }
-
- /**
- * Set scan result type for Bluetooth LE scan.
- *
- * @param scanResultType Type for scan result, could be either {@link
- * ScanSettings#SCAN_RESULT_TYPE_FULL} or {@link ScanSettings#SCAN_RESULT_TYPE_ABBREVIATED}.
- * @throws IllegalArgumentException If the {@code scanResultType} is invalid.
- * @hide
- */
- @SystemApi
- public Builder setScanResultType(int scanResultType) {
- if (scanResultType < SCAN_RESULT_TYPE_FULL
- || scanResultType > SCAN_RESULT_TYPE_ABBREVIATED) {
- throw new IllegalArgumentException(
- "invalid scanResultType - " + scanResultType);
- }
- mScanResultType = scanResultType;
- return this;
- }
-
- /**
- * Set report delay timestamp for Bluetooth LE scan. If set to 0, you will be notified of
- * scan results immediately. If > 0, scan results are queued up and delivered after the
- * requested delay or 5000 milliseconds (whichever is higher). Note scan results may be
- * delivered sooner if the internal buffers fill up.
- *
- * @param reportDelayMillis how frequently scan results should be delivered in
- * milliseconds
- * @throws IllegalArgumentException if {@code reportDelayMillis} < 0
- */
- public Builder setReportDelay(long reportDelayMillis) {
- if (reportDelayMillis < 0) {
- throw new IllegalArgumentException("reportDelay must be > 0");
- }
- mReportDelayMillis = reportDelayMillis;
- return this;
- }
-
- /**
- * Set the number of matches for Bluetooth LE scan filters hardware match
- *
- * @param numOfMatches The num of matches can be one of
- * {@link ScanSettings#MATCH_NUM_ONE_ADVERTISEMENT}
- * or {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or {@link
- * ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT}
- * @throws IllegalArgumentException If the {@code matchMode} is invalid.
- */
- public Builder setNumOfMatches(int numOfMatches) {
- if (numOfMatches < MATCH_NUM_ONE_ADVERTISEMENT
- || numOfMatches > MATCH_NUM_MAX_ADVERTISEMENT) {
- throw new IllegalArgumentException("invalid numOfMatches " + numOfMatches);
- }
- mNumOfMatchesPerFilter = numOfMatches;
- return this;
- }
-
- /**
- * Set match mode for Bluetooth LE scan filters hardware match
- *
- * @param matchMode The match mode can be one of {@link ScanSettings#MATCH_MODE_AGGRESSIVE}
- * or {@link ScanSettings#MATCH_MODE_STICKY}
- * @throws IllegalArgumentException If the {@code matchMode} is invalid.
- */
- public Builder setMatchMode(int matchMode) {
- if (matchMode < MATCH_MODE_AGGRESSIVE
- || matchMode > MATCH_MODE_STICKY) {
- throw new IllegalArgumentException("invalid matchMode " + matchMode);
- }
- mMatchMode = matchMode;
- return this;
- }
-
- /**
- * Set whether only legacy advertisments should be returned in scan results.
- * Legacy advertisements include advertisements as specified by the
- * Bluetooth core specification 4.2 and below. This is true by default
- * for compatibility with older apps.
- *
- * @param legacy true if only legacy advertisements will be returned
- */
- public Builder setLegacy(boolean legacy) {
- mLegacy = legacy;
- return this;
- }
-
- /**
- * Set the Physical Layer to use during this scan.
- * This is used only if {@link ScanSettings.Builder#setLegacy}
- * is set to false.
- * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}
- * may be used to check whether LE Coded phy is supported by calling
- * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}.
- * Selecting an unsupported phy will result in failure to start scan.
- *
- * @param phy Can be one of {@link BluetoothDevice#PHY_LE_1M}, {@link
- * BluetoothDevice#PHY_LE_CODED} or {@link ScanSettings#PHY_LE_ALL_SUPPORTED}
- */
- public Builder setPhy(int phy) {
- mPhy = phy;
- return this;
- }
-
- /**
- * Build {@link ScanSettings}.
- */
- public ScanSettings build() {
- return new ScanSettings(mScanMode, mCallbackType, mScanResultType,
- mReportDelayMillis, mMatchMode,
- mNumOfMatchesPerFilter, mLegacy, mPhy);
- }
- }
-}
diff --git a/core/java/android/bluetooth/le/TransportBlock.java b/core/java/android/bluetooth/le/TransportBlock.java
deleted file mode 100644
index 18bad9c..0000000
--- a/core/java/android/bluetooth/le/TransportBlock.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-/**
- * Wrapper for Transport Discovery Data Transport Blocks.
- * This class represents a Transport Block from a Transport Discovery Data.
- *
- * @see TransportDiscoveryData
- * @see AdvertiseData
- */
-public final class TransportBlock implements Parcelable {
- private static final String TAG = "TransportBlock";
- private final int mOrgId;
- private final int mTdsFlags;
- private final int mTransportDataLength;
- private final byte[] mTransportData;
-
- /**
- * Creates an instance of TransportBlock from raw data.
- *
- * @param orgId the Organization ID
- * @param tdsFlags the TDS flags
- * @param transportDataLength the total length of the Transport Data
- * @param transportData the Transport Data
- */
- public TransportBlock(int orgId, int tdsFlags, int transportDataLength,
- @Nullable byte[] transportData) {
- mOrgId = orgId;
- mTdsFlags = tdsFlags;
- mTransportDataLength = transportDataLength;
- mTransportData = transportData;
- }
-
- private TransportBlock(Parcel in) {
- mOrgId = in.readInt();
- mTdsFlags = in.readInt();
- mTransportDataLength = in.readInt();
- if (mTransportDataLength > 0) {
- mTransportData = new byte[mTransportDataLength];
- in.readByteArray(mTransportData);
- } else {
- mTransportData = null;
- }
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mOrgId);
- dest.writeInt(mTdsFlags);
- dest.writeInt(mTransportDataLength);
- if (mTransportData != null) {
- dest.writeByteArray(mTransportData);
- }
- }
-
- /**
- * @hide
- */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /**
- * @hide
- */
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- TransportBlock other = (TransportBlock) obj;
- return Arrays.equals(toByteArray(), other.toByteArray());
- }
-
- public static final @NonNull Creator<TransportBlock> CREATOR = new Creator<TransportBlock>() {
- @Override
- public TransportBlock createFromParcel(Parcel in) {
- return new TransportBlock(in);
- }
-
- @Override
- public TransportBlock[] newArray(int size) {
- return new TransportBlock[size];
- }
- };
-
- /**
- * Gets the Organization ID of the Transport Block which corresponds to one of the
- * the Bluetooth SIG Assigned Numbers.
- */
- public int getOrgId() {
- return mOrgId;
- }
-
- /**
- * Gets the TDS flags of the Transport Block which represents the role of the device and
- * information about its state and supported features.
- */
- public int getTdsFlags() {
- return mTdsFlags;
- }
-
- /**
- * Gets the total number of octets in the Transport Data field in this Transport Block.
- */
- public int getTransportDataLength() {
- return mTransportDataLength;
- }
-
- /**
- * Gets the Transport Data of the Transport Block which contains organization-specific data.
- */
- @Nullable
- public byte[] getTransportData() {
- return mTransportData;
- }
-
- /**
- * Converts this TransportBlock to byte array
- *
- * @return byte array representation of this Transport Block or null if the conversion failed
- */
- @Nullable
- public byte[] toByteArray() {
- try {
- ByteBuffer buffer = ByteBuffer.allocate(totalBytes());
- buffer.put((byte) mOrgId);
- buffer.put((byte) mTdsFlags);
- buffer.put((byte) mTransportDataLength);
- if (mTransportData != null) {
- buffer.put(mTransportData);
- }
- return buffer.array();
- } catch (BufferOverflowException e) {
- Log.e(TAG, "Error converting to byte array: " + e.toString());
- return null;
- }
- }
-
- /**
- * @return total byte count of this TransportBlock
- */
- public int totalBytes() {
- // 3 uint8 + byte[] length
- int size = 3 + mTransportDataLength;
- return size;
- }
-}
diff --git a/core/java/android/bluetooth/le/TransportDiscoveryData.java b/core/java/android/bluetooth/le/TransportDiscoveryData.java
deleted file mode 100644
index 2b52f19..0000000
--- a/core/java/android/bluetooth/le/TransportDiscoveryData.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.nio.BufferOverflowException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Wrapper for Transport Discovery Data AD Type.
- * This class contains the Transport Discovery Data AD Type Code as well as
- * a list of potential Transport Blocks.
- *
- * @see AdvertiseData
- */
-public final class TransportDiscoveryData implements Parcelable {
- private static final String TAG = "TransportDiscoveryData";
- private final int mTransportDataType;
- private final List<TransportBlock> mTransportBlocks;
-
- /**
- * Creates a TransportDiscoveryData instance.
- *
- * @param transportDataType the Transport Discovery Data AD Type
- * @param transportBlocks the list of Transport Blocks
- */
- public TransportDiscoveryData(int transportDataType,
- @NonNull List<TransportBlock> transportBlocks) {
- mTransportDataType = transportDataType;
- mTransportBlocks = transportBlocks;
- }
-
- /**
- * Creates a TransportDiscoveryData instance from byte arrays.
- *
- * Uses the transport discovery data bytes and parses them into an usable class.
- *
- * @param transportDiscoveryData the raw discovery data
- */
- public TransportDiscoveryData(@NonNull byte[] transportDiscoveryData) {
- ByteBuffer byteBuffer = ByteBuffer.wrap(transportDiscoveryData);
- mTransportBlocks = new ArrayList();
- if (byteBuffer.remaining() > 0) {
- mTransportDataType = byteBuffer.get();
- } else {
- mTransportDataType = -1;
- }
- try {
- while (byteBuffer.remaining() > 0) {
- int orgId = byteBuffer.get();
- int tdsFlags = byteBuffer.get();
- int transportDataLength = byteBuffer.get();
- byte[] transportData = new byte[transportDataLength];
- byteBuffer.get(transportData, 0, transportDataLength);
- mTransportBlocks.add(new TransportBlock(orgId, tdsFlags,
- transportDataLength, transportData));
- }
- } catch (BufferUnderflowException e) {
- Log.e(TAG, "Error while parsing data: " + e.toString());
- }
- }
-
- private TransportDiscoveryData(Parcel in) {
- mTransportDataType = in.readInt();
- mTransportBlocks = in.createTypedArrayList(TransportBlock.CREATOR);
- }
-
- /**
- * @hide
- */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /**
- * @hide
- */
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- TransportDiscoveryData other = (TransportDiscoveryData) obj;
- return Arrays.equals(toByteArray(), other.toByteArray());
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mTransportDataType);
- dest.writeTypedList(mTransportBlocks);
- }
-
- public static final @NonNull Creator<TransportDiscoveryData> CREATOR =
- new Creator<TransportDiscoveryData>() {
- @Override
- public TransportDiscoveryData createFromParcel(Parcel in) {
- return new TransportDiscoveryData(in);
- }
-
- @Override
- public TransportDiscoveryData[] newArray(int size) {
- return new TransportDiscoveryData[size];
- }
- };
-
- /**
- * Gets the transport data type.
- */
- public int getTransportDataType() {
- return mTransportDataType;
- }
-
- /**
- * @return the list of {@link TransportBlock} in this TransportDiscoveryData
- * or an empty list if there are no Transport Blocks
- */
- @NonNull
- public List<TransportBlock> getTransportBlocks() {
- if (mTransportBlocks == null) {
- return Collections.emptyList();
- }
- return mTransportBlocks;
- }
-
- /**
- * Converts this TransportDiscoveryData to byte array
- *
- * @return byte array representation of this Transport Discovery Data or null if the
- * conversion failed
- */
- @Nullable
- public byte[] toByteArray() {
- try {
- ByteBuffer buffer = ByteBuffer.allocate(totalBytes());
- buffer.put((byte) mTransportDataType);
- for (TransportBlock transportBlock : getTransportBlocks()) {
- buffer.put(transportBlock.toByteArray());
- }
- return buffer.array();
- } catch (BufferOverflowException e) {
- Log.e(TAG, "Error converting to byte array: " + e.toString());
- return null;
- }
- }
-
- /**
- * @return total byte count of this TransportDataDiscovery
- */
- public int totalBytes() {
- int size = 1; // Counting Transport Data Type here.
- for (TransportBlock transportBlock : getTransportBlocks()) {
- size += transportBlock.totalBytes();
- }
- return size;
- }
-}
diff --git a/core/java/android/bluetooth/le/TruncatedFilter.java b/core/java/android/bluetooth/le/TruncatedFilter.java
deleted file mode 100644
index 2592588..0000000
--- a/core/java/android/bluetooth/le/TruncatedFilter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-
-import java.util.List;
-
-/**
- * A special scan filter that lets the client decide how the scan record should be stored.
- *
- * @deprecated this is not used anywhere
- *
- * @hide
- */
-@Deprecated
-@SystemApi
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-public final class TruncatedFilter {
- private final ScanFilter mFilter;
- private final List<ResultStorageDescriptor> mStorageDescriptors;
-
- /**
- * Constructor for {@link TruncatedFilter}.
- *
- * @param filter Scan filter of the truncated filter.
- * @param storageDescriptors Describes how the scan should be stored.
- */
- public TruncatedFilter(ScanFilter filter, List<ResultStorageDescriptor> storageDescriptors) {
- mFilter = filter;
- mStorageDescriptors = storageDescriptors;
- }
-
- /**
- * Returns the scan filter.
- */
- public ScanFilter getFilter() {
- return mFilter;
- }
-
- /**
- * Returns a list of descriptor for scan result storage.
- */
- public List<ResultStorageDescriptor> getStorageDescriptors() {
- return mStorageDescriptors;
- }
-
-
-}
diff --git a/core/java/android/bluetooth/package.html b/core/java/android/bluetooth/package.html
deleted file mode 100644
index d9ca4f1..0000000
--- a/core/java/android/bluetooth/package.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<HTML>
-<BODY>
-<p>Provides classes that manage Bluetooth functionality, such as scanning for
-devices, connecting with devices, and managing data transfer between devices.
-The Bluetooth API supports both "Classic Bluetooth" and Bluetooth Low Energy.</p>
-
-<p>For more information about Classic Bluetooth, see the
-<a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> guide.
-For more information about Bluetooth Low Energy, see the
-<a href="{@docRoot}guide/topics/connectivity/bluetooth-le.html">
-Bluetooth Low Energy</a> (BLE) guide.</p>
-{@more}
-
-<p>The Bluetooth APIs let applications:</p>
-<ul>
- <li>Scan for other Bluetooth devices (including BLE devices).</li>
- <li>Query the local Bluetooth adapter for paired Bluetooth devices.</li>
- <li>Establish RFCOMM channels/sockets.</li>
- <li>Connect to specified sockets on other devices.</li>
- <li>Transfer data to and from other devices.</li>
- <li>Communicate with BLE devices, such as proximity sensors, heart rate
- monitors, fitness devices, and so on.</li>
- <li>Act as a GATT client or a GATT server (BLE).</li>
-</ul>
-
-<p>
-To perform Bluetooth communication using these APIs, an application must
-declare the {@link android.Manifest.permission#BLUETOOTH} permission. Some
-additional functionality, such as requesting device discovery,
-also requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-permission.
-</p>
-
-<p class="note"><strong>Note:</strong>
-Not all Android-powered devices provide Bluetooth functionality.</p>
-
-</BODY>
-</HTML>
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/ISerialManager.aidl b/core/java/android/hardware/ISerialManager.aidl
index 74d30f7..65a0fa4 100644
--- a/core/java/android/hardware/ISerialManager.aidl
+++ b/core/java/android/hardware/ISerialManager.aidl
@@ -22,8 +22,10 @@
interface ISerialManager
{
/* Returns a list of all available serial ports */
+ @EnforcePermission("SERIAL_PORT")
String[] getSerialPorts();
/* Returns a file descriptor for the serial port. */
+ @EnforcePermission("SERIAL_PORT")
ParcelFileDescriptor openSerialPort(String name);
}
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/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 5554137..036607b 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;
@@ -644,6 +658,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;
@@ -671,6 +781,7 @@
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 +798,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 +856,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 +893,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 +921,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;
@@ -931,8 +1071,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)
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..3c45799 100644
--- a/core/java/android/net/PlatformVpnProfile.java
+++ b/core/java/android/net/PlatformVpnProfile.java
@@ -83,8 +83,6 @@
/**
* Returns if the local traffic is exempted from the VPN.
- *
- * @hide TODO(184750836): unhide once the implementation is completed
*/
public final boolean getExcludeLocalRoutes() {
return mExcludeLocalRoutes;
diff --git a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
new file mode 100644
index 0000000..24c22a9
--- /dev/null
+++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
@@ -0,0 +1,520 @@
+/*
+ * 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.app.usage.NetworkStatsManager.PREFIX_UID;
+import static android.app.usage.NetworkStatsManager.PREFIX_UID_TAG;
+import static android.app.usage.NetworkStatsManager.PREFIX_XT;
+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.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 {
+
+ 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 a default
+ * implementation to read persisted network stats from two different locations.
+ * And this is intended to be modified by OEM to read from 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 readPlatformCollectionLocked(
+ @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 = NetworkIdentity.OEM_NONE;
+ }
+
+ // 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..2a2cbb9 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);
}
}
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/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/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/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/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/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/jni/Android.bp b/core/jni/Android.bp
index 07b16ed..adcbb425 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -245,7 +245,6 @@
"libandroid_net",
"libandroidicu",
"libbpf_android",
- "libnetdbpf",
"libnetdutils",
"libmemtrack",
"libandroidfw",
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 832c498..80e83ad 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -72,6 +72,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_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/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/Android.bp b/core/res/Android.bp
index 6063062..c42517d 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -37,7 +37,6 @@
visibility: [":__subpackages__"],
license_kinds: [
"SPDX-license-identifier-Apache-2.0",
- "SPDX-license-identifier-GPL",
],
license_text: [
"NOTICE",
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/bluetoothtests/Android.bp b/core/tests/bluetoothtests/Android.bp
deleted file mode 100644
index 68416dd..0000000
--- a/core/tests/bluetoothtests/Android.bp
+++ /dev/null
@@ -1,24 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-android_test {
- name: "BluetoothTests",
- // Include all test java files.
- srcs: ["src/**/*.java"],
- libs: [
- "android.test.runner",
- "android.test.base",
- ],
- static_libs: [
- "junit",
- "modules-utils-bytesmatcher",
- ],
- platform_apis: true,
- certificate: "platform",
-}
diff --git a/core/tests/bluetoothtests/AndroidManifest.xml b/core/tests/bluetoothtests/AndroidManifest.xml
deleted file mode 100644
index 75583d5..0000000
--- a/core/tests/bluetoothtests/AndroidManifest.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.bluetooth.tests"
- android:sharedUserId="android.uid.bluetooth" >
-
- <uses-permission android:name="android.permission.BLUETOOTH" />
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
- <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
- <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
- <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
- <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
- <uses-permission android:name="android.permission.BROADCAST_STICKY" />
- <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
- <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
- <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
- <uses-permission android:name="android.permission.RECEIVE_SMS" />
- <uses-permission android:name="android.permission.READ_SMS"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.WRITE_SETTINGS" />
- <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
-
- <application >
- <uses-library android:name="android.test.runner" />
- </application>
- <instrumentation android:name="android.bluetooth.BluetoothTestRunner"
- android:targetPackage="com.android.bluetooth.tests"
- android:label="Bluetooth Tests" />
- <instrumentation android:name="android.bluetooth.BluetoothInstrumentation"
- android:targetPackage="com.android.bluetooth.tests"
- android:label="Bluetooth Test Utils" />
-
-</manifest>
diff --git a/core/tests/bluetoothtests/AndroidTest.xml b/core/tests/bluetoothtests/AndroidTest.xml
deleted file mode 100644
index f93c4eb..0000000
--- a/core/tests/bluetoothtests/AndroidTest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<configuration description="Config for Bluetooth test cases">
- <option name="test-suite-tag" value="apct"/>
- <option name="test-suite-tag" value="apct-instrumentation"/>
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="BluetoothTests.apk" />
- </target_preparer>
-
- <option name="test-suite-tag" value="apct"/>
- <option name="test-tag" value="BluetoothTests"/>
-
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.android.bluetooth.tests" />
- <option name="hidden-api-checks" value="false"/>
- <option name="runner" value="android.bluetooth.BluetoothTestRunner"/>
- </test>
-</configuration>
diff --git a/core/tests/bluetoothtests/OWNERS b/core/tests/bluetoothtests/OWNERS
deleted file mode 100644
index 98bb877..0000000
--- a/core/tests/bluetoothtests/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /core/java/android/bluetooth/OWNERS
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
deleted file mode 100644
index bd55426..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for {@link BluetoothCodecConfig}.
- * <p>
- * To run this test, use:
- * runtest --path core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
- */
-public class BluetoothCodecConfigTest extends TestCase {
- private static final int[] kCodecTypeArray = new int[] {
- BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
- BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
- BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
- BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
- BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID,
- };
- private static final int[] kCodecPriorityArray = new int[] {
- BluetoothCodecConfig.CODEC_PRIORITY_DISABLED,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST,
- };
- private static final int[] kSampleRateArray = new int[] {
- BluetoothCodecConfig.SAMPLE_RATE_NONE,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.SAMPLE_RATE_88200,
- BluetoothCodecConfig.SAMPLE_RATE_96000,
- BluetoothCodecConfig.SAMPLE_RATE_176400,
- BluetoothCodecConfig.SAMPLE_RATE_192000,
- };
- private static final int[] kBitsPerSampleArray = new int[] {
- BluetoothCodecConfig.BITS_PER_SAMPLE_NONE,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.BITS_PER_SAMPLE_24,
- BluetoothCodecConfig.BITS_PER_SAMPLE_32,
- };
- private static final int[] kChannelModeArray = new int[] {
- BluetoothCodecConfig.CHANNEL_MODE_NONE,
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- };
- private static final long[] kCodecSpecific1Array = new long[] { 1000, 1001, 1002, 1003, };
- private static final long[] kCodecSpecific2Array = new long[] { 2000, 2001, 2002, 2003, };
- private static final long[] kCodecSpecific3Array = new long[] { 3000, 3001, 3002, 3003, };
- private static final long[] kCodecSpecific4Array = new long[] { 4000, 4001, 4002, 4003, };
-
- private static final int kTotalConfigs = kCodecTypeArray.length * kCodecPriorityArray.length *
- kSampleRateArray.length * kBitsPerSampleArray.length * kChannelModeArray.length *
- kCodecSpecific1Array.length * kCodecSpecific2Array.length * kCodecSpecific3Array.length *
- kCodecSpecific4Array.length;
-
- private int selectCodecType(int configId) {
- int left = kCodecTypeArray.length;
- int right = kTotalConfigs / left;
- int index = configId / right;
- index = index % kCodecTypeArray.length;
- return kCodecTypeArray[index];
- }
-
- private int selectCodecPriority(int configId) {
- int left = kCodecTypeArray.length * kCodecPriorityArray.length;
- int right = kTotalConfigs / left;
- int index = configId / right;
- index = index % kCodecPriorityArray.length;
- return kCodecPriorityArray[index];
- }
-
- private int selectSampleRate(int configId) {
- int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length;
- int right = kTotalConfigs / left;
- int index = configId / right;
- index = index % kSampleRateArray.length;
- return kSampleRateArray[index];
- }
-
- private int selectBitsPerSample(int configId) {
- int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
- kBitsPerSampleArray.length;
- int right = kTotalConfigs / left;
- int index = configId / right;
- index = index % kBitsPerSampleArray.length;
- return kBitsPerSampleArray[index];
- }
-
- private int selectChannelMode(int configId) {
- int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
- kBitsPerSampleArray.length * kChannelModeArray.length;
- int right = kTotalConfigs / left;
- int index = configId / right;
- index = index % kChannelModeArray.length;
- return kChannelModeArray[index];
- }
-
- private long selectCodecSpecific1(int configId) {
- int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
- kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length;
- int right = kTotalConfigs / left;
- int index = configId / right;
- index = index % kCodecSpecific1Array.length;
- return kCodecSpecific1Array[index];
- }
-
- private long selectCodecSpecific2(int configId) {
- int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
- kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length *
- kCodecSpecific2Array.length;
- int right = kTotalConfigs / left;
- int index = configId / right;
- index = index % kCodecSpecific2Array.length;
- return kCodecSpecific2Array[index];
- }
-
- private long selectCodecSpecific3(int configId) {
- int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
- kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length *
- kCodecSpecific2Array.length * kCodecSpecific3Array.length;
- int right = kTotalConfigs / left;
- int index = configId / right;
- index = index % kCodecSpecific3Array.length;
- return kCodecSpecific3Array[index];
- }
-
- private long selectCodecSpecific4(int configId) {
- int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
- kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length *
- kCodecSpecific2Array.length * kCodecSpecific3Array.length *
- kCodecSpecific4Array.length;
- int right = kTotalConfigs / left;
- int index = configId / right;
- index = index % kCodecSpecific4Array.length;
- return kCodecSpecific4Array[index];
- }
-
- @SmallTest
- public void testBluetoothCodecConfig_valid_get_methods() {
-
- for (int config_id = 0; config_id < kTotalConfigs; config_id++) {
- int codec_type = selectCodecType(config_id);
- int codec_priority = selectCodecPriority(config_id);
- int sample_rate = selectSampleRate(config_id);
- int bits_per_sample = selectBitsPerSample(config_id);
- int channel_mode = selectChannelMode(config_id);
- long codec_specific1 = selectCodecSpecific1(config_id);
- long codec_specific2 = selectCodecSpecific2(config_id);
- long codec_specific3 = selectCodecSpecific3(config_id);
- long codec_specific4 = selectCodecSpecific4(config_id);
-
- BluetoothCodecConfig bcc = buildBluetoothCodecConfig(codec_type, codec_priority,
- sample_rate, bits_per_sample,
- channel_mode, codec_specific1,
- codec_specific2, codec_specific3,
- codec_specific4);
-
- if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC) {
- assertTrue(bcc.isMandatoryCodec());
- } else {
- assertFalse(bcc.isMandatoryCodec());
- }
-
- if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC) {
- assertEquals("SBC", bcc.getCodecName());
- }
- if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC) {
- assertEquals("AAC", bcc.getCodecName());
- }
- if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX) {
- assertEquals("aptX", bcc.getCodecName());
- }
- if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD) {
- assertEquals("aptX HD", bcc.getCodecName());
- }
- if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC) {
- assertEquals("LDAC", bcc.getCodecName());
- }
- if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
- assertEquals("INVALID CODEC", bcc.getCodecName());
- }
-
- assertEquals(codec_type, bcc.getCodecType());
- assertEquals(codec_priority, bcc.getCodecPriority());
- assertEquals(sample_rate, bcc.getSampleRate());
- assertEquals(bits_per_sample, bcc.getBitsPerSample());
- assertEquals(channel_mode, bcc.getChannelMode());
- assertEquals(codec_specific1, bcc.getCodecSpecific1());
- assertEquals(codec_specific2, bcc.getCodecSpecific2());
- assertEquals(codec_specific3, bcc.getCodecSpecific3());
- assertEquals(codec_specific4, bcc.getCodecSpecific4());
- }
- }
-
- @SmallTest
- public void testBluetoothCodecConfig_equals() {
- BluetoothCodecConfig bcc1 =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- BluetoothCodecConfig bcc2_same =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
- assertTrue(bcc1.equals(bcc2_same));
-
- BluetoothCodecConfig bcc3_codec_type =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
- assertFalse(bcc1.equals(bcc3_codec_type));
-
- BluetoothCodecConfig bcc4_codec_priority =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
- assertFalse(bcc1.equals(bcc4_codec_priority));
-
- BluetoothCodecConfig bcc5_sample_rate =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
- assertFalse(bcc1.equals(bcc5_sample_rate));
-
- BluetoothCodecConfig bcc6_bits_per_sample =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_24,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
- assertFalse(bcc1.equals(bcc6_bits_per_sample));
-
- BluetoothCodecConfig bcc7_channel_mode =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
- assertFalse(bcc1.equals(bcc7_channel_mode));
-
- BluetoothCodecConfig bcc8_codec_specific1 =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1001, 2000, 3000, 4000);
- assertFalse(bcc1.equals(bcc8_codec_specific1));
-
- BluetoothCodecConfig bcc9_codec_specific2 =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2002, 3000, 4000);
- assertFalse(bcc1.equals(bcc9_codec_specific2));
-
- BluetoothCodecConfig bcc10_codec_specific3 =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3003, 4000);
- assertFalse(bcc1.equals(bcc10_codec_specific3));
-
- BluetoothCodecConfig bcc11_codec_specific4 =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4004);
- assertFalse(bcc1.equals(bcc11_codec_specific4));
- }
-
- private BluetoothCodecConfig buildBluetoothCodecConfig(int sourceCodecType,
- int codecPriority, int sampleRate, int bitsPerSample, int channelMode,
- long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4) {
- return new BluetoothCodecConfig.Builder()
- .setCodecType(sourceCodecType)
- .setCodecPriority(codecPriority)
- .setSampleRate(sampleRate)
- .setBitsPerSample(bitsPerSample)
- .setChannelMode(channelMode)
- .setCodecSpecific1(codecSpecific1)
- .setCodecSpecific2(codecSpecific2)
- .setCodecSpecific3(codecSpecific3)
- .setCodecSpecific4(codecSpecific4)
- .build();
-
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
deleted file mode 100644
index 1cb2dca..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Unit test cases for {@link BluetoothCodecStatus}.
- * <p>
- * To run this test, use:
- * runtest --path core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
- */
-public class BluetoothCodecStatusTest extends TestCase {
-
- // Codec configs: A and B are same; C is different
- private static final BluetoothCodecConfig config_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig config_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig config_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- // Local capabilities: A and B are same; C is different
- private static final BluetoothCodecConfig local_capability1_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability1_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability1_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
-
- private static final BluetoothCodecConfig local_capability2_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability2_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability2_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability3_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability3_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability3_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability4_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_24,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability4_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_24,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability4_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_24,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability5_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000 |
- BluetoothCodecConfig.SAMPLE_RATE_88200 |
- BluetoothCodecConfig.SAMPLE_RATE_96000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_32,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability5_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000 |
- BluetoothCodecConfig.SAMPLE_RATE_88200 |
- BluetoothCodecConfig.SAMPLE_RATE_96000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_32,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig local_capability5_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000 |
- BluetoothCodecConfig.SAMPLE_RATE_88200 |
- BluetoothCodecConfig.SAMPLE_RATE_96000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_32,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
-
- // Selectable capabilities: A and B are same; C is different
- private static final BluetoothCodecConfig selectable_capability1_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability1_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability1_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability2_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability2_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability2_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability3_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability3_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability3_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability4_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_24,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability4_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_24,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability4_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100,
- BluetoothCodecConfig.BITS_PER_SAMPLE_24,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability5_A =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000 |
- BluetoothCodecConfig.SAMPLE_RATE_88200 |
- BluetoothCodecConfig.SAMPLE_RATE_96000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_32,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability5_B =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000 |
- BluetoothCodecConfig.SAMPLE_RATE_88200 |
- BluetoothCodecConfig.SAMPLE_RATE_96000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_32,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO |
- BluetoothCodecConfig.CHANNEL_MODE_MONO,
- 1000, 2000, 3000, 4000);
-
- private static final BluetoothCodecConfig selectable_capability5_C =
- buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
- BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
- BluetoothCodecConfig.SAMPLE_RATE_44100 |
- BluetoothCodecConfig.SAMPLE_RATE_48000 |
- BluetoothCodecConfig.SAMPLE_RATE_88200 |
- BluetoothCodecConfig.SAMPLE_RATE_96000,
- BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
- BluetoothCodecConfig.BITS_PER_SAMPLE_32,
- BluetoothCodecConfig.CHANNEL_MODE_STEREO,
- 1000, 2000, 3000, 4000);
-
- private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_A =
- new ArrayList() {{
- add(local_capability1_A);
- add(local_capability2_A);
- add(local_capability3_A);
- add(local_capability4_A);
- add(local_capability5_A);
- }};
-
- private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B =
- new ArrayList() {{
- add(local_capability1_B);
- add(local_capability2_B);
- add(local_capability3_B);
- add(local_capability4_B);
- add(local_capability5_B);
- }};
-
- private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B_REORDERED =
- new ArrayList() {{
- add(local_capability5_B);
- add(local_capability4_B);
- add(local_capability2_B);
- add(local_capability3_B);
- add(local_capability1_B);
- }};
-
- private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_C =
- new ArrayList() {{
- add(local_capability1_C);
- add(local_capability2_C);
- add(local_capability3_C);
- add(local_capability4_C);
- add(local_capability5_C);
- }};
-
- private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_A =
- new ArrayList() {{
- add(selectable_capability1_A);
- add(selectable_capability2_A);
- add(selectable_capability3_A);
- add(selectable_capability4_A);
- add(selectable_capability5_A);
- }};
-
- private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B =
- new ArrayList() {{
- add(selectable_capability1_B);
- add(selectable_capability2_B);
- add(selectable_capability3_B);
- add(selectable_capability4_B);
- add(selectable_capability5_B);
- }};
-
- private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B_REORDERED =
- new ArrayList() {{
- add(selectable_capability5_B);
- add(selectable_capability4_B);
- add(selectable_capability2_B);
- add(selectable_capability3_B);
- add(selectable_capability1_B);
- }};
-
- private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_C =
- new ArrayList() {{
- add(selectable_capability1_C);
- add(selectable_capability2_C);
- add(selectable_capability3_C);
- add(selectable_capability4_C);
- add(selectable_capability5_C);
- }};
-
- private static final BluetoothCodecStatus bcs_A =
- new BluetoothCodecStatus(config_A, LOCAL_CAPABILITY_A, SELECTABLE_CAPABILITY_A);
- private static final BluetoothCodecStatus bcs_B =
- new BluetoothCodecStatus(config_B, LOCAL_CAPABILITY_B, SELECTABLE_CAPABILITY_B);
- private static final BluetoothCodecStatus bcs_B_reordered =
- new BluetoothCodecStatus(config_B, LOCAL_CAPABILITY_B_REORDERED,
- SELECTABLE_CAPABILITY_B_REORDERED);
- private static final BluetoothCodecStatus bcs_C =
- new BluetoothCodecStatus(config_C, LOCAL_CAPABILITY_C, SELECTABLE_CAPABILITY_C);
-
- @SmallTest
- public void testBluetoothCodecStatus_get_methods() {
-
- assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_A));
- assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_B));
- assertFalse(Objects.equals(bcs_A.getCodecConfig(), config_C));
-
- assertTrue(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_A));
- assertTrue(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_B));
- assertFalse(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_C));
-
- assertTrue(bcs_A.getCodecsSelectableCapabilities()
- .equals(SELECTABLE_CAPABILITY_A));
- assertTrue(bcs_A.getCodecsSelectableCapabilities()
- .equals(SELECTABLE_CAPABILITY_B));
- assertFalse(bcs_A.getCodecsSelectableCapabilities()
- .equals(SELECTABLE_CAPABILITY_C));
- }
-
- @SmallTest
- public void testBluetoothCodecStatus_equals() {
- assertTrue(bcs_A.equals(bcs_B));
- assertTrue(bcs_B.equals(bcs_A));
- assertTrue(bcs_A.equals(bcs_B_reordered));
- assertTrue(bcs_B_reordered.equals(bcs_A));
- assertFalse(bcs_A.equals(bcs_C));
- assertFalse(bcs_C.equals(bcs_A));
- }
-
- private static BluetoothCodecConfig buildBluetoothCodecConfig(int sourceCodecType,
- int codecPriority, int sampleRate, int bitsPerSample, int channelMode,
- long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4) {
- return new BluetoothCodecConfig.Builder()
- .setCodecType(sourceCodecType)
- .setCodecPriority(codecPriority)
- .setSampleRate(sampleRate)
- .setBitsPerSample(bitsPerSample)
- .setChannelMode(channelMode)
- .setCodecSpecific1(codecSpecific1)
- .setCodecSpecific2(codecSpecific2)
- .setCodecSpecific3(codecSpecific3)
- .setCodecSpecific4(codecSpecific4)
- .build();
-
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
deleted file mode 100644
index 37b2a50..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.bluetooth;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.os.Bundle;
-
-import junit.framework.Assert;
-
-import java.util.Set;
-
-public class BluetoothInstrumentation extends Instrumentation {
-
- private BluetoothTestUtils mUtils = null;
- private BluetoothAdapter mAdapter = null;
- private Bundle mArgs = null;
- private Bundle mSuccessResult = null;
-
- private BluetoothTestUtils getBluetoothTestUtils() {
- if (mUtils == null) {
- mUtils = new BluetoothTestUtils(getContext(),
- BluetoothInstrumentation.class.getSimpleName());
- }
- return mUtils;
- }
-
- private BluetoothAdapter getBluetoothAdapter() {
- if (mAdapter == null) {
- mAdapter = ((BluetoothManager)getContext().getSystemService(
- Context.BLUETOOTH_SERVICE)).getAdapter();
- }
- return mAdapter;
- }
-
- @Override
- public void onCreate(Bundle arguments) {
- super.onCreate(arguments);
- mArgs = arguments;
- // create the default result response, but only use it in success code path
- mSuccessResult = new Bundle();
- mSuccessResult.putString("result", "SUCCESS");
- start();
- }
-
- @Override
- public void onStart() {
- String command = mArgs.getString("command");
- if ("enable".equals(command)) {
- enable();
- } else if ("disable".equals(command)) {
- disable();
- } else if ("unpairAll".equals(command)) {
- unpairAll();
- } else if ("getName".equals(command)) {
- getName();
- } else if ("getAddress".equals(command)) {
- getAddress();
- } else if ("getBondedDevices".equals(command)) {
- getBondedDevices();
- } else {
- finish(null);
- }
- }
-
- public void enable() {
- getBluetoothTestUtils().enable(getBluetoothAdapter());
- finish(mSuccessResult);
- }
-
- public void disable() {
- getBluetoothTestUtils().disable(getBluetoothAdapter());
- finish(mSuccessResult);
- }
-
- public void unpairAll() {
- getBluetoothTestUtils().unpairAll(getBluetoothAdapter());
- finish(mSuccessResult);
- }
-
- public void getName() {
- String name = getBluetoothAdapter().getName();
- mSuccessResult.putString("name", name);
- finish(mSuccessResult);
- }
-
- public void getAddress() {
- String name = getBluetoothAdapter().getAddress();
- mSuccessResult.putString("address", name);
- finish(mSuccessResult);
- }
-
- public void getBondedDevices() {
- Set<BluetoothDevice> devices = getBluetoothAdapter().getBondedDevices();
- int i = 0;
- for (BluetoothDevice device : devices) {
- mSuccessResult.putString(String.format("device-%02d", i), device.getAddress());
- i++;
- }
- finish(mSuccessResult);
- }
-
- public void finish(Bundle result) {
- if (result == null) {
- result = new Bundle();
- }
- finish(Activity.RESULT_OK, result);
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java
deleted file mode 100644
index c3d707c..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java
+++ /dev/null
@@ -1,58 +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.bluetooth;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for {@link BluetoothLeAudioCodecConfig}.
- */
-public class BluetoothLeAudioCodecConfigTest extends TestCase {
- private int[] mCodecTypeArray = new int[] {
- BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3,
- BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID,
- };
-
- @SmallTest
- public void testBluetoothLeAudioCodecConfig_valid_get_methods() {
-
- for (int codecIdx = 0; codecIdx < mCodecTypeArray.length; codecIdx++) {
- int codecType = mCodecTypeArray[codecIdx];
-
- BluetoothLeAudioCodecConfig leAudioCodecConfig =
- buildBluetoothLeAudioCodecConfig(codecType);
-
- if (codecType == BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3) {
- assertEquals("LC3", leAudioCodecConfig.getCodecName());
- }
- if (codecType == BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
- assertEquals("INVALID CODEC", leAudioCodecConfig.getCodecName());
- }
-
- assertEquals(codecType, leAudioCodecConfig.getCodecType());
- }
- }
-
- private BluetoothLeAudioCodecConfig buildBluetoothLeAudioCodecConfig(int sourceCodecType) {
- return new BluetoothLeAudioCodecConfig.Builder()
- .setCodecType(sourceCodecType)
- .build();
-
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothRebootStressTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothRebootStressTest.java
deleted file mode 100644
index 33e9dd7..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothRebootStressTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2010 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.bluetooth;
-
-import android.content.Context;
-import android.test.InstrumentationTestCase;
-
-/**
- * Instrumentation test case for stress test involving rebooting the device.
- * <p>
- * This test case tests that bluetooth is enabled after a device reboot. Because
- * the device will reboot, the instrumentation must be driven by a script on the
- * host side.
- */
-public class BluetoothRebootStressTest extends InstrumentationTestCase {
- private static final String TAG = "BluetoothRebootStressTest";
- private static final String OUTPUT_FILE = "BluetoothRebootStressTestOutput.txt";
-
- private BluetoothTestUtils mTestUtils;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- Context context = getInstrumentation().getTargetContext();
- mTestUtils = new BluetoothTestUtils(context, TAG, OUTPUT_FILE);
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- mTestUtils.close();
- }
-
- /**
- * Test method used to start the test by turning bluetooth on.
- */
- public void testStart() {
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- mTestUtils.enable(adapter);
- }
-
- /**
- * Test method used in the middle iterations of the test to check if
- * bluetooth is on. Does not toggle bluetooth after the check. Assumes that
- * bluetooth has been turned on by {@code #testStart()}
- */
- public void testMiddleNoToggle() {
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
- assertTrue(adapter.isEnabled());
- }
-
- /**
- * Test method used in the middle iterations of the test to check if
- * bluetooth is on. Toggles bluetooth after the check. Assumes that
- * bluetooth has been turned on by {@code #testStart()}
- */
- public void testMiddleToggle() {
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
- assertTrue(adapter.isEnabled());
-
- mTestUtils.disable(adapter);
- mTestUtils.enable(adapter);
- }
-
- /**
- * Test method used in the stop the test by turning bluetooth off. Assumes
- * that bluetooth has been turned on by {@code #testStart()}
- */
- public void testStop() {
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
- assertTrue(adapter.isEnabled());
-
- mTestUtils.disable(adapter);
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java
deleted file mode 100644
index 89dbe3f..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (C) 2010 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.bluetooth;
-
-import android.content.Context;
-import android.test.InstrumentationTestCase;
-
-/**
- * Stress test suite for Bluetooth related functions.
- *
- * Includes tests for enabling/disabling bluetooth, enabling/disabling discoverable mode,
- * starting/stopping scans, connecting/disconnecting to HFP, A2DP, HID, PAN profiles, and verifying
- * that remote connections/disconnections occur for the PAN profile.
- * <p>
- * This test suite uses {@link android.bluetooth.BluetoothTestRunner} to for parameters such as the
- * number of iterations and the addresses of remote Bluetooth devices.
- */
-public class BluetoothStressTest extends InstrumentationTestCase {
- private static final String TAG = "BluetoothStressTest";
- private static final String OUTPUT_FILE = "BluetoothStressTestOutput.txt";
- /** The amount of time to sleep between issuing start/stop SCO in ms. */
- private static final long SCO_SLEEP_TIME = 2 * 1000;
-
- private BluetoothAdapter mAdapter;
- private BluetoothTestUtils mTestUtils;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- Context context = getInstrumentation().getTargetContext();
- mAdapter = BluetoothAdapter.getDefaultAdapter();
- mTestUtils = new BluetoothTestUtils(context, TAG, OUTPUT_FILE);
-
- // Start all tests in a disabled state.
- if (mAdapter.isEnabled()) {
- mTestUtils.disable(mAdapter);
- }
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- mTestUtils.close();
- }
-
- /**
- * Stress test for enabling and disabling Bluetooth.
- */
- public void testEnable() {
- int iterations = BluetoothTestRunner.sEnableIterations;
- if (iterations == 0) {
- return;
- }
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("enable iteration " + (i + 1) + " of " + iterations);
- mTestUtils.enable(mAdapter);
- mTestUtils.disable(mAdapter);
- }
- }
-
- /**
- * Stress test for putting the device in and taking the device out of discoverable mode.
- */
- public void testDiscoverable() {
- int iterations = BluetoothTestRunner.sDiscoverableIterations;
- if (iterations == 0) {
- return;
- }
-
- mTestUtils.enable(mAdapter);
- mTestUtils.undiscoverable(mAdapter);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("discoverable iteration " + (i + 1) + " of " + iterations);
- mTestUtils.discoverable(mAdapter);
- mTestUtils.undiscoverable(mAdapter);
- }
- }
-
- /**
- * Stress test for starting and stopping Bluetooth scans.
- */
- public void testScan() {
- int iterations = BluetoothTestRunner.sScanIterations;
- if (iterations == 0) {
- return;
- }
-
- mTestUtils.enable(mAdapter);
- mTestUtils.stopScan(mAdapter);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("scan iteration " + (i + 1) + " of " + iterations);
- mTestUtils.startScan(mAdapter);
- mTestUtils.stopScan(mAdapter);
- }
- }
-
- /**
- * Stress test for enabling and disabling the PAN NAP profile.
- */
- public void testEnablePan() {
- int iterations = BluetoothTestRunner.sEnablePanIterations;
- if (iterations == 0) {
- return;
- }
-
- mTestUtils.enable(mAdapter);
- mTestUtils.disablePan(mAdapter);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("testEnablePan iteration " + (i + 1) + " of "
- + iterations);
- mTestUtils.enablePan(mAdapter);
- mTestUtils.disablePan(mAdapter);
- }
- }
-
- /**
- * Stress test for pairing and unpairing with a remote device.
- * <p>
- * In this test, the local device initiates pairing with a remote device, and then unpairs with
- * the device after the pairing has successfully completed.
- */
- public void testPair() {
- int iterations = BluetoothTestRunner.sPairIterations;
- if (iterations == 0) {
- return;
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
- mTestUtils.enable(mAdapter);
- mTestUtils.unpair(mAdapter, device);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("pair iteration " + (i + 1) + " of " + iterations);
- mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
- BluetoothTestRunner.sDevicePairPin);
- mTestUtils.unpair(mAdapter, device);
- }
- }
-
- /**
- * Stress test for accepting a pairing request and unpairing with a remote device.
- * <p>
- * In this test, the local device waits for a pairing request from a remote device. It accepts
- * the request and then unpairs after the paring has successfully completed.
- */
- public void testAcceptPair() {
- int iterations = BluetoothTestRunner.sPairIterations;
- if (iterations == 0) {
- return;
- }
- BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
- mTestUtils.enable(mAdapter);
- mTestUtils.unpair(mAdapter, device);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("acceptPair iteration " + (i + 1) + " of " + iterations);
- mTestUtils.acceptPair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
- BluetoothTestRunner.sDevicePairPin);
- mTestUtils.unpair(mAdapter, device);
- }
- }
-
- /**
- * Stress test for connecting and disconnecting with an A2DP source.
- * <p>
- * In this test, the local device plays the role of an A2DP sink, and initiates connections and
- * disconnections with an A2DP source.
- */
- public void testConnectA2dp() {
- int iterations = BluetoothTestRunner.sConnectA2dpIterations;
- if (iterations == 0) {
- return;
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
- mTestUtils.enable(mAdapter);
- mTestUtils.unpair(mAdapter, device);
- mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
- BluetoothTestRunner.sDevicePairPin);
- mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.A2DP, null);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("connectA2dp iteration " + (i + 1) + " of " + iterations);
- mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.A2DP,
- String.format("connectA2dp(device=%s)", device));
- mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.A2DP,
- String.format("disconnectA2dp(device=%s)", device));
- }
-
- mTestUtils.unpair(mAdapter, device);
- }
-
- /**
- * Stress test for connecting and disconnecting the HFP with a hands free device.
- * <p>
- * In this test, the local device plays the role of an HFP audio gateway, and initiates
- * connections and disconnections with a hands free device.
- */
- public void testConnectHeadset() {
- int iterations = BluetoothTestRunner.sConnectHeadsetIterations;
- if (iterations == 0) {
- return;
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
- mTestUtils.enable(mAdapter);
- mTestUtils.unpair(mAdapter, device);
- mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
- BluetoothTestRunner.sDevicePairPin);
- mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("connectHeadset iteration " + (i + 1) + " of " + iterations);
- mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.HEADSET,
- String.format("connectHeadset(device=%s)", device));
- mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET,
- String.format("disconnectHeadset(device=%s)", device));
- }
-
- mTestUtils.unpair(mAdapter, device);
- }
-
- /**
- * Stress test for connecting and disconnecting with a HID device.
- * <p>
- * In this test, the local device plays the role of a HID host, and initiates connections and
- * disconnections with a HID device.
- */
- public void testConnectInput() {
- int iterations = BluetoothTestRunner.sConnectInputIterations;
- if (iterations == 0) {
- return;
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
- mTestUtils.enable(mAdapter);
- mTestUtils.unpair(mAdapter, device);
- mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
- BluetoothTestRunner.sDevicePairPin);
- mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HID_HOST, null);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("connectInput iteration " + (i + 1) + " of " + iterations);
- mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.HID_HOST,
- String.format("connectInput(device=%s)", device));
- mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HID_HOST,
- String.format("disconnectInput(device=%s)", device));
- }
-
- mTestUtils.unpair(mAdapter, device);
- }
-
- /**
- * Stress test for connecting and disconnecting with a PAN NAP.
- * <p>
- * In this test, the local device plays the role of a PANU, and initiates connections and
- * disconnections with a NAP.
- */
- public void testConnectPan() {
- int iterations = BluetoothTestRunner.sConnectPanIterations;
- if (iterations == 0) {
- return;
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
- mTestUtils.enable(mAdapter);
- mTestUtils.unpair(mAdapter, device);
- mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
- BluetoothTestRunner.sDevicePairPin);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("connectPan iteration " + (i + 1) + " of " + iterations);
- mTestUtils.connectPan(mAdapter, device);
- mTestUtils.disconnectPan(mAdapter, device);
- }
-
- mTestUtils.unpair(mAdapter, device);
- }
-
- /**
- * Stress test for verifying a PANU connecting and disconnecting with the device.
- * <p>
- * In this test, the local device plays the role of a NAP which a remote PANU connects and
- * disconnects from.
- */
- public void testIncomingPanConnection() {
- int iterations = BluetoothTestRunner.sConnectPanIterations;
- if (iterations == 0) {
- return;
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
- mTestUtils.enable(mAdapter);
- mTestUtils.disablePan(mAdapter);
- mTestUtils.enablePan(mAdapter);
- mTestUtils.unpair(mAdapter, device);
- mTestUtils.acceptPair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
- BluetoothTestRunner.sDevicePairPin);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("incomingPanConnection iteration " + (i + 1) + " of "
- + iterations);
- mTestUtils.incomingPanConnection(mAdapter, device);
- mTestUtils.incomingPanDisconnection(mAdapter, device);
- }
-
- mTestUtils.unpair(mAdapter, device);
- mTestUtils.disablePan(mAdapter);
- }
-
- /**
- * Stress test for verifying that AudioManager can open and close SCO connections.
- * <p>
- * In this test, a HSP connection is opened with an external headset and the SCO connection is
- * repeatibly opened and closed.
- */
- public void testStartStopSco() {
- int iterations = BluetoothTestRunner.sStartStopScoIterations;
- if (iterations == 0) {
- return;
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
- mTestUtils.enable(mAdapter);
- mTestUtils.unpair(mAdapter, device);
- mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
- BluetoothTestRunner.sDevicePairPin);
- mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
- mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
- mTestUtils.stopSco(mAdapter, device);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.writeOutput("startStopSco iteration " + (i + 1) + " of " + iterations);
- mTestUtils.startSco(mAdapter, device);
- sleep(SCO_SLEEP_TIME);
- mTestUtils.stopSco(mAdapter, device);
- sleep(SCO_SLEEP_TIME);
- }
-
- mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
- mTestUtils.unpair(mAdapter, device);
- }
-
- /* Make sure there is at least 1 unread message in the last week on remote device */
- public void testMceSetMessageStatus() {
- int iterations = BluetoothTestRunner.sMceSetMessageStatusIterations;
- if (iterations == 0) {
- return;
- }
-
- BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
- mTestUtils.enable(mAdapter);
- mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.MAP_CLIENT, null);
- mTestUtils.mceGetUnreadMessage(mAdapter, device);
-
- for (int i = 0; i < iterations; i++) {
- mTestUtils.mceSetMessageStatus(mAdapter, device, BluetoothMapClient.READ);
- mTestUtils.mceSetMessageStatus(mAdapter, device, BluetoothMapClient.UNREAD);
- }
-
- /**
- * It is hard to find device to support set undeleted status, so just
- * set deleted in 1 iteration
- **/
- mTestUtils.mceSetMessageStatus(mAdapter, device, BluetoothMapClient.DELETED);
- }
-
- private void sleep(long time) {
- try {
- Thread.sleep(time);
- } catch (InterruptedException e) {
- }
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java
deleted file mode 100644
index d19c2c3..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2010 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.bluetooth;
-
-import junit.framework.TestSuite;
-
-import android.os.Bundle;
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-import android.util.Log;
-
-/**
- * Instrumentation test runner for Bluetooth tests.
- * <p>
- * To run:
- * <pre>
- * {@code
- * adb shell am instrument \
- * [-e enable_iterations <iterations>] \
- * [-e discoverable_iterations <iterations>] \
- * [-e scan_iterations <iterations>] \
- * [-e enable_pan_iterations <iterations>] \
- * [-e pair_iterations <iterations>] \
- * [-e connect_a2dp_iterations <iterations>] \
- * [-e connect_headset_iterations <iterations>] \
- * [-e connect_input_iterations <iterations>] \
- * [-e connect_pan_iterations <iterations>] \
- * [-e start_stop_sco_iterations <iterations>] \
- * [-e mce_set_message_status_iterations <iterations>] \
- * [-e pair_address <address>] \
- * [-e headset_address <address>] \
- * [-e a2dp_address <address>] \
- * [-e input_address <address>] \
- * [-e pan_address <address>] \
- * [-e pair_pin <pin>] \
- * [-e pair_passkey <passkey>] \
- * -w com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner
- * }
- * </pre>
- */
-public class BluetoothTestRunner extends InstrumentationTestRunner {
- private static final String TAG = "BluetoothTestRunner";
-
- public static int sEnableIterations = 100;
- public static int sDiscoverableIterations = 1000;
- public static int sScanIterations = 1000;
- public static int sEnablePanIterations = 1000;
- public static int sPairIterations = 100;
- public static int sConnectHeadsetIterations = 100;
- public static int sConnectA2dpIterations = 100;
- public static int sConnectInputIterations = 100;
- public static int sConnectPanIterations = 100;
- public static int sStartStopScoIterations = 100;
- public static int sMceSetMessageStatusIterations = 100;
-
- public static String sDeviceAddress = "";
- public static byte[] sDevicePairPin = {'1', '2', '3', '4'};
- public static int sDevicePairPasskey = 123456;
-
- @Override
- public TestSuite getAllTests() {
- TestSuite suite = new InstrumentationTestSuite(this);
- suite.addTestSuite(BluetoothStressTest.class);
- return suite;
- }
-
- @Override
- public ClassLoader getLoader() {
- return BluetoothTestRunner.class.getClassLoader();
- }
-
- @Override
- public void onCreate(Bundle arguments) {
- String val = arguments.getString("enable_iterations");
- if (val != null) {
- try {
- sEnableIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("discoverable_iterations");
- if (val != null) {
- try {
- sDiscoverableIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("scan_iterations");
- if (val != null) {
- try {
- sScanIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("enable_pan_iterations");
- if (val != null) {
- try {
- sEnablePanIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("pair_iterations");
- if (val != null) {
- try {
- sPairIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("connect_a2dp_iterations");
- if (val != null) {
- try {
- sConnectA2dpIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("connect_headset_iterations");
- if (val != null) {
- try {
- sConnectHeadsetIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("connect_input_iterations");
- if (val != null) {
- try {
- sConnectInputIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("connect_pan_iterations");
- if (val != null) {
- try {
- sConnectPanIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("start_stop_sco_iterations");
- if (val != null) {
- try {
- sStartStopScoIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("mce_set_message_status_iterations");
- if (val != null) {
- try {
- sMceSetMessageStatusIterations = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- val = arguments.getString("device_address");
- if (val != null) {
- sDeviceAddress = val;
- }
-
- val = arguments.getString("device_pair_pin");
- if (val != null) {
- byte[] pin = BluetoothDevice.convertPinToBytes(val);
- if (pin != null) {
- sDevicePairPin = pin;
- }
- }
-
- val = arguments.getString("device_pair_passkey");
- if (val != null) {
- try {
- sDevicePairPasskey = Integer.parseInt(val);
- } catch (NumberFormatException e) {
- // Invalid argument, fall back to default value
- }
- }
-
- Log.i(TAG, String.format("enable_iterations=%d", sEnableIterations));
- Log.i(TAG, String.format("discoverable_iterations=%d", sDiscoverableIterations));
- Log.i(TAG, String.format("scan_iterations=%d", sScanIterations));
- Log.i(TAG, String.format("pair_iterations=%d", sPairIterations));
- Log.i(TAG, String.format("connect_a2dp_iterations=%d", sConnectA2dpIterations));
- Log.i(TAG, String.format("connect_headset_iterations=%d", sConnectHeadsetIterations));
- Log.i(TAG, String.format("connect_input_iterations=%d", sConnectInputIterations));
- Log.i(TAG, String.format("connect_pan_iterations=%d", sConnectPanIterations));
- Log.i(TAG, String.format("start_stop_sco_iterations=%d", sStartStopScoIterations));
- Log.i(TAG, String.format("device_address=%s", sDeviceAddress));
- Log.i(TAG, String.format("device_pair_pin=%s", new String(sDevicePairPin)));
- Log.i(TAG, String.format("device_pair_passkey=%d", sDevicePairPasskey));
-
- // Call onCreate last since we want to set the static variables first.
- super.onCreate(arguments);
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
deleted file mode 100644
index 409025b..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ /dev/null
@@ -1,1649 +0,0 @@
-/*
- * Copyright (C) 2010 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.bluetooth;
-
-import android.bluetooth.BluetoothPan;
-import android.bluetooth.BluetoothProfile;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.media.AudioManager;
-import android.os.Environment;
-import android.util.Log;
-
-import junit.framework.Assert;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-public class BluetoothTestUtils extends Assert {
-
- /** Timeout for enable/disable in ms. */
- private static final int ENABLE_DISABLE_TIMEOUT = 20000;
- /** Timeout for discoverable/undiscoverable in ms. */
- private static final int DISCOVERABLE_UNDISCOVERABLE_TIMEOUT = 5000;
- /** Timeout for starting/stopping a scan in ms. */
- private static final int START_STOP_SCAN_TIMEOUT = 5000;
- /** Timeout for pair/unpair in ms. */
- private static final int PAIR_UNPAIR_TIMEOUT = 20000;
- /** Timeout for connecting/disconnecting a profile in ms. */
- private static final int CONNECT_DISCONNECT_PROFILE_TIMEOUT = 20000;
- /** Timeout to start or stop a SCO channel in ms. */
- private static final int START_STOP_SCO_TIMEOUT = 10000;
- /** Timeout to connect a profile proxy in ms. */
- private static final int CONNECT_PROXY_TIMEOUT = 5000;
- /** Time between polls in ms. */
- private static final int POLL_TIME = 100;
- /** Timeout to get map message in ms. */
- private static final int GET_UNREAD_MESSAGE_TIMEOUT = 10000;
- /** Timeout to set map message status in ms. */
- private static final int SET_MESSAGE_STATUS_TIMEOUT = 2000;
-
- private abstract class FlagReceiver extends BroadcastReceiver {
- private int mExpectedFlags = 0;
- private int mFiredFlags = 0;
- private long mCompletedTime = -1;
-
- public FlagReceiver(int expectedFlags) {
- mExpectedFlags = expectedFlags;
- }
-
- public int getFiredFlags() {
- synchronized (this) {
- return mFiredFlags;
- }
- }
-
- public long getCompletedTime() {
- synchronized (this) {
- return mCompletedTime;
- }
- }
-
- protected void setFiredFlag(int flag) {
- synchronized (this) {
- mFiredFlags |= flag;
- if ((mFiredFlags & mExpectedFlags) == mExpectedFlags) {
- mCompletedTime = System.currentTimeMillis();
- }
- }
- }
- }
-
- private class BluetoothReceiver extends FlagReceiver {
- private static final int DISCOVERY_STARTED_FLAG = 1;
- private static final int DISCOVERY_FINISHED_FLAG = 1 << 1;
- private static final int SCAN_MODE_NONE_FLAG = 1 << 2;
- private static final int SCAN_MODE_CONNECTABLE_FLAG = 1 << 3;
- private static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG = 1 << 4;
- private static final int STATE_OFF_FLAG = 1 << 5;
- private static final int STATE_TURNING_ON_FLAG = 1 << 6;
- private static final int STATE_ON_FLAG = 1 << 7;
- private static final int STATE_TURNING_OFF_FLAG = 1 << 8;
- private static final int STATE_GET_MESSAGE_FINISHED_FLAG = 1 << 9;
- private static final int STATE_SET_MESSAGE_STATUS_FINISHED_FLAG = 1 << 10;
-
- public BluetoothReceiver(int expectedFlags) {
- super(expectedFlags);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
- setFiredFlag(DISCOVERY_STARTED_FLAG);
- } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
- setFiredFlag(DISCOVERY_FINISHED_FLAG);
- } else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) {
- int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, -1);
- assertNotSame(-1, mode);
- switch (mode) {
- case BluetoothAdapter.SCAN_MODE_NONE:
- setFiredFlag(SCAN_MODE_NONE_FLAG);
- break;
- case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
- setFiredFlag(SCAN_MODE_CONNECTABLE_FLAG);
- break;
- case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
- setFiredFlag(SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG);
- break;
- }
- } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
- int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
- assertNotSame(-1, state);
- switch (state) {
- case BluetoothAdapter.STATE_OFF:
- setFiredFlag(STATE_OFF_FLAG);
- break;
- case BluetoothAdapter.STATE_TURNING_ON:
- setFiredFlag(STATE_TURNING_ON_FLAG);
- break;
- case BluetoothAdapter.STATE_ON:
- setFiredFlag(STATE_ON_FLAG);
- break;
- case BluetoothAdapter.STATE_TURNING_OFF:
- setFiredFlag(STATE_TURNING_OFF_FLAG);
- break;
- }
- }
- }
- }
-
- private class PairReceiver extends FlagReceiver {
- private static final int STATE_BONDED_FLAG = 1;
- private static final int STATE_BONDING_FLAG = 1 << 1;
- private static final int STATE_NONE_FLAG = 1 << 2;
-
- private BluetoothDevice mDevice;
- private int mPasskey;
- private byte[] mPin;
-
- public PairReceiver(BluetoothDevice device, int passkey, byte[] pin, int expectedFlags) {
- super(expectedFlags);
-
- mDevice = device;
- mPasskey = passkey;
- mPin = pin;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
- return;
- }
-
- if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
- int varient = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, -1);
- assertNotSame(-1, varient);
- switch (varient) {
- case BluetoothDevice.PAIRING_VARIANT_PIN:
- case BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS:
- mDevice.setPin(mPin);
- break;
- case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
- break;
- case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
- case BluetoothDevice.PAIRING_VARIANT_CONSENT:
- mDevice.setPairingConfirmation(true);
- break;
- case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
- break;
- }
- } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
- int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
- assertNotSame(-1, state);
- switch (state) {
- case BluetoothDevice.BOND_NONE:
- setFiredFlag(STATE_NONE_FLAG);
- break;
- case BluetoothDevice.BOND_BONDING:
- setFiredFlag(STATE_BONDING_FLAG);
- break;
- case BluetoothDevice.BOND_BONDED:
- setFiredFlag(STATE_BONDED_FLAG);
- break;
- }
- }
- }
- }
-
- private class ConnectProfileReceiver extends FlagReceiver {
- private static final int STATE_DISCONNECTED_FLAG = 1;
- private static final int STATE_CONNECTING_FLAG = 1 << 1;
- private static final int STATE_CONNECTED_FLAG = 1 << 2;
- private static final int STATE_DISCONNECTING_FLAG = 1 << 3;
-
- private BluetoothDevice mDevice;
- private int mProfile;
- private String mConnectionAction;
-
- public ConnectProfileReceiver(BluetoothDevice device, int profile, int expectedFlags) {
- super(expectedFlags);
-
- mDevice = device;
- mProfile = profile;
-
- switch (mProfile) {
- case BluetoothProfile.A2DP:
- mConnectionAction = BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED;
- break;
- case BluetoothProfile.HEADSET:
- mConnectionAction = BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED;
- break;
- case BluetoothProfile.HID_HOST:
- mConnectionAction = BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED;
- break;
- case BluetoothProfile.PAN:
- mConnectionAction = BluetoothPan.ACTION_CONNECTION_STATE_CHANGED;
- break;
- case BluetoothProfile.MAP_CLIENT:
- mConnectionAction = BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED;
- break;
- default:
- mConnectionAction = null;
- }
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (mConnectionAction != null && mConnectionAction.equals(intent.getAction())) {
- if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
- return;
- }
-
- int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
- assertNotSame(-1, state);
- switch (state) {
- case BluetoothProfile.STATE_DISCONNECTED:
- setFiredFlag(STATE_DISCONNECTED_FLAG);
- break;
- case BluetoothProfile.STATE_CONNECTING:
- setFiredFlag(STATE_CONNECTING_FLAG);
- break;
- case BluetoothProfile.STATE_CONNECTED:
- setFiredFlag(STATE_CONNECTED_FLAG);
- break;
- case BluetoothProfile.STATE_DISCONNECTING:
- setFiredFlag(STATE_DISCONNECTING_FLAG);
- break;
- }
- }
- }
- }
-
- private class ConnectPanReceiver extends ConnectProfileReceiver {
- private int mRole;
-
- public ConnectPanReceiver(BluetoothDevice device, int role, int expectedFlags) {
- super(device, BluetoothProfile.PAN, expectedFlags);
-
- mRole = role;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (mRole != intent.getIntExtra(BluetoothPan.EXTRA_LOCAL_ROLE, -1)) {
- return;
- }
-
- super.onReceive(context, intent);
- }
- }
-
- private class StartStopScoReceiver extends FlagReceiver {
- private static final int STATE_CONNECTED_FLAG = 1;
- private static final int STATE_DISCONNECTED_FLAG = 1 << 1;
-
- public StartStopScoReceiver(int expectedFlags) {
- super(expectedFlags);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(intent.getAction())) {
- int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
- AudioManager.SCO_AUDIO_STATE_ERROR);
- assertNotSame(AudioManager.SCO_AUDIO_STATE_ERROR, state);
- switch(state) {
- case AudioManager.SCO_AUDIO_STATE_CONNECTED:
- setFiredFlag(STATE_CONNECTED_FLAG);
- break;
- case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
- setFiredFlag(STATE_DISCONNECTED_FLAG);
- break;
- }
- }
- }
- }
-
-
- private class MceSetMessageStatusReceiver extends FlagReceiver {
- private static final int MESSAGE_RECEIVED_FLAG = 1;
- private static final int STATUS_CHANGED_FLAG = 1 << 1;
-
- public MceSetMessageStatusReceiver(int expectedFlags) {
- super(expectedFlags);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (BluetoothMapClient.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
- String handle = intent.getStringExtra(BluetoothMapClient.EXTRA_MESSAGE_HANDLE);
- assertNotNull(handle);
- setFiredFlag(MESSAGE_RECEIVED_FLAG);
- mMsgHandle = handle;
- } else if (BluetoothMapClient.ACTION_MESSAGE_DELETED_STATUS_CHANGED.equals(intent.getAction())) {
- int result = intent.getIntExtra(BluetoothMapClient.EXTRA_RESULT_CODE, BluetoothMapClient.RESULT_FAILURE);
- assertEquals(result, BluetoothMapClient.RESULT_SUCCESS);
- setFiredFlag(STATUS_CHANGED_FLAG);
- } else if (BluetoothMapClient.ACTION_MESSAGE_READ_STATUS_CHANGED.equals(intent.getAction())) {
- int result = intent.getIntExtra(BluetoothMapClient.EXTRA_RESULT_CODE, BluetoothMapClient.RESULT_FAILURE);
- assertEquals(result, BluetoothMapClient.RESULT_SUCCESS);
- setFiredFlag(STATUS_CHANGED_FLAG);
- }
- }
- }
-
- private BluetoothProfile.ServiceListener mServiceListener =
- new BluetoothProfile.ServiceListener() {
- @Override
- public void onServiceConnected(int profile, BluetoothProfile proxy) {
- synchronized (this) {
- switch (profile) {
- case BluetoothProfile.A2DP:
- mA2dp = (BluetoothA2dp) proxy;
- break;
- case BluetoothProfile.HEADSET:
- mHeadset = (BluetoothHeadset) proxy;
- break;
- case BluetoothProfile.HID_HOST:
- mInput = (BluetoothHidHost) proxy;
- break;
- case BluetoothProfile.PAN:
- mPan = (BluetoothPan) proxy;
- break;
- case BluetoothProfile.MAP_CLIENT:
- mMce = (BluetoothMapClient) proxy;
- break;
- }
- }
- }
-
- @Override
- public void onServiceDisconnected(int profile) {
- synchronized (this) {
- switch (profile) {
- case BluetoothProfile.A2DP:
- mA2dp = null;
- break;
- case BluetoothProfile.HEADSET:
- mHeadset = null;
- break;
- case BluetoothProfile.HID_HOST:
- mInput = null;
- break;
- case BluetoothProfile.PAN:
- mPan = null;
- break;
- case BluetoothProfile.MAP_CLIENT:
- mMce = null;
- break;
- }
- }
- }
- };
-
- private List<BroadcastReceiver> mReceivers = new ArrayList<BroadcastReceiver>();
-
- private BufferedWriter mOutputWriter;
- private String mTag;
- private String mOutputFile;
-
- private Context mContext;
- private BluetoothA2dp mA2dp = null;
- private BluetoothHeadset mHeadset = null;
- private BluetoothHidHost mInput = null;
- private BluetoothPan mPan = null;
- private BluetoothMapClient mMce = null;
- private String mMsgHandle = null;
-
- /**
- * Creates a utility instance for testing Bluetooth.
- *
- * @param context The context of the application using the utility.
- * @param tag The log tag of the application using the utility.
- */
- public BluetoothTestUtils(Context context, String tag) {
- this(context, tag, null);
- }
-
- /**
- * Creates a utility instance for testing Bluetooth.
- *
- * @param context The context of the application using the utility.
- * @param tag The log tag of the application using the utility.
- * @param outputFile The path to an output file if the utility is to write results to a
- * separate file.
- */
- public BluetoothTestUtils(Context context, String tag, String outputFile) {
- mContext = context;
- mTag = tag;
- mOutputFile = outputFile;
-
- if (mOutputFile == null) {
- mOutputWriter = null;
- } else {
- try {
- mOutputWriter = new BufferedWriter(new FileWriter(new File(
- Environment.getExternalStorageDirectory(), mOutputFile), true));
- } catch (IOException e) {
- Log.w(mTag, "Test output file could not be opened", e);
- mOutputWriter = null;
- }
- }
- }
-
- /**
- * Closes the utility instance and unregisters any BroadcastReceivers.
- */
- public void close() {
- while (!mReceivers.isEmpty()) {
- mContext.unregisterReceiver(mReceivers.remove(0));
- }
-
- if (mOutputWriter != null) {
- try {
- mOutputWriter.close();
- } catch (IOException e) {
- Log.w(mTag, "Test output file could not be closed", e);
- }
- }
- }
-
- /**
- * Enables Bluetooth and checks to make sure that Bluetooth was turned on and that the correct
- * actions were broadcast.
- *
- * @param adapter The BT adapter.
- */
- public void enable(BluetoothAdapter adapter) {
- writeOutput("Enabling Bluetooth adapter.");
- assertFalse(adapter.isEnabled());
- int btState = adapter.getState();
- final Semaphore completionSemaphore = new Semaphore(0);
- final BroadcastReceiver receiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (!BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
- return;
- }
- final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
- BluetoothAdapter.ERROR);
- if (state == BluetoothAdapter.STATE_ON) {
- completionSemaphore.release();
- }
- }
- };
-
- final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
- mContext.registerReceiver(receiver, filter);
- // Note: for Wear Local Edition builds, which have Permission Review Mode enabled to
- // obey China CMIIT, BluetoothAdapter may not startup immediately on methods enable/disable.
- // So no assertion applied here.
- adapter.enable();
- boolean success = false;
- try {
- success = completionSemaphore.tryAcquire(ENABLE_DISABLE_TIMEOUT, TimeUnit.MILLISECONDS);
- writeOutput(String.format("enable() completed in 0 ms"));
- } catch (final InterruptedException e) {
- // This should never happen but just in case it does, the test will fail anyway.
- }
- mContext.unregisterReceiver(receiver);
- if (!success) {
- fail(String.format("enable() timeout: state=%d (expected %d)", btState,
- BluetoothAdapter.STATE_ON));
- }
- }
-
- /**
- * Disables Bluetooth and checks to make sure that Bluetooth was turned off and that the correct
- * actions were broadcast.
- *
- * @param adapter The BT adapter.
- */
- public void disable(BluetoothAdapter adapter) {
- writeOutput("Disabling Bluetooth adapter.");
- assertTrue(adapter.isEnabled());
- int btState = adapter.getState();
- final Semaphore completionSemaphore = new Semaphore(0);
- final BroadcastReceiver receiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (!BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
- return;
- }
- final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
- BluetoothAdapter.ERROR);
- if (state == BluetoothAdapter.STATE_OFF) {
- completionSemaphore.release();
- }
- }
- };
-
- final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
- mContext.registerReceiver(receiver, filter);
- // Note: for Wear Local Edition builds, which have Permission Review Mode enabled to
- // obey China CMIIT, BluetoothAdapter may not startup immediately on methods enable/disable.
- // So no assertion applied here.
- adapter.disable();
- boolean success = false;
- try {
- success = completionSemaphore.tryAcquire(ENABLE_DISABLE_TIMEOUT, TimeUnit.MILLISECONDS);
- writeOutput(String.format("disable() completed in 0 ms"));
- } catch (final InterruptedException e) {
- // This should never happen but just in case it does, the test will fail anyway.
- }
- mContext.unregisterReceiver(receiver);
- if (!success) {
- fail(String.format("disable() timeout: state=%d (expected %d)", btState,
- BluetoothAdapter.STATE_OFF));
- }
- }
-
- /**
- * Puts the local device into discoverable mode and checks to make sure that the local device
- * is in discoverable mode and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- */
- public void discoverable(BluetoothAdapter adapter) {
- if (!adapter.isEnabled()) {
- fail("discoverable() bluetooth not enabled");
- }
-
- int scanMode = adapter.getScanMode();
- if (scanMode != BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
- return;
- }
-
- final Semaphore completionSemaphore = new Semaphore(0);
- final BroadcastReceiver receiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (!BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {
- return;
- }
- final int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,
- BluetoothAdapter.SCAN_MODE_NONE);
- if (mode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
- completionSemaphore.release();
- }
- }
- };
-
- final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
- mContext.registerReceiver(receiver, filter);
- assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
- boolean success = false;
- try {
- success = completionSemaphore.tryAcquire(DISCOVERABLE_UNDISCOVERABLE_TIMEOUT,
- TimeUnit.MILLISECONDS);
- writeOutput(String.format("discoverable() completed in 0 ms"));
- } catch (final InterruptedException e) {
- // This should never happen but just in case it does, the test will fail anyway.
- }
- mContext.unregisterReceiver(receiver);
- if (!success) {
- fail(String.format("discoverable() timeout: scanMode=%d (expected %d)", scanMode,
- BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
- }
- }
-
- /**
- * Puts the local device into connectable only mode and checks to make sure that the local
- * device is in in connectable mode and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- */
- public void undiscoverable(BluetoothAdapter adapter) {
- if (!adapter.isEnabled()) {
- fail("undiscoverable() bluetooth not enabled");
- }
-
- int scanMode = adapter.getScanMode();
- if (scanMode != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
- return;
- }
-
- final Semaphore completionSemaphore = new Semaphore(0);
- final BroadcastReceiver receiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (!BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {
- return;
- }
- final int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,
- BluetoothAdapter.SCAN_MODE_NONE);
- if (mode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
- completionSemaphore.release();
- }
- }
- };
-
- final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
- mContext.registerReceiver(receiver, filter);
- assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE));
- boolean success = false;
- try {
- success = completionSemaphore.tryAcquire(DISCOVERABLE_UNDISCOVERABLE_TIMEOUT,
- TimeUnit.MILLISECONDS);
- writeOutput(String.format("undiscoverable() completed in 0 ms"));
- } catch (InterruptedException e) {
- // This should never happen but just in case it does, the test will fail anyway.
- }
- mContext.unregisterReceiver(receiver);
- if (!success) {
- fail(String.format("undiscoverable() timeout: scanMode=%d (expected %d)", scanMode,
- BluetoothAdapter.SCAN_MODE_CONNECTABLE));
- }
- }
-
- /**
- * Starts a scan for remote devices and checks to make sure that the local device is scanning
- * and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- */
- public void startScan(BluetoothAdapter adapter) {
- int mask = BluetoothReceiver.DISCOVERY_STARTED_FLAG;
-
- if (!adapter.isEnabled()) {
- fail("startScan() bluetooth not enabled");
- }
-
- if (adapter.isDiscovering()) {
- return;
- }
-
- BluetoothReceiver receiver = getBluetoothReceiver(mask);
-
- long start = System.currentTimeMillis();
- assertTrue(adapter.startDiscovery());
-
- while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
- if (adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
- writeOutput(String.format("startScan() completed in %d ms",
- (receiver.getCompletedTime() - start)));
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("startScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)",
- adapter.isDiscovering(), firedFlags, mask));
- }
-
- /**
- * Stops a scan for remote devices and checks to make sure that the local device is not scanning
- * and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- */
- public void stopScan(BluetoothAdapter adapter) {
- int mask = BluetoothReceiver.DISCOVERY_FINISHED_FLAG;
-
- if (!adapter.isEnabled()) {
- fail("stopScan() bluetooth not enabled");
- }
-
- if (!adapter.isDiscovering()) {
- return;
- }
-
- BluetoothReceiver receiver = getBluetoothReceiver(mask);
-
- long start = System.currentTimeMillis();
- assertTrue(adapter.cancelDiscovery());
-
- while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
- if (!adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
- writeOutput(String.format("stopScan() completed in %d ms",
- (receiver.getCompletedTime() - start)));
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("stopScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)",
- adapter.isDiscovering(), firedFlags, mask));
-
- }
-
- /**
- * Enables PAN tethering on the local device and checks to make sure that tethering is enabled.
- *
- * @param adapter The BT adapter.
- */
- public void enablePan(BluetoothAdapter adapter) {
- if (mPan == null) mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
- assertNotNull(mPan);
-
- long start = System.currentTimeMillis();
- mPan.setBluetoothTethering(true);
- long stop = System.currentTimeMillis();
- assertTrue(mPan.isTetheringOn());
-
- writeOutput(String.format("enablePan() completed in %d ms", (stop - start)));
- }
-
- /**
- * Disables PAN tethering on the local device and checks to make sure that tethering is
- * disabled.
- *
- * @param adapter The BT adapter.
- */
- public void disablePan(BluetoothAdapter adapter) {
- if (mPan == null) mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
- assertNotNull(mPan);
-
- long start = System.currentTimeMillis();
- mPan.setBluetoothTethering(false);
- long stop = System.currentTimeMillis();
- assertFalse(mPan.isTetheringOn());
-
- writeOutput(String.format("disablePan() completed in %d ms", (stop - start)));
- }
-
- /**
- * Initiates a pairing with a remote device and checks to make sure that the devices are paired
- * and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
- * @param pin The pairing pin if pairing requires a pin. Any value if not.
- */
- public void pair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) {
- pairOrAcceptPair(adapter, device, passkey, pin, true);
- }
-
- /**
- * Accepts a pairing with a remote device and checks to make sure that the devices are paired
- * and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
- * @param pin The pairing pin if pairing requires a pin. Any value if not.
- */
- public void acceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
- byte[] pin) {
- pairOrAcceptPair(adapter, device, passkey, pin, false);
- }
-
- /**
- * Helper method used by {@link #pair(BluetoothAdapter, BluetoothDevice, int, byte[])} and
- * {@link #acceptPair(BluetoothAdapter, BluetoothDevice, int, byte[])} to either pair or accept
- * a pairing request.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
- * @param pin The pairing pin if pairing requires a pin. Any value if not.
- * @param shouldPair Whether to pair or accept the pair.
- */
- private void pairOrAcceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
- byte[] pin, boolean shouldPair) {
- int mask = PairReceiver.STATE_BONDING_FLAG | PairReceiver.STATE_BONDED_FLAG;
- long start = -1;
- String methodName;
- if (shouldPair) {
- methodName = String.format("pair(device=%s)", device);
- } else {
- methodName = String.format("acceptPair(device=%s)", device);
- }
-
- if (!adapter.isEnabled()) {
- fail(String.format("%s bluetooth not enabled", methodName));
- }
-
- PairReceiver receiver = getPairReceiver(device, passkey, pin, mask);
-
- int state = device.getBondState();
- switch (state) {
- case BluetoothDevice.BOND_NONE:
- assertFalse(adapter.getBondedDevices().contains(device));
- start = System.currentTimeMillis();
- if (shouldPair) {
- assertTrue(device.createBond());
- }
- break;
- case BluetoothDevice.BOND_BONDING:
- mask = 0; // Don't check for received intents since we might have missed them.
- break;
- case BluetoothDevice.BOND_BONDED:
- assertTrue(adapter.getBondedDevices().contains(device));
- return;
- default:
- removeReceiver(receiver);
- fail(String.format("%s invalid state: state=%d", methodName, state));
- }
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < PAIR_UNPAIR_TIMEOUT) {
- state = device.getBondState();
- if (state == BluetoothDevice.BOND_BONDED && (receiver.getFiredFlags() & mask) == mask) {
- assertTrue(adapter.getBondedDevices().contains(device));
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("%s completed in %d ms", methodName,
- (finish - start)));
- } else {
- writeOutput(String.format("%s completed", methodName));
- }
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
- methodName, state, BluetoothDevice.BOND_BONDED, firedFlags, mask));
- }
-
- /**
- * Deletes a pairing with a remote device and checks to make sure that the devices are unpaired
- * and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- */
- public void unpair(BluetoothAdapter adapter, BluetoothDevice device) {
- int mask = PairReceiver.STATE_NONE_FLAG;
- long start = -1;
- String methodName = String.format("unpair(device=%s)", device);
-
- if (!adapter.isEnabled()) {
- fail(String.format("%s bluetooth not enabled", methodName));
- }
-
- PairReceiver receiver = getPairReceiver(device, 0, null, mask);
-
- int state = device.getBondState();
- switch (state) {
- case BluetoothDevice.BOND_NONE:
- assertFalse(adapter.getBondedDevices().contains(device));
- removeReceiver(receiver);
- return;
- case BluetoothDevice.BOND_BONDING:
- start = System.currentTimeMillis();
- assertTrue(device.removeBond());
- break;
- case BluetoothDevice.BOND_BONDED:
- assertTrue(adapter.getBondedDevices().contains(device));
- start = System.currentTimeMillis();
- assertTrue(device.removeBond());
- break;
- default:
- removeReceiver(receiver);
- fail(String.format("%s invalid state: state=%d", methodName, state));
- }
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < PAIR_UNPAIR_TIMEOUT) {
- if (device.getBondState() == BluetoothDevice.BOND_NONE
- && (receiver.getFiredFlags() & mask) == mask) {
- assertFalse(adapter.getBondedDevices().contains(device));
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("%s completed in %d ms", methodName,
- (finish - start)));
- } else {
- writeOutput(String.format("%s completed", methodName));
- }
- removeReceiver(receiver);
- return;
- }
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
- methodName, state, BluetoothDevice.BOND_BONDED, firedFlags, mask));
- }
-
- /**
- * Deletes all pairings of remote devices
- * @param adapter the BT adapter
- */
- public void unpairAll(BluetoothAdapter adapter) {
- Set<BluetoothDevice> devices = adapter.getBondedDevices();
- for (BluetoothDevice device : devices) {
- unpair(adapter, device);
- }
- }
-
- /**
- * Connects a profile from the local device to a remote device and checks to make sure that the
- * profile is connected and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- * @param profile The profile to connect. One of {@link BluetoothProfile#A2DP},
- * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#HID_HOST} or {@link BluetoothProfile#MAP_CLIENT}..
- * @param methodName The method name to printed in the logs. If null, will be
- * "connectProfile(profile=<profile>, device=<device>)"
- */
- public void connectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile,
- String methodName) {
- if (methodName == null) {
- methodName = String.format("connectProfile(profile=%d, device=%s)", profile, device);
- }
- int mask = (ConnectProfileReceiver.STATE_CONNECTING_FLAG
- | ConnectProfileReceiver.STATE_CONNECTED_FLAG);
- long start = -1;
-
- if (!adapter.isEnabled()) {
- fail(String.format("%s bluetooth not enabled", methodName));
- }
-
- if (!adapter.getBondedDevices().contains(device)) {
- fail(String.format("%s device not paired", methodName));
- }
-
- BluetoothProfile proxy = connectProxy(adapter, profile);
- assertNotNull(proxy);
-
- ConnectProfileReceiver receiver = getConnectProfileReceiver(device, profile, mask);
-
- int state = proxy.getConnectionState(device);
- switch (state) {
- case BluetoothProfile.STATE_CONNECTED:
- removeReceiver(receiver);
- return;
- case BluetoothProfile.STATE_CONNECTING:
- mask = 0; // Don't check for received intents since we might have missed them.
- break;
- case BluetoothProfile.STATE_DISCONNECTED:
- case BluetoothProfile.STATE_DISCONNECTING:
- start = System.currentTimeMillis();
- if (profile == BluetoothProfile.A2DP) {
- assertTrue(((BluetoothA2dp)proxy).connect(device));
- } else if (profile == BluetoothProfile.HEADSET) {
- assertTrue(((BluetoothHeadset)proxy).connect(device));
- } else if (profile == BluetoothProfile.HID_HOST) {
- assertTrue(((BluetoothHidHost)proxy).connect(device));
- } else if (profile == BluetoothProfile.MAP_CLIENT) {
- assertTrue(((BluetoothMapClient)proxy).connect(device));
- }
- break;
- default:
- removeReceiver(receiver);
- fail(String.format("%s invalid state: state=%d", methodName, state));
- }
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
- state = proxy.getConnectionState(device);
- if (state == BluetoothProfile.STATE_CONNECTED
- && (receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("%s completed in %d ms", methodName,
- (finish - start)));
- } else {
- writeOutput(String.format("%s completed", methodName));
- }
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
- methodName, state, BluetoothProfile.STATE_CONNECTED, firedFlags, mask));
- }
-
- /**
- * Disconnects a profile between the local device and a remote device and checks to make sure
- * that the profile is disconnected and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- * @param profile The profile to disconnect. One of {@link BluetoothProfile#A2DP},
- * {@link BluetoothProfile#HEADSET}, or {@link BluetoothProfile#HID_HOST}.
- * @param methodName The method name to printed in the logs. If null, will be
- * "connectProfile(profile=<profile>, device=<device>)"
- */
- public void disconnectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile,
- String methodName) {
- if (methodName == null) {
- methodName = String.format("disconnectProfile(profile=%d, device=%s)", profile, device);
- }
- int mask = (ConnectProfileReceiver.STATE_DISCONNECTING_FLAG
- | ConnectProfileReceiver.STATE_DISCONNECTED_FLAG);
- long start = -1;
-
- if (!adapter.isEnabled()) {
- fail(String.format("%s bluetooth not enabled", methodName));
- }
-
- if (!adapter.getBondedDevices().contains(device)) {
- fail(String.format("%s device not paired", methodName));
- }
-
- BluetoothProfile proxy = connectProxy(adapter, profile);
- assertNotNull(proxy);
-
- ConnectProfileReceiver receiver = getConnectProfileReceiver(device, profile, mask);
-
- int state = proxy.getConnectionState(device);
- switch (state) {
- case BluetoothProfile.STATE_CONNECTED:
- case BluetoothProfile.STATE_CONNECTING:
- start = System.currentTimeMillis();
- if (profile == BluetoothProfile.A2DP) {
- assertTrue(((BluetoothA2dp)proxy).disconnect(device));
- } else if (profile == BluetoothProfile.HEADSET) {
- assertTrue(((BluetoothHeadset)proxy).disconnect(device));
- } else if (profile == BluetoothProfile.HID_HOST) {
- assertTrue(((BluetoothHidHost)proxy).disconnect(device));
- } else if (profile == BluetoothProfile.MAP_CLIENT) {
- assertTrue(((BluetoothMapClient)proxy).disconnect(device));
- }
- break;
- case BluetoothProfile.STATE_DISCONNECTED:
- removeReceiver(receiver);
- return;
- case BluetoothProfile.STATE_DISCONNECTING:
- mask = 0; // Don't check for received intents since we might have missed them.
- break;
- default:
- removeReceiver(receiver);
- fail(String.format("%s invalid state: state=%d", methodName, state));
- }
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
- state = proxy.getConnectionState(device);
- if (state == BluetoothProfile.STATE_DISCONNECTED
- && (receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("%s completed in %d ms", methodName,
- (finish - start)));
- } else {
- writeOutput(String.format("%s completed", methodName));
- }
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
- methodName, state, BluetoothProfile.STATE_DISCONNECTED, firedFlags, mask));
- }
-
- /**
- * Connects the PANU to a remote NAP and checks to make sure that the PANU is connected and that
- * the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- */
- public void connectPan(BluetoothAdapter adapter, BluetoothDevice device) {
- connectPanOrIncomingPanConnection(adapter, device, true);
- }
-
- /**
- * Checks that a remote PANU connects to the local NAP correctly and that the correct actions
- * were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- */
- public void incomingPanConnection(BluetoothAdapter adapter, BluetoothDevice device) {
- connectPanOrIncomingPanConnection(adapter, device, false);
- }
-
- /**
- * Helper method used by {@link #connectPan(BluetoothAdapter, BluetoothDevice)} and
- * {@link #incomingPanConnection(BluetoothAdapter, BluetoothDevice)} to either connect to a
- * remote NAP or verify that a remote device connected to the local NAP.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- * @param connect If the method should initiate the connection (is PANU)
- */
- private void connectPanOrIncomingPanConnection(BluetoothAdapter adapter, BluetoothDevice device,
- boolean connect) {
- long start = -1;
- int mask, role;
- String methodName;
-
- if (connect) {
- methodName = String.format("connectPan(device=%s)", device);
- mask = (ConnectProfileReceiver.STATE_CONNECTED_FLAG |
- ConnectProfileReceiver.STATE_CONNECTING_FLAG);
- role = BluetoothPan.LOCAL_PANU_ROLE;
- } else {
- methodName = String.format("incomingPanConnection(device=%s)", device);
- mask = ConnectProfileReceiver.STATE_CONNECTED_FLAG;
- role = BluetoothPan.LOCAL_NAP_ROLE;
- }
-
- if (!adapter.isEnabled()) {
- fail(String.format("%s bluetooth not enabled", methodName));
- }
-
- if (!adapter.getBondedDevices().contains(device)) {
- fail(String.format("%s device not paired", methodName));
- }
-
- mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
- assertNotNull(mPan);
- ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
-
- int state = mPan.getConnectionState(device);
- switch (state) {
- case BluetoothPan.STATE_CONNECTED:
- removeReceiver(receiver);
- return;
- case BluetoothPan.STATE_CONNECTING:
- mask = 0; // Don't check for received intents since we might have missed them.
- break;
- case BluetoothPan.STATE_DISCONNECTED:
- case BluetoothPan.STATE_DISCONNECTING:
- start = System.currentTimeMillis();
- if (role == BluetoothPan.LOCAL_PANU_ROLE) {
- Log.i("BT", "connect to pan");
- assertTrue(mPan.connect(device));
- }
- break;
- default:
- removeReceiver(receiver);
- fail(String.format("%s invalid state: state=%d", methodName, state));
- }
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
- state = mPan.getConnectionState(device);
- if (state == BluetoothPan.STATE_CONNECTED
- && (receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("%s completed in %d ms", methodName,
- (finish - start)));
- } else {
- writeOutput(String.format("%s completed", methodName));
- }
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)",
- methodName, state, BluetoothPan.STATE_CONNECTED, firedFlags, mask));
- }
-
- /**
- * Disconnects the PANU from a remote NAP and checks to make sure that the PANU is disconnected
- * and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- */
- public void disconnectPan(BluetoothAdapter adapter, BluetoothDevice device) {
- disconnectFromRemoteOrVerifyConnectNap(adapter, device, true);
- }
-
- /**
- * Checks that a remote PANU disconnects from the local NAP correctly and that the correct
- * actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- */
- public void incomingPanDisconnection(BluetoothAdapter adapter, BluetoothDevice device) {
- disconnectFromRemoteOrVerifyConnectNap(adapter, device, false);
- }
-
- /**
- * Helper method used by {@link #disconnectPan(BluetoothAdapter, BluetoothDevice)} and
- * {@link #incomingPanDisconnection(BluetoothAdapter, BluetoothDevice)} to either disconnect
- * from a remote NAP or verify that a remote device disconnected from the local NAP.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- * @param disconnect Whether the method should connect or verify.
- */
- private void disconnectFromRemoteOrVerifyConnectNap(BluetoothAdapter adapter,
- BluetoothDevice device, boolean disconnect) {
- long start = -1;
- int mask, role;
- String methodName;
-
- if (disconnect) {
- methodName = String.format("disconnectPan(device=%s)", device);
- mask = (ConnectProfileReceiver.STATE_DISCONNECTED_FLAG |
- ConnectProfileReceiver.STATE_DISCONNECTING_FLAG);
- role = BluetoothPan.LOCAL_PANU_ROLE;
- } else {
- methodName = String.format("incomingPanDisconnection(device=%s)", device);
- mask = ConnectProfileReceiver.STATE_DISCONNECTED_FLAG;
- role = BluetoothPan.LOCAL_NAP_ROLE;
- }
-
- if (!adapter.isEnabled()) {
- fail(String.format("%s bluetooth not enabled", methodName));
- }
-
- if (!adapter.getBondedDevices().contains(device)) {
- fail(String.format("%s device not paired", methodName));
- }
-
- mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
- assertNotNull(mPan);
- ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
-
- int state = mPan.getConnectionState(device);
- switch (state) {
- case BluetoothPan.STATE_CONNECTED:
- case BluetoothPan.STATE_CONNECTING:
- start = System.currentTimeMillis();
- if (role == BluetoothPan.LOCAL_PANU_ROLE) {
- assertTrue(mPan.disconnect(device));
- }
- break;
- case BluetoothPan.STATE_DISCONNECTED:
- removeReceiver(receiver);
- return;
- case BluetoothPan.STATE_DISCONNECTING:
- mask = 0; // Don't check for received intents since we might have missed them.
- break;
- default:
- removeReceiver(receiver);
- fail(String.format("%s invalid state: state=%d", methodName, state));
- }
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
- state = mPan.getConnectionState(device);
- if (state == BluetoothHidHost.STATE_DISCONNECTED
- && (receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("%s completed in %d ms", methodName,
- (finish - start)));
- } else {
- writeOutput(String.format("%s completed", methodName));
- }
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)",
- methodName, state, BluetoothHidHost.STATE_DISCONNECTED, firedFlags, mask));
- }
-
- /**
- * Opens a SCO channel using {@link android.media.AudioManager#startBluetoothSco()} and checks
- * to make sure that the channel is opened and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- */
- public void startSco(BluetoothAdapter adapter, BluetoothDevice device) {
- startStopSco(adapter, device, true);
- }
-
- /**
- * Closes a SCO channel using {@link android.media.AudioManager#stopBluetoothSco()} and checks
- * to make sure that the channel is closed and that the correct actions were broadcast.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- */
- public void stopSco(BluetoothAdapter adapter, BluetoothDevice device) {
- startStopSco(adapter, device, false);
- }
- /**
- * Helper method for {@link #startSco(BluetoothAdapter, BluetoothDevice)} and
- * {@link #stopSco(BluetoothAdapter, BluetoothDevice)}.
- *
- * @param adapter The BT adapter.
- * @param device The remote device.
- * @param isStart Whether the SCO channel should be opened.
- */
- private void startStopSco(BluetoothAdapter adapter, BluetoothDevice device, boolean isStart) {
- long start = -1;
- int mask;
- String methodName;
-
- if (isStart) {
- methodName = String.format("startSco(device=%s)", device);
- mask = StartStopScoReceiver.STATE_CONNECTED_FLAG;
- } else {
- methodName = String.format("stopSco(device=%s)", device);
- mask = StartStopScoReceiver.STATE_DISCONNECTED_FLAG;
- }
-
- if (!adapter.isEnabled()) {
- fail(String.format("%s bluetooth not enabled", methodName));
- }
-
- if (!adapter.getBondedDevices().contains(device)) {
- fail(String.format("%s device not paired", methodName));
- }
-
- AudioManager manager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- assertNotNull(manager);
-
- if (!manager.isBluetoothScoAvailableOffCall()) {
- fail(String.format("%s device does not support SCO", methodName));
- }
-
- boolean isScoOn = manager.isBluetoothScoOn();
- if (isStart == isScoOn) {
- return;
- }
-
- StartStopScoReceiver receiver = getStartStopScoReceiver(mask);
- start = System.currentTimeMillis();
- if (isStart) {
- manager.startBluetoothSco();
- } else {
- manager.stopBluetoothSco();
- }
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < START_STOP_SCO_TIMEOUT) {
- isScoOn = manager.isBluetoothScoOn();
- if (isStart == isScoOn && (receiver.getFiredFlags() & mask) == mask) {
- long finish = receiver.getCompletedTime();
- if (start != -1 && finish != -1) {
- writeOutput(String.format("%s completed in %d ms", methodName,
- (finish - start)));
- } else {
- writeOutput(String.format("%s completed", methodName));
- }
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("%s timeout: on=%b (expected %b), flags=0x%x (expected 0x%x)",
- methodName, isScoOn, isStart, firedFlags, mask));
- }
-
- /**
- * Writes a string to the logcat and a file if a file has been specified in the constructor.
- *
- * @param s The string to be written.
- */
- public void writeOutput(String s) {
- Log.i(mTag, s);
- if (mOutputWriter == null) {
- return;
- }
- try {
- mOutputWriter.write(s + "\n");
- mOutputWriter.flush();
- } catch (IOException e) {
- Log.w(mTag, "Could not write to output file", e);
- }
- }
-
- public void mceGetUnreadMessage(BluetoothAdapter adapter, BluetoothDevice device) {
- int mask;
- String methodName = "getUnreadMessage";
-
- if (!adapter.isEnabled()) {
- fail(String.format("%s bluetooth not enabled", methodName));
- }
-
- if (!adapter.getBondedDevices().contains(device)) {
- fail(String.format("%s device not paired", methodName));
- }
-
- mMce = (BluetoothMapClient) connectProxy(adapter, BluetoothProfile.MAP_CLIENT);
- assertNotNull(mMce);
-
- if (mMce.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
- fail(String.format("%s device is not connected", methodName));
- }
-
- mMsgHandle = null;
- mask = MceSetMessageStatusReceiver.MESSAGE_RECEIVED_FLAG;
- MceSetMessageStatusReceiver receiver = getMceSetMessageStatusReceiver(device, mask);
- assertTrue(mMce.getUnreadMessages(device));
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < GET_UNREAD_MESSAGE_TIMEOUT) {
- if ((receiver.getFiredFlags() & mask) == mask) {
- writeOutput(String.format("%s completed", methodName));
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)",
- methodName, mMce.getConnectionState(device), BluetoothMapClient.STATE_CONNECTED, firedFlags, mask));
- }
-
- /**
- * Set a message to read/unread/deleted/undeleted
- */
- public void mceSetMessageStatus(BluetoothAdapter adapter, BluetoothDevice device, int status) {
- int mask;
- String methodName = "setMessageStatus";
-
- if (!adapter.isEnabled()) {
- fail(String.format("%s bluetooth not enabled", methodName));
- }
-
- if (!adapter.getBondedDevices().contains(device)) {
- fail(String.format("%s device not paired", methodName));
- }
-
- mMce = (BluetoothMapClient) connectProxy(adapter, BluetoothProfile.MAP_CLIENT);
- assertNotNull(mMce);
-
- if (mMce.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
- fail(String.format("%s device is not connected", methodName));
- }
-
- assertNotNull(mMsgHandle);
- mask = MceSetMessageStatusReceiver.STATUS_CHANGED_FLAG;
- MceSetMessageStatusReceiver receiver = getMceSetMessageStatusReceiver(device, mask);
-
- assertTrue(mMce.setMessageStatus(device, mMsgHandle, status));
-
- long s = System.currentTimeMillis();
- while (System.currentTimeMillis() - s < SET_MESSAGE_STATUS_TIMEOUT) {
- if ((receiver.getFiredFlags() & mask) == mask) {
- writeOutput(String.format("%s completed", methodName));
- removeReceiver(receiver);
- return;
- }
- sleep(POLL_TIME);
- }
-
- int firedFlags = receiver.getFiredFlags();
- removeReceiver(receiver);
- fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)",
- methodName, mMce.getConnectionState(device), BluetoothPan.STATE_CONNECTED, firedFlags, mask));
- }
-
- private void addReceiver(BroadcastReceiver receiver, String[] actions) {
- IntentFilter filter = new IntentFilter();
- for (String action: actions) {
- filter.addAction(action);
- }
- mContext.registerReceiver(receiver, filter);
- mReceivers.add(receiver);
- }
-
- private BluetoothReceiver getBluetoothReceiver(int expectedFlags) {
- String[] actions = {
- BluetoothAdapter.ACTION_DISCOVERY_FINISHED,
- BluetoothAdapter.ACTION_DISCOVERY_STARTED,
- BluetoothAdapter.ACTION_SCAN_MODE_CHANGED,
- BluetoothAdapter.ACTION_STATE_CHANGED};
- BluetoothReceiver receiver = new BluetoothReceiver(expectedFlags);
- addReceiver(receiver, actions);
- return receiver;
- }
-
- private PairReceiver getPairReceiver(BluetoothDevice device, int passkey, byte[] pin,
- int expectedFlags) {
- String[] actions = {
- BluetoothDevice.ACTION_PAIRING_REQUEST,
- BluetoothDevice.ACTION_BOND_STATE_CHANGED};
- PairReceiver receiver = new PairReceiver(device, passkey, pin, expectedFlags);
- addReceiver(receiver, actions);
- return receiver;
- }
-
- private ConnectProfileReceiver getConnectProfileReceiver(BluetoothDevice device, int profile,
- int expectedFlags) {
- String[] actions = {
- BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED,
- BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED,
- BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED,
- BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED};
- ConnectProfileReceiver receiver = new ConnectProfileReceiver(device, profile,
- expectedFlags);
- addReceiver(receiver, actions);
- return receiver;
- }
-
- private ConnectPanReceiver getConnectPanReceiver(BluetoothDevice device, int role,
- int expectedFlags) {
- String[] actions = {BluetoothPan.ACTION_CONNECTION_STATE_CHANGED};
- ConnectPanReceiver receiver = new ConnectPanReceiver(device, role, expectedFlags);
- addReceiver(receiver, actions);
- return receiver;
- }
-
- private StartStopScoReceiver getStartStopScoReceiver(int expectedFlags) {
- String[] actions = {AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED};
- StartStopScoReceiver receiver = new StartStopScoReceiver(expectedFlags);
- addReceiver(receiver, actions);
- return receiver;
- }
-
- private MceSetMessageStatusReceiver getMceSetMessageStatusReceiver(BluetoothDevice device,
- int expectedFlags) {
- String[] actions = {BluetoothMapClient.ACTION_MESSAGE_RECEIVED,
- BluetoothMapClient.ACTION_MESSAGE_READ_STATUS_CHANGED,
- BluetoothMapClient.ACTION_MESSAGE_DELETED_STATUS_CHANGED};
- MceSetMessageStatusReceiver receiver = new MceSetMessageStatusReceiver(expectedFlags);
- addReceiver(receiver, actions);
- return receiver;
- }
-
- private void removeReceiver(BroadcastReceiver receiver) {
- mContext.unregisterReceiver(receiver);
- mReceivers.remove(receiver);
- }
-
- private BluetoothProfile connectProxy(BluetoothAdapter adapter, int profile) {
- switch (profile) {
- case BluetoothProfile.A2DP:
- if (mA2dp != null) {
- return mA2dp;
- }
- break;
- case BluetoothProfile.HEADSET:
- if (mHeadset != null) {
- return mHeadset;
- }
- break;
- case BluetoothProfile.HID_HOST:
- if (mInput != null) {
- return mInput;
- }
- break;
- case BluetoothProfile.PAN:
- if (mPan != null) {
- return mPan;
- }
- case BluetoothProfile.MAP_CLIENT:
- if (mMce != null) {
- return mMce;
- }
- break;
- default:
- return null;
- }
- adapter.getProfileProxy(mContext, mServiceListener, profile);
- long s = System.currentTimeMillis();
- switch (profile) {
- case BluetoothProfile.A2DP:
- while (mA2dp == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
- sleep(POLL_TIME);
- }
- return mA2dp;
- case BluetoothProfile.HEADSET:
- while (mHeadset == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
- sleep(POLL_TIME);
- }
- return mHeadset;
- case BluetoothProfile.HID_HOST:
- while (mInput == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
- sleep(POLL_TIME);
- }
- return mInput;
- case BluetoothProfile.PAN:
- while (mPan == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
- sleep(POLL_TIME);
- }
- return mPan;
- case BluetoothProfile.MAP_CLIENT:
- while (mMce == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
- sleep(POLL_TIME);
- }
- return mMce;
- default:
- return null;
- }
- }
-
- private void sleep(long time) {
- try {
- Thread.sleep(time);
- } catch (InterruptedException e) {
- }
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java
deleted file mode 100644
index 536d722..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.ParcelUuid;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for {@link BluetoothUuid}.
- * <p>
- * To run this test, use adb shell am instrument -e class 'android.bluetooth.BluetoothUuidTest' -w
- * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
-public class BluetoothUuidTest extends TestCase {
-
- @SmallTest
- public void testUuidParser() {
- byte[] uuid16 = new byte[] {
- 0x0B, 0x11 };
- assertEquals(ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"),
- BluetoothUuid.parseUuidFrom(uuid16));
-
- byte[] uuid32 = new byte[] {
- 0x0B, 0x11, 0x33, (byte) 0xFE };
- assertEquals(ParcelUuid.fromString("FE33110B-0000-1000-8000-00805F9B34FB"),
- BluetoothUuid.parseUuidFrom(uuid32));
-
- byte[] uuid128 = new byte[] {
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, (byte) 0xFF };
- assertEquals(ParcelUuid.fromString("FF0F0E0D-0C0B-0A09-0807-0060504030201"),
- BluetoothUuid.parseUuidFrom(uuid128));
- }
-
- @SmallTest
- public void testUuidType() {
- assertTrue(BluetoothUuid.is16BitUuid(
- ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB")));
- assertFalse(BluetoothUuid.is32BitUuid(
- ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB")));
-
- assertFalse(BluetoothUuid.is16BitUuid(
- ParcelUuid.fromString("FE33110B-0000-1000-8000-00805F9B34FB")));
- assertTrue(BluetoothUuid.is32BitUuid(
- ParcelUuid.fromString("FE33110B-0000-1000-8000-00805F9B34FB")));
- assertFalse(BluetoothUuid.is32BitUuid(
- ParcelUuid.fromString("FE33110B-1000-1000-8000-00805F9B34FB")));
-
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/AdvertiseDataTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/AdvertiseDataTest.java
deleted file mode 100644
index e58d905..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/AdvertiseDataTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for {@link AdvertiseData}.
- * <p>
- * To run the test, use adb shell am instrument -e class 'android.bluetooth.le.AdvertiseDataTest' -w
- * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
-public class AdvertiseDataTest extends TestCase {
-
- private AdvertiseData.Builder mAdvertiseDataBuilder;
-
- @Override
- protected void setUp() throws Exception {
- mAdvertiseDataBuilder = new AdvertiseData.Builder();
- }
-
- @SmallTest
- public void testEmptyData() {
- Parcel parcel = Parcel.obtain();
- AdvertiseData data = mAdvertiseDataBuilder.build();
- data.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- AdvertiseData dataFromParcel =
- AdvertiseData.CREATOR.createFromParcel(parcel);
- assertEquals(data, dataFromParcel);
- }
-
- @SmallTest
- public void testEmptyServiceUuid() {
- Parcel parcel = Parcel.obtain();
- AdvertiseData data = mAdvertiseDataBuilder.setIncludeDeviceName(true).build();
- data.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- AdvertiseData dataFromParcel =
- AdvertiseData.CREATOR.createFromParcel(parcel);
- assertEquals(data, dataFromParcel);
- }
-
- @SmallTest
- public void testEmptyManufacturerData() {
- Parcel parcel = Parcel.obtain();
- int manufacturerId = 50;
- byte[] manufacturerData = new byte[0];
- AdvertiseData data =
- mAdvertiseDataBuilder.setIncludeDeviceName(true)
- .addManufacturerData(manufacturerId, manufacturerData).build();
- data.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- AdvertiseData dataFromParcel =
- AdvertiseData.CREATOR.createFromParcel(parcel);
- assertEquals(data, dataFromParcel);
- }
-
- @SmallTest
- public void testEmptyServiceData() {
- Parcel parcel = Parcel.obtain();
- ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
- byte[] serviceData = new byte[0];
- AdvertiseData data =
- mAdvertiseDataBuilder.setIncludeDeviceName(true)
- .addServiceData(uuid, serviceData).build();
- data.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- AdvertiseData dataFromParcel =
- AdvertiseData.CREATOR.createFromParcel(parcel);
- assertEquals(data, dataFromParcel);
- }
-
- @SmallTest
- public void testServiceUuid() {
- Parcel parcel = Parcel.obtain();
- ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
- ParcelUuid uuid2 = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
-
- AdvertiseData data =
- mAdvertiseDataBuilder.setIncludeDeviceName(true)
- .addServiceUuid(uuid).addServiceUuid(uuid2).build();
- data.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- AdvertiseData dataFromParcel =
- AdvertiseData.CREATOR.createFromParcel(parcel);
- assertEquals(data, dataFromParcel);
- }
-
- @SmallTest
- public void testManufacturerData() {
- Parcel parcel = Parcel.obtain();
- ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
- ParcelUuid uuid2 = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
-
- int manufacturerId = 50;
- byte[] manufacturerData = new byte[] {
- (byte) 0xF0, 0x00, 0x02, 0x15 };
- AdvertiseData data =
- mAdvertiseDataBuilder.setIncludeDeviceName(true)
- .addServiceUuid(uuid).addServiceUuid(uuid2)
- .addManufacturerData(manufacturerId, manufacturerData).build();
-
- data.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- AdvertiseData dataFromParcel =
- AdvertiseData.CREATOR.createFromParcel(parcel);
- assertEquals(data, dataFromParcel);
- }
-
- @SmallTest
- public void testServiceData() {
- Parcel parcel = Parcel.obtain();
- ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
- byte[] serviceData = new byte[] {
- (byte) 0xF0, 0x00, 0x02, 0x15 };
- AdvertiseData data =
- mAdvertiseDataBuilder.setIncludeDeviceName(true)
- .addServiceData(uuid, serviceData).build();
- data.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- AdvertiseData dataFromParcel =
- AdvertiseData.CREATOR.createFromParcel(parcel);
- assertEquals(data, dataFromParcel);
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanFilterTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanFilterTest.java
deleted file mode 100644
index 35da4bc..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanFilterTest.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanRecord;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for Bluetooth LE scan filters.
- * <p>
- * To run this test, use adb shell am instrument -e class 'android.bluetooth.ScanFilterTest' -w
- * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
-public class ScanFilterTest extends TestCase {
-
- private static final String DEVICE_MAC = "01:02:03:04:05:AB";
- private ScanResult mScanResult;
- private ScanFilter.Builder mFilterBuilder;
-
- @Override
- protected void setUp() throws Exception {
- byte[] scanRecord = new byte[] {
- 0x02, 0x01, 0x1a, // advertising flags
- 0x05, 0x02, 0x0b, 0x11, 0x0a, 0x11, // 16 bit service uuids
- 0x04, 0x09, 0x50, 0x65, 0x64, // setName
- 0x02, 0x0A, (byte) 0xec, // tx power level
- 0x05, 0x16, 0x0b, 0x11, 0x50, 0x64, // service data
- 0x05, (byte) 0xff, (byte) 0xe0, 0x00, 0x02, 0x15, // manufacturer specific data
- 0x03, 0x50, 0x01, 0x02, // an unknown data type won't cause trouble
- };
-
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- BluetoothDevice device = adapter.getRemoteDevice(DEVICE_MAC);
- mScanResult = new ScanResult(device, ScanRecord.parseFromBytes(scanRecord),
- -10, 1397545200000000L);
- mFilterBuilder = new ScanFilter.Builder();
- }
-
- @SmallTest
- public void testsetNameFilter() {
- ScanFilter filter = mFilterBuilder.setDeviceName("Ped").build();
- assertTrue("setName filter fails", filter.matches(mScanResult));
-
- filter = mFilterBuilder.setDeviceName("Pem").build();
- assertFalse("setName filter fails", filter.matches(mScanResult));
-
- }
-
- @SmallTest
- public void testDeviceFilter() {
- ScanFilter filter = mFilterBuilder.setDeviceAddress(DEVICE_MAC).build();
- assertTrue("device filter fails", filter.matches(mScanResult));
-
- filter = mFilterBuilder.setDeviceAddress("11:22:33:44:55:66").build();
- assertFalse("device filter fails", filter.matches(mScanResult));
- }
-
- @SmallTest
- public void testsetServiceUuidFilter() {
- ScanFilter filter = mFilterBuilder.setServiceUuid(
- ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB")).build();
- assertTrue("uuid filter fails", filter.matches(mScanResult));
-
- filter = mFilterBuilder.setServiceUuid(
- ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB")).build();
- assertFalse("uuid filter fails", filter.matches(mScanResult));
-
- filter = mFilterBuilder
- .setServiceUuid(ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"),
- ParcelUuid.fromString("FFFFFFF0-FFFF-FFFF-FFFF-FFFFFFFFFFFF"))
- .build();
- assertTrue("uuid filter fails", filter.matches(mScanResult));
- }
-
- @SmallTest
- public void testsetServiceDataFilter() {
- byte[] setServiceData = new byte[] {
- 0x50, 0x64 };
- ParcelUuid serviceDataUuid = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
- ScanFilter filter = mFilterBuilder.setServiceData(serviceDataUuid, setServiceData).build();
- assertTrue("service data filter fails", filter.matches(mScanResult));
-
- byte[] emptyData = new byte[0];
- filter = mFilterBuilder.setServiceData(serviceDataUuid, emptyData).build();
- assertTrue("service data filter fails", filter.matches(mScanResult));
-
- byte[] prefixData = new byte[] {
- 0x50 };
- filter = mFilterBuilder.setServiceData(serviceDataUuid, prefixData).build();
- assertTrue("service data filter fails", filter.matches(mScanResult));
-
- byte[] nonMatchData = new byte[] {
- 0x51, 0x64 };
- byte[] mask = new byte[] {
- (byte) 0x00, (byte) 0xFF };
- filter = mFilterBuilder.setServiceData(serviceDataUuid, nonMatchData, mask).build();
- assertTrue("partial service data filter fails", filter.matches(mScanResult));
-
- filter = mFilterBuilder.setServiceData(serviceDataUuid, nonMatchData).build();
- assertFalse("service data filter fails", filter.matches(mScanResult));
- }
-
- @SmallTest
- public void testManufacturerSpecificData() {
- byte[] setManufacturerData = new byte[] {
- 0x02, 0x15 };
- int manufacturerId = 0xE0;
- ScanFilter filter =
- mFilterBuilder.setManufacturerData(manufacturerId, setManufacturerData).build();
- assertTrue("manufacturer data filter fails", filter.matches(mScanResult));
-
- byte[] emptyData = new byte[0];
- filter = mFilterBuilder.setManufacturerData(manufacturerId, emptyData).build();
- assertTrue("manufacturer data filter fails", filter.matches(mScanResult));
-
- byte[] prefixData = new byte[] {
- 0x02 };
- filter = mFilterBuilder.setManufacturerData(manufacturerId, prefixData).build();
- assertTrue("manufacturer data filter fails", filter.matches(mScanResult));
-
- // Test data mask
- byte[] nonMatchData = new byte[] {
- 0x02, 0x14 };
- filter = mFilterBuilder.setManufacturerData(manufacturerId, nonMatchData).build();
- assertFalse("manufacturer data filter fails", filter.matches(mScanResult));
- byte[] mask = new byte[] {
- (byte) 0xFF, (byte) 0x00
- };
- filter = mFilterBuilder.setManufacturerData(manufacturerId, nonMatchData, mask).build();
- assertTrue("partial setManufacturerData filter fails", filter.matches(mScanResult));
- }
-
- @SmallTest
- public void testReadWriteParcel() {
- ScanFilter filter = mFilterBuilder.build();
- testReadWriteParcelForFilter(filter);
-
- filter = mFilterBuilder.setDeviceName("Ped").build();
- testReadWriteParcelForFilter(filter);
-
- filter = mFilterBuilder.setDeviceAddress("11:22:33:44:55:66").build();
- testReadWriteParcelForFilter(filter);
-
- filter = mFilterBuilder.setServiceUuid(
- ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB")).build();
- testReadWriteParcelForFilter(filter);
-
- filter = mFilterBuilder.setServiceUuid(
- ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"),
- ParcelUuid.fromString("FFFFFFF0-FFFF-FFFF-FFFF-FFFFFFFFFFFF")).build();
- testReadWriteParcelForFilter(filter);
-
- byte[] serviceData = new byte[] {
- 0x50, 0x64 };
-
- ParcelUuid serviceDataUuid = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
- filter = mFilterBuilder.setServiceData(serviceDataUuid, serviceData).build();
- testReadWriteParcelForFilter(filter);
-
- filter = mFilterBuilder.setServiceData(serviceDataUuid, new byte[0]).build();
- testReadWriteParcelForFilter(filter);
-
- byte[] serviceDataMask = new byte[] {
- (byte) 0xFF, (byte) 0xFF };
- filter = mFilterBuilder.setServiceData(serviceDataUuid, serviceData, serviceDataMask)
- .build();
- testReadWriteParcelForFilter(filter);
-
- byte[] manufacturerData = new byte[] {
- 0x02, 0x15 };
- int manufacturerId = 0xE0;
- filter = mFilterBuilder.setManufacturerData(manufacturerId, manufacturerData).build();
- testReadWriteParcelForFilter(filter);
-
- filter = mFilterBuilder.setServiceData(serviceDataUuid, new byte[0]).build();
- testReadWriteParcelForFilter(filter);
-
- byte[] manufacturerDataMask = new byte[] {
- (byte) 0xFF, (byte) 0xFF
- };
- filter = mFilterBuilder.setManufacturerData(manufacturerId, manufacturerData,
- manufacturerDataMask).build();
- testReadWriteParcelForFilter(filter);
- }
-
- private void testReadWriteParcelForFilter(ScanFilter filter) {
- Parcel parcel = Parcel.obtain();
- filter.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- ScanFilter filterFromParcel =
- ScanFilter.CREATOR.createFromParcel(parcel);
- assertEquals(filter, filterFromParcel);
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java
deleted file mode 100644
index 4e817d4..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.os.ParcelUuid;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.internal.util.HexDump;
-import com.android.modules.utils.BytesMatcher;
-
-import junit.framework.TestCase;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Predicate;
-
-/**
- * Unit test cases for {@link ScanRecord}.
- * <p>
- * To run this test, use adb shell am instrument -e class 'android.bluetooth.ScanRecordTest' -w
- * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
-public class ScanRecordTest extends TestCase {
- /**
- * Example raw beacons captured from a Blue Charm BC011
- */
- private static final String RECORD_URL = "0201060303AAFE1716AAFE10EE01626C7565636861726D626561636F6E730009168020691E0EFE13551109426C7565436861726D5F313639363835000000";
- private static final String RECORD_UUID = "0201060303AAFE1716AAFE00EE626C7565636861726D31000000000001000009168020691E0EFE13551109426C7565436861726D5F313639363835000000";
- private static final String RECORD_TLM = "0201060303AAFE1116AAFE20000BF017000008874803FB93540916802069080EFE13551109426C7565436861726D5F313639363835000000000000000000";
- private static final String RECORD_IBEACON = "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000";
-
- @SmallTest
- public void testMatchesAnyField_Eddystone_Parser() {
- final List<String> found = new ArrayList<>();
- final Predicate<byte[]> matcher = (v) -> {
- found.add(HexDump.toHexString(v));
- return false;
- };
- ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(RECORD_URL))
- .matchesAnyField(matcher);
-
- assertEquals(Arrays.asList(
- "020106",
- "0303AAFE",
- "1716AAFE10EE01626C7565636861726D626561636F6E7300",
- "09168020691E0EFE1355",
- "1109426C7565436861726D5F313639363835"), found);
- }
-
- @SmallTest
- public void testMatchesAnyField_Eddystone() {
- final BytesMatcher matcher = BytesMatcher.decode("⊆0016AAFE/00FFFFFF");
- assertMatchesAnyField(RECORD_URL, matcher);
- assertMatchesAnyField(RECORD_UUID, matcher);
- assertMatchesAnyField(RECORD_TLM, matcher);
- assertNotMatchesAnyField(RECORD_IBEACON, matcher);
- }
-
- @SmallTest
- public void testMatchesAnyField_iBeacon_Parser() {
- final List<String> found = new ArrayList<>();
- final Predicate<byte[]> matcher = (v) -> {
- found.add(HexDump.toHexString(v));
- return false;
- };
- ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(RECORD_IBEACON))
- .matchesAnyField(matcher);
-
- assertEquals(Arrays.asList(
- "020106",
- "1AFF4C000215426C7565436861726D426561636F6E730EFE1355C5",
- "09168020691E0EFE1355",
- "1109426C7565436861726D5F313639363835"), found);
- }
-
- @SmallTest
- public void testMatchesAnyField_iBeacon() {
- final BytesMatcher matcher = BytesMatcher.decode("⊆00FF4C0002/00FFFFFFFF");
- assertNotMatchesAnyField(RECORD_URL, matcher);
- assertNotMatchesAnyField(RECORD_UUID, matcher);
- assertNotMatchesAnyField(RECORD_TLM, matcher);
- assertMatchesAnyField(RECORD_IBEACON, matcher);
- }
-
- @SmallTest
- public void testParser() {
- byte[] scanRecord = new byte[] {
- 0x02, 0x01, 0x1a, // advertising flags
- 0x05, 0x02, 0x0b, 0x11, 0x0a, 0x11, // 16 bit service uuids
- 0x04, 0x09, 0x50, 0x65, 0x64, // name
- 0x02, 0x0A, (byte) 0xec, // tx power level
- 0x05, 0x16, 0x0b, 0x11, 0x50, 0x64, // service data
- 0x05, (byte) 0xff, (byte) 0xe0, 0x00, 0x02, 0x15, // manufacturer specific data
- 0x03, 0x50, 0x01, 0x02, // an unknown data type won't cause trouble
- };
- ScanRecord data = ScanRecord.parseFromBytes(scanRecord);
- assertEquals(0x1a, data.getAdvertiseFlags());
- ParcelUuid uuid1 = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
- ParcelUuid uuid2 = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
- assertTrue(data.getServiceUuids().contains(uuid1));
- assertTrue(data.getServiceUuids().contains(uuid2));
-
- assertEquals("Ped", data.getDeviceName());
- assertEquals(-20, data.getTxPowerLevel());
-
- assertTrue(data.getManufacturerSpecificData().get(0x00E0) != null);
- assertArrayEquals(new byte[] {
- 0x02, 0x15 }, data.getManufacturerSpecificData().get(0x00E0));
-
- assertTrue(data.getServiceData().containsKey(uuid2));
- assertArrayEquals(new byte[] {
- 0x50, 0x64 }, data.getServiceData().get(uuid2));
- }
-
- // Assert two byte arrays are equal.
- private static void assertArrayEquals(byte[] expected, byte[] actual) {
- if (!Arrays.equals(expected, actual)) {
- fail("expected:<" + Arrays.toString(expected) +
- "> but was:<" + Arrays.toString(actual) + ">");
- }
-
- }
-
- private static void assertMatchesAnyField(String record, BytesMatcher matcher) {
- assertTrue(ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(record))
- .matchesAnyField(matcher));
- }
-
- private static void assertNotMatchesAnyField(String record, BytesMatcher matcher) {
- assertFalse(ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(record))
- .matchesAnyField(matcher));
- }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanResultTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanResultTest.java
deleted file mode 100644
index 01d5c59..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanResultTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for Bluetooth LE scans.
- * <p>
- * To run this test, use adb shell am instrument -e class 'android.bluetooth.ScanResultTest' -w
- * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
-public class ScanResultTest extends TestCase {
-
- /**
- * Test read and write parcel of ScanResult
- */
- @SmallTest
- public void testScanResultParceling() {
- BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(
- "01:02:03:04:05:06");
- byte[] scanRecord = new byte[] {
- 1, 2, 3 };
- int rssi = -10;
- long timestampMicros = 10000L;
-
- ScanResult result = new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), rssi,
- timestampMicros);
- Parcel parcel = Parcel.obtain();
- result.writeToParcel(parcel, 0);
- // Need to reset parcel data position to the beginning.
- parcel.setDataPosition(0);
- ScanResult resultFromParcel = ScanResult.CREATOR.createFromParcel(parcel);
- assertEquals(result, resultFromParcel);
- }
-
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanSettingsTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanSettingsTest.java
deleted file mode 100644
index 7c42c3b..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanSettingsTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Test for Bluetooth LE {@link ScanSettings}.
- */
-public class ScanSettingsTest extends TestCase {
-
- @SmallTest
- public void testCallbackType() {
- ScanSettings.Builder builder = new ScanSettings.Builder();
- builder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
- builder.setCallbackType(ScanSettings.CALLBACK_TYPE_FIRST_MATCH);
- builder.setCallbackType(ScanSettings.CALLBACK_TYPE_MATCH_LOST);
- builder.setCallbackType(
- ScanSettings.CALLBACK_TYPE_FIRST_MATCH | ScanSettings.CALLBACK_TYPE_MATCH_LOST);
- try {
- builder.setCallbackType(
- ScanSettings.CALLBACK_TYPE_ALL_MATCHES | ScanSettings.CALLBACK_TYPE_MATCH_LOST);
- fail("should have thrown IllegalArgumentException!");
- } catch (IllegalArgumentException e) {
- // nothing to do
- }
-
- try {
- builder.setCallbackType(
- ScanSettings.CALLBACK_TYPE_ALL_MATCHES |
- ScanSettings.CALLBACK_TYPE_FIRST_MATCH);
- fail("should have thrown IllegalArgumentException!");
- } catch (IllegalArgumentException e) {
- // nothing to do
- }
-
- try {
- builder.setCallbackType(
- ScanSettings.CALLBACK_TYPE_ALL_MATCHES |
- ScanSettings.CALLBACK_TYPE_FIRST_MATCH |
- ScanSettings.CALLBACK_TYPE_MATCH_LOST);
- fail("should have thrown IllegalArgumentException!");
- } catch (IllegalArgumentException e) {
- // nothing to do
- }
-
- }
-}
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/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index fefcebe..fa6b086 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -390,6 +390,9 @@
<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" />
<!-- Permissions required for Incremental CTS tests -->
<permission name="com.android.permission.USE_INSTALLER_V2"/>
<permission name="android.permission.LOADER_USAGE_STATS"/>
@@ -458,6 +461,7 @@
<!-- 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.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/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
index 919a93b..05fb4c3 100644
--- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
+import android.security.keystore.KeyProperties;
import android.security.maintenance.IKeystoreMaintenance;
import android.system.keystore2.Domain;
import android.system.keystore2.KeyDescriptor;
@@ -157,6 +158,11 @@
* Migrates a key given by the source descriptor to the location designated by the destination
* descriptor.
*
+ * If Domain::APP is selected in either source or destination, nspace must be set to
+ * {@link KeyProperties#NAMESPACE_APPLICATION}, implying the caller's UID.
+ * If the caller has the MIGRATE_ANY_KEY permission, Domain::APP may be used with
+ * other nspace values which then indicates the UID of a different application.
+ *
* @param source - The key to migrate may be specified by Domain.APP, Domain.SELINUX, or
* Domain.KEY_ID. The caller needs the permissions use, delete, and grant for the
* source namespace.
@@ -183,4 +189,20 @@
return SYSTEM_ERROR;
}
}
+
+ /**
+ * @see IKeystoreMaintenance#listEntries(int, long)
+ */
+ @Nullable
+ public static KeyDescriptor[] listEntries(int domain, long nspace) {
+ try {
+ return getService().listEntries(domain, nspace);
+ } catch (ServiceSpecificException e) {
+ Log.e(TAG, "listEntries failed", e);
+ return null;
+ } catch (Exception e) {
+ Log.e(TAG, "Can not connect to keystore", e);
+ return null;
+ }
+ }
}
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/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/usb/tests/accessorytest/f_accessory.h b/libs/usb/tests/accessorytest/f_accessory.h
index 312f4ba..75e017c 100644
--- a/libs/usb/tests/accessorytest/f_accessory.h
+++ b/libs/usb/tests/accessorytest/f_accessory.h
@@ -1,148 +1,53 @@
-/*
- * Gadget Function Driver for Android USB accessories
- *
- * Copyright (C) 2011 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __LINUX_USB_F_ACCESSORY_H
-#define __LINUX_USB_F_ACCESSORY_H
-
-/* Use Google Vendor ID when in accessory mode */
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_USB_F_ACCESSORY_H
+#define _UAPI_LINUX_USB_F_ACCESSORY_H
#define USB_ACCESSORY_VENDOR_ID 0x18D1
-
-
-/* Product ID to use when in accessory mode */
#define USB_ACCESSORY_PRODUCT_ID 0x2D00
-
-/* Product ID to use when in accessory mode and adb is enabled */
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define USB_ACCESSORY_ADB_PRODUCT_ID 0x2D01
-
-/* Indexes for strings sent by the host via ACCESSORY_SEND_STRING */
-#define ACCESSORY_STRING_MANUFACTURER 0
-#define ACCESSORY_STRING_MODEL 1
-#define ACCESSORY_STRING_DESCRIPTION 2
-#define ACCESSORY_STRING_VERSION 3
-#define ACCESSORY_STRING_URI 4
-#define ACCESSORY_STRING_SERIAL 5
-
-/* Control request for retrieving device's protocol version
- *
- * requestType: USB_DIR_IN | USB_TYPE_VENDOR
- * request: ACCESSORY_GET_PROTOCOL
- * value: 0
- * index: 0
- * data version number (16 bits little endian)
- * 1 for original accessory support
- * 2 adds audio and HID support
- */
-#define ACCESSORY_GET_PROTOCOL 51
-
-/* Control request for host to send a string to the device
- *
- * requestType: USB_DIR_OUT | USB_TYPE_VENDOR
- * request: ACCESSORY_SEND_STRING
- * value: 0
- * index: string ID
- * data zero terminated UTF8 string
- *
- * The device can later retrieve these strings via the
- * ACCESSORY_GET_STRING_* ioctls
- */
-#define ACCESSORY_SEND_STRING 52
-
-/* Control request for starting device in accessory mode.
- * The host sends this after setting all its strings to the device.
- *
- * requestType: USB_DIR_OUT | USB_TYPE_VENDOR
- * request: ACCESSORY_START
- * value: 0
- * index: 0
- * data none
- */
-#define ACCESSORY_START 53
-
-/* Control request for registering a HID device.
- * Upon registering, a unique ID is sent by the accessory in the
- * value parameter. This ID will be used for future commands for
- * the device
- *
- * requestType: USB_DIR_OUT | USB_TYPE_VENDOR
- * request: ACCESSORY_REGISTER_HID_DEVICE
- * value: Accessory assigned ID for the HID device
- * index: total length of the HID report descriptor
- * data none
- */
-#define ACCESSORY_REGISTER_HID 54
-
-/* Control request for unregistering a HID device.
- *
- * requestType: USB_DIR_OUT | USB_TYPE_VENDOR
- * request: ACCESSORY_REGISTER_HID
- * value: Accessory assigned ID for the HID device
- * index: 0
- * data none
- */
-#define ACCESSORY_UNREGISTER_HID 55
-
-/* Control request for sending the HID report descriptor.
- * If the HID descriptor is longer than the endpoint zero max packet size,
- * the descriptor will be sent in multiple ACCESSORY_SET_HID_REPORT_DESC
- * commands. The data for the descriptor must be sent sequentially
- * if multiple packets are needed.
- *
- * requestType: USB_DIR_OUT | USB_TYPE_VENDOR
- * request: ACCESSORY_SET_HID_REPORT_DESC
- * value: Accessory assigned ID for the HID device
- * index: offset of data in descriptor
- * (needed when HID descriptor is too big for one packet)
- * data the HID report descriptor
- */
-#define ACCESSORY_SET_HID_REPORT_DESC 56
-
-/* Control request for sending HID events.
- *
- * requestType: USB_DIR_OUT | USB_TYPE_VENDOR
- * request: ACCESSORY_SEND_HID_EVENT
- * value: Accessory assigned ID for the HID device
- * index: 0
- * data the HID report for the event
- */
-#define ACCESSORY_SEND_HID_EVENT 57
-
-/* Control request for setting the audio mode.
- *
- * requestType: USB_DIR_OUT | USB_TYPE_VENDOR
- * request: ACCESSORY_SET_AUDIO_MODE
- * value: 0 - no audio
- * 1 - device to host, 44100 16-bit stereo PCM
- * index: 0
- * data the HID report for the event
- */
-#define ACCESSORY_SET_AUDIO_MODE 58
-
-
-
-/* ioctls for retrieving strings set by the host */
-#define ACCESSORY_GET_STRING_MANUFACTURER _IOW('M', 1, char[256])
-#define ACCESSORY_GET_STRING_MODEL _IOW('M', 2, char[256])
-#define ACCESSORY_GET_STRING_DESCRIPTION _IOW('M', 3, char[256])
-#define ACCESSORY_GET_STRING_VERSION _IOW('M', 4, char[256])
-#define ACCESSORY_GET_STRING_URI _IOW('M', 5, char[256])
-#define ACCESSORY_GET_STRING_SERIAL _IOW('M', 6, char[256])
-/* returns 1 if there is a start request pending */
-#define ACCESSORY_IS_START_REQUESTED _IO('M', 7)
-/* returns audio mode (set via the ACCESSORY_SET_AUDIO_MODE control request) */
-#define ACCESSORY_GET_AUDIO_MODE _IO('M', 8)
-
-#endif /* __LINUX_USB_F_ACCESSORY_H */
+#define ACCESSORY_STRING_MANUFACTURER 0
+#define ACCESSORY_STRING_MODEL 1
+#define ACCESSORY_STRING_DESCRIPTION 2
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_STRING_VERSION 3
+#define ACCESSORY_STRING_URI 4
+#define ACCESSORY_STRING_SERIAL 5
+#define ACCESSORY_GET_PROTOCOL 51
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_SEND_STRING 52
+#define ACCESSORY_START 53
+#define ACCESSORY_REGISTER_HID 54
+#define ACCESSORY_UNREGISTER_HID 55
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_SET_HID_REPORT_DESC 56
+#define ACCESSORY_SEND_HID_EVENT 57
+#define ACCESSORY_SET_AUDIO_MODE 58
+#define ACCESSORY_GET_STRING_MANUFACTURER _IOW('M', 1, char[256])
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_GET_STRING_MODEL _IOW('M', 2, char[256])
+#define ACCESSORY_GET_STRING_DESCRIPTION _IOW('M', 3, char[256])
+#define ACCESSORY_GET_STRING_VERSION _IOW('M', 4, char[256])
+#define ACCESSORY_GET_STRING_URI _IOW('M', 5, char[256])
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_GET_STRING_SERIAL _IOW('M', 6, char[256])
+#define ACCESSORY_IS_START_REQUESTED _IO('M', 7)
+#define ACCESSORY_GET_AUDIO_MODE _IO('M', 8)
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
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.java b/media/java/android/media/BtProfileConnectionInfo.java
index d1bb41e..88b9777 100644
--- a/media/java/android/media/BtProfileConnectionInfo.java
+++ b/media/java/android/media/BtProfileConnectionInfo.java
@@ -15,39 +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;
+ 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,
+ private BtProfileConnectionInfo(int profile, boolean suppressNoisyIntent, int volume,
boolean isLeOutput) {
mProfile = profile;
mSupprNoisy = suppressNoisyIntent;
@@ -59,7 +45,7 @@
* Constructor used by BtHelper when a profile is connected
* {@hide}
*/
- public BtProfileConnectionInfo(@BtProfile int profile) {
+ public BtProfileConnectionInfo(int profile) {
this(profile, false, -1, false);
}
@@ -142,7 +128,7 @@
/**
* @return The profile connection
*/
- public @BtProfile int getProfile() {
+ public int getProfile() {
return mProfile;
}
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/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
index 90bb76a..223bdcdd 100644
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ b/packages/ConnectivityT/framework-t/Android.bp
@@ -129,6 +129,11 @@
"src/android/net/EthernetNetworkSpecifier.java",
"src/android/net/IEthernetManager.aidl",
"src/android/net/IEthernetServiceListener.aidl",
+ "src/android/net/IInternalNetworkManagementListener.aidl",
+ "src/android/net/InternalNetworkUpdateRequest.java",
+ "src/android/net/InternalNetworkUpdateRequest.aidl",
+ "src/android/net/InternalNetworkManagementException.java",
+ "src/android/net/InternalNetworkManagementException.aidl",
"src/android/net/ITetheredInterfaceCallback.aidl",
],
path: "src",
@@ -156,8 +161,18 @@
":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__",
+ ],
}
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..84adef5 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,11 @@
import android.net.NetworkStateSnapshot;
import android.net.NetworkTemplate;
import android.net.UnderlyingNetworkInfo;
+import android.net.netstats.IUsageCallback;
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 +55,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 +125,19 @@
private final Context mContext;
private final INetworkStatsService mService;
+ /**
+ * Type constants for reading different types of Data Usage.
+ * @hide
+ */
+ // @SystemApi(client = MODULE_LIBRARIES)
+ public static final String PREFIX_DEV = "dev";
+ /** @hide */
+ public static final String PREFIX_XT = "xt";
+ /** @hide */
+ public static final String PREFIX_UID = "uid";
+ /** @hide */
+ public static final String PREFIX_UID_TAG = "uid_tag";
+
/** @hide */
public static final int FLAG_POLL_ON_OPEN = 1 << 0;
/** @hide */
@@ -131,6 +145,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 +168,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 +181,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 +241,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 +416,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 +450,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 +467,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 +569,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 +585,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 +687,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 +816,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 +849,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 +879,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 +1016,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 +1050,7 @@
*
* @hide
*/
- // @SystemApi
+ @SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
@@ -890,17 +1063,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 +1085,7 @@
*
* @hide
*/
- // @SystemApi
+ @SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
@@ -927,9 +1101,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 +1123,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/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/IInternalNetworkManagementListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IInternalNetworkManagementListener.aidl
similarity index 100%
rename from core/java/android/net/IInternalNetworkManagementListener.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/IInternalNetworkManagementListener.aidl
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/core/java/android/net/InternalNetworkManagementException.aidl b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.aidl
similarity index 100%
rename from core/java/android/net/InternalNetworkManagementException.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.aidl
diff --git a/core/java/android/net/InternalNetworkManagementException.java b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java
similarity index 100%
rename from core/java/android/net/InternalNetworkManagementException.java
rename to packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl
similarity index 100%
rename from core/java/android/net/InternalNetworkUpdateRequest.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java
similarity index 100%
rename from core/java/android/net/InternalNetworkUpdateRequest.java
rename to packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java
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..73b9c72 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
@@ -16,18 +16,30 @@
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.Annotation;
+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 +49,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 +76,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 +110,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 +118,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 +132,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 +181,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 +197,99 @@
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, @Annotation.NetworkType 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 +302,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(@Annotation.NetworkType 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..27e717f 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
@@ -41,13 +41,13 @@
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 +58,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 +134,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)
@@ -263,7 +252,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 +272,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 +353,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 +402,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 +424,7 @@
mMetered = metered;
mRoaming = roaming;
mDefaultNetwork = defaultNetwork;
- mSubType = subType;
+ mRatType = ratType;
mOemManaged = oemManaged;
mSubscriberIdMatchRule = subscriberIdMatchRule;
checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule);
@@ -453,7 +442,7 @@
mMetered = in.readInt();
mRoaming = in.readInt();
mDefaultNetwork = in.readInt();
- mSubType = in.readInt();
+ mRatType = in.readInt();
mOemManaged = in.readInt();
mSubscriberIdMatchRule = in.readInt();
}
@@ -467,7 +456,7 @@
dest.writeInt(mMetered);
dest.writeInt(mRoaming);
dest.writeInt(mDefaultNetwork);
- dest.writeInt(mSubType);
+ dest.writeInt(mRatType);
dest.writeInt(mOemManaged);
dest.writeInt(mSubscriberIdMatchRule);
}
@@ -500,8 +489,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 +503,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 +515,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 +582,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 +624,7 @@
* Get the Radio Access Technology(RAT) type filter of the template.
*/
public int getRatType() {
- return mSubType;
+ return mRatType;
}
/**
@@ -652,7 +641,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 +699,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 +721,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 +745,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 +973,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.
diff --git a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
index 1af32bf..c2f0cdf 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,9 +28,10 @@
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 android.util.Log;
import com.android.server.NetworkManagementSocketTagger;
@@ -37,8 +39,6 @@
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;
@@ -177,25 +177,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 +197,45 @@
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() {
+ NetworkManagementSocketTagger.install();
+ }
+
+ /**
* Set active tag to use when accounting {@link Socket} traffic originating
* from the current thread. Only one active tag per thread is supported.
* <p>
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/service/Android.bp b/packages/ConnectivityT/service/Android.bp
index 97dfb64..24bc91d 100644
--- a/packages/ConnectivityT/service/Android.bp
+++ b/packages/ConnectivityT/service/Android.bp
@@ -26,6 +26,8 @@
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",
],
path: "src",
visibility: [
@@ -66,6 +68,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 +85,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/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/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..17f3455 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
@@ -26,10 +26,10 @@
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 +70,7 @@
private final boolean mUseBpfStats;
- private final INetd mNetd;
+ private final Context mContext;
/**
* Guards persistent data access in this class
@@ -158,12 +158,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 +172,7 @@
mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1);
mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
}
- mNetd = netd;
+ mContext = ctx;
}
public NetworkStats readBpfNetworkStatsDev() throws IOException {
@@ -295,11 +295,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 +328,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
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..8e584d0 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,16 @@
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.app.usage.NetworkStatsManager.PREFIX_UID;
+import static android.app.usage.NetworkStatsManager.PREFIX_UID_TAG;
+import static android.app.usage.NetworkStatsManager.PREFIX_XT;
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;
@@ -47,23 +51,6 @@
import static android.net.TrafficStats.UID_TETHERING;
import static android.net.TrafficStats.UNSUPPORTED;
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;
@@ -73,7 +60,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 +98,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 +106,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 +120,7 @@
import android.provider.Settings.Global;
import android.service.NetworkInterfaceProto;
import android.service.NetworkStatsServiceDumpProto;
+import android.system.ErrnoException;
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,31 @@
}
};
}
+
+ /**
+ * @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;
+ }
+ }
}
/**
@@ -557,7 +594,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 +628,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 +745,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 +777,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 +811,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 +863,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 +876,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 +891,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 +915,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 +971,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 +988,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 +1026,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 +1055,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 +1103,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 +1206,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 +1444,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 +1470,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 +1485,9 @@
if (isMobile) {
mobileIfaces.add(baseIface);
}
+ if (isWifi) {
+ wifiIfaces.add(baseIface);
+ }
}
// Traffic occurring on stacked interfaces is usually clatd.
@@ -1399,6 +1529,9 @@
if (isMobile) {
mobileIfaces.add(iface);
}
+ if (isWifi) {
+ wifiIfaces.add(iface);
+ }
mStatsFactory.noteStackedIface(iface, baseIface);
}
@@ -1406,11 +1539,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 +1566,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;
}
@@ -2120,7 +2258,7 @@
public void notifyWarningOrLimitReached() {
Log.d(TAG, mTag + ": notifyWarningOrLimitReached");
BinderUtils.withCleanCallingIdentity(() ->
- mNetworkPolicyManager.onStatsProviderWarningOrLimitReached());
+ mNetworkPolicyManager.notifyStatsProviderWarningOrLimitReached());
}
@Override
@@ -2179,24 +2317,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 +2329,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,31 +2353,27 @@
}
@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;
}
}
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..3e35e603 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -16,8 +16,8 @@
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;
@@ -57,7 +57,7 @@
*
* @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);
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/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/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..5b2e8ae 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -245,6 +245,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 +504,7 @@
<!-- 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.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 +529,10 @@
<!-- 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" />
+
<!-- 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/services/Android.bp b/services/Android.bp
index 841edc7..8947393 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -74,6 +74,7 @@
":services.appwidget-sources",
":services.autofill-sources",
":services.backup-sources",
+ ":services.bluetooth-sources", // TODO(b/214988855) : Remove once apex/service-bluetooth jar is ready
":backuplib-sources",
":services.companion-sources",
":services.contentcapture-sources",
@@ -175,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 7a4f1de..9d19008 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -93,6 +93,7 @@
defaults: ["platform_service_defaults"],
srcs: [
":statslog-art-java-gen",
+ ":services.bluetooth-sources", // TODO(b/214988855) : Remove once apex is ready
":services.core-sources",
":services.core.protologsrc",
":dumpstate_aidl",
@@ -165,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/BluetoothAirplaneModeListener.java b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
deleted file mode 100644
index 380b1f3..0000000
--- a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.annotation.RequiresPermission;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.provider.Settings;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * The BluetoothAirplaneModeListener handles system airplane mode change callback and checks
- * whether we need to inform BluetoothManagerService on this change.
- *
- * The information of airplane mode turns on would not be passed to the BluetoothManagerService
- * when Bluetooth is on and Bluetooth is in one of the following situations:
- * 1. Bluetooth A2DP is connected.
- * 2. Bluetooth Hearing Aid profile is connected.
- * 3. Bluetooth LE Audio is connected
- */
-class BluetoothAirplaneModeListener {
- private static final String TAG = "BluetoothAirplaneModeListener";
- @VisibleForTesting static final String TOAST_COUNT = "bluetooth_airplane_toast_count";
-
- private static final int MSG_AIRPLANE_MODE_CHANGED = 0;
-
- @VisibleForTesting static final int MAX_TOAST_COUNT = 10; // 10 times
-
- private final BluetoothManagerService mBluetoothManager;
- private final BluetoothAirplaneModeHandler mHandler;
- private BluetoothModeChangeHelper mAirplaneHelper;
-
- @VisibleForTesting int mToastCount = 0;
-
- BluetoothAirplaneModeListener(BluetoothManagerService service, Looper looper, Context context) {
- mBluetoothManager = service;
-
- mHandler = new BluetoothAirplaneModeHandler(looper);
- context.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
- mAirplaneModeObserver);
- }
-
- private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
- @Override
- public void onChange(boolean unused) {
- // Post from system main thread to android_io thread.
- Message msg = mHandler.obtainMessage(MSG_AIRPLANE_MODE_CHANGED);
- mHandler.sendMessage(msg);
- }
- };
-
- private class BluetoothAirplaneModeHandler extends Handler {
- BluetoothAirplaneModeHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_AIRPLANE_MODE_CHANGED:
- handleAirplaneModeChange();
- break;
- default:
- Log.e(TAG, "Invalid message: " + msg.what);
- break;
- }
- }
- }
-
- /**
- * Call after boot complete
- */
- @VisibleForTesting
- void start(BluetoothModeChangeHelper helper) {
- Log.i(TAG, "start");
- mAirplaneHelper = helper;
- mToastCount = mAirplaneHelper.getSettingsInt(TOAST_COUNT);
- }
-
- @VisibleForTesting
- boolean shouldPopToast() {
- if (mToastCount >= MAX_TOAST_COUNT) {
- return false;
- }
- mToastCount++;
- mAirplaneHelper.setSettingsInt(TOAST_COUNT, mToastCount);
- return true;
- }
-
- @VisibleForTesting
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- void handleAirplaneModeChange() {
- if (shouldSkipAirplaneModeChange()) {
- Log.i(TAG, "Ignore airplane mode change");
- // Airplane mode enabled when Bluetooth is being used for audio/headering aid.
- // Bluetooth is not disabled in such case, only state is changed to
- // BLUETOOTH_ON_AIRPLANE mode.
- mAirplaneHelper.setSettingsInt(Settings.Global.BLUETOOTH_ON,
- BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
- if (shouldPopToast()) {
- mAirplaneHelper.showToastMessage();
- }
- return;
- }
- if (mAirplaneHelper != null) {
- mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager);
- }
- }
-
- @VisibleForTesting
- boolean shouldSkipAirplaneModeChange() {
- if (mAirplaneHelper == null) {
- return false;
- }
- if (!mAirplaneHelper.isBluetoothOn() || !mAirplaneHelper.isAirplaneModeOn()
- || !mAirplaneHelper.isMediaProfileConnected()) {
- return false;
- }
- return true;
- }
-}
diff --git a/services/core/java/com/android/server/BluetoothDeviceConfigListener.java b/services/core/java/com/android/server/BluetoothDeviceConfigListener.java
deleted file mode 100644
index 611a37d..0000000
--- a/services/core/java/com/android/server/BluetoothDeviceConfigListener.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.provider.DeviceConfig;
-import android.util.Slog;
-
-import java.util.ArrayList;
-
-/**
- * The BluetoothDeviceConfigListener handles system device config change callback and checks
- * whether we need to inform BluetoothManagerService on this change.
- *
- * The information of device config change would not be passed to the BluetoothManagerService
- * when Bluetooth is on and Bluetooth is in one of the following situations:
- * 1. Bluetooth A2DP is connected.
- * 2. Bluetooth Hearing Aid profile is connected.
- */
-class BluetoothDeviceConfigListener {
- private static final String TAG = "BluetoothDeviceConfigListener";
-
- private final BluetoothManagerService mService;
- private final boolean mLogDebug;
-
- BluetoothDeviceConfigListener(BluetoothManagerService service, boolean logDebug) {
- mService = service;
- mLogDebug = logDebug;
- DeviceConfig.addOnPropertiesChangedListener(
- DeviceConfig.NAMESPACE_BLUETOOTH,
- (Runnable r) -> r.run(),
- mDeviceConfigChangedListener);
- }
-
- private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener =
- new DeviceConfig.OnPropertiesChangedListener() {
- @Override
- public void onPropertiesChanged(DeviceConfig.Properties properties) {
- if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_BLUETOOTH)) {
- return;
- }
- if (mLogDebug) {
- ArrayList<String> flags = new ArrayList<>();
- for (String name : properties.getKeyset()) {
- flags.add(name + "='" + properties.getString(name, "") + "'");
- }
- Slog.d(TAG, "onPropertiesChanged: " + String.join(",", flags));
- }
- boolean foundInit = false;
- for (String name : properties.getKeyset()) {
- if (name.startsWith("INIT_")) {
- foundInit = true;
- break;
- }
- }
- if (!foundInit) {
- return;
- }
- mService.onInitFlagsChanged();
- }
- };
-
-}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
deleted file mode 100644
index c8b4f11..0000000
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ /dev/null
@@ -1,2960 +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 com.android.server;
-
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.content.PermissionChecker.PERMISSION_HARD_DENIED;
-import static android.content.PermissionChecker.PID_UNKNOWN;
-import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
-import static android.os.UserHandle.USER_SYSTEM;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.app.ActivityManager;
-import android.app.AppGlobals;
-import android.app.AppOpsManager;
-import android.app.BroadcastOptions;
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothHearingAid;
-import android.bluetooth.BluetoothLeAudio;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProtoEnums;
-import android.bluetooth.IBluetooth;
-import android.bluetooth.IBluetoothCallback;
-import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothHeadset;
-import android.bluetooth.IBluetoothManager;
-import android.bluetooth.IBluetoothManagerCallback;
-import android.bluetooth.IBluetoothProfileServiceConnection;
-import android.bluetooth.IBluetoothStateChangeCallback;
-import android.bluetooth.IBluetoothLeCallControl;
-import android.content.ActivityNotFoundException;
-import android.content.AttributionSource;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.PermissionChecker;
-import android.content.ServiceConnection;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
-import android.content.pm.UserInfo;
-import android.database.ContentObserver;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerExemptionManager;
-import android.os.Process;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
-import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
-import android.util.Log;
-import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.DumpUtils;
-import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.pm.UserManagerInternal;
-import com.android.server.pm.UserManagerInternal.UserRestrictionsListener;
-import com.android.server.pm.UserRestrictionsUtils;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Locale;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-class BluetoothManagerService extends IBluetoothManager.Stub {
- private static final String TAG = "BluetoothManagerService";
- private static final boolean DBG = true;
-
- private static final String BLUETOOTH_PRIVILEGED =
- android.Manifest.permission.BLUETOOTH_PRIVILEGED;
-
- private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid";
- private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address";
- private static final String SECURE_SETTINGS_BLUETOOTH_NAME = "bluetooth_name";
-
- private static final int ACTIVE_LOG_MAX_SIZE = 20;
- private static final int CRASH_LOG_MAX_SIZE = 100;
-
- private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
- //Maximum msec to wait for service restart
- private static final int SERVICE_RESTART_TIME_MS = 400;
- //Maximum msec to wait for restart due to error
- private static final int ERROR_RESTART_TIME_MS = 3000;
- //Maximum msec to delay MESSAGE_USER_SWITCHED
- private static final int USER_SWITCHED_TIME_MS = 200;
- // Delay for the addProxy function in msec
- private static final int ADD_PROXY_DELAY_MS = 100;
- // Delay for retrying enable and disable in msec
- private static final int ENABLE_DISABLE_DELAY_MS = 300;
- private static final int DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS = 300;
- private static final int DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS = 86400;
-
- private static final int MESSAGE_ENABLE = 1;
- private static final int MESSAGE_DISABLE = 2;
- private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3;
- private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4;
- private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
- private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31;
- private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
- private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
- private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
- private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
- private static final int MESSAGE_TIMEOUT_BIND = 100;
- private static final int MESSAGE_TIMEOUT_UNBIND = 101;
- private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200;
- private static final int MESSAGE_USER_SWITCHED = 300;
- private static final int MESSAGE_USER_UNLOCKED = 301;
- private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
- private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
- private static final int MESSAGE_RESTORE_USER_SETTING = 500;
- private static final int MESSAGE_INIT_FLAGS_CHANGED = 600;
-
- private static final int RESTORE_SETTING_TO_ON = 1;
- private static final int RESTORE_SETTING_TO_OFF = 0;
-
- private static final int MAX_ERROR_RESTART_RETRIES = 6;
- private static final int MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES = 10;
-
- // Bluetooth persisted setting is off
- private static final int BLUETOOTH_OFF = 0;
- // Bluetooth persisted setting is on
- // and Airplane mode won't affect Bluetooth state at start up
- private static final int BLUETOOTH_ON_BLUETOOTH = 1;
- // Bluetooth persisted setting is on
- // but Airplane mode will affect Bluetooth state at start up
- // and Airplane mode will have higher priority.
- @VisibleForTesting
- static final int BLUETOOTH_ON_AIRPLANE = 2;
-
- private static final int SERVICE_IBLUETOOTH = 1;
- private static final int SERVICE_IBLUETOOTHGATT = 2;
-
- private final Context mContext;
-
- // Locks are not provided for mName and mAddress.
- // They are accessed in handler or broadcast receiver, same thread context.
- private String mAddress;
- private String mName;
- private final ContentResolver mContentResolver;
- private final int mUserId;
- private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
- private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
- private IBinder mBluetoothBinder;
- private IBluetooth mBluetooth;
- private IBluetoothGatt mBluetoothGatt;
- private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock();
- private boolean mBinding;
- private boolean mUnbinding;
-
- private BluetoothModeChangeHelper mBluetoothModeChangeHelper;
-
- private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
-
- private BluetoothDeviceConfigListener mBluetoothDeviceConfigListener;
-
- // used inside handler thread
- private boolean mQuietEnable = false;
- private boolean mEnable;
-
- private static CharSequence timeToLog(long timestamp) {
- return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
- }
-
- /**
- * Used for tracking apps that enabled / disabled Bluetooth.
- */
- private class ActiveLog {
- private int mReason;
- private String mPackageName;
- private boolean mEnable;
- private long mTimestamp;
-
- ActiveLog(int reason, String packageName, boolean enable, long timestamp) {
- mReason = reason;
- mPackageName = packageName;
- mEnable = enable;
- mTimestamp = timestamp;
- }
-
- public String toString() {
- return timeToLog(mTimestamp) + (mEnable ? " Enabled " : " Disabled ")
- + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName;
- }
-
- void dump(ProtoOutputStream proto) {
- proto.write(BluetoothManagerServiceDumpProto.ActiveLog.TIMESTAMP_MS, mTimestamp);
- proto.write(BluetoothManagerServiceDumpProto.ActiveLog.ENABLE, mEnable);
- proto.write(BluetoothManagerServiceDumpProto.ActiveLog.PACKAGE_NAME, mPackageName);
- proto.write(BluetoothManagerServiceDumpProto.ActiveLog.REASON, mReason);
- }
- }
-
- private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>();
- private final LinkedList<Long> mCrashTimestamps = new LinkedList<>();
- private int mCrashes;
- private long mLastEnabledTime;
-
- // configuration from external IBinder call which is used to
- // synchronize with broadcast receiver.
- private boolean mQuietEnableExternal;
- private boolean mEnableExternal;
-
- // Map of apps registered to keep BLE scanning on.
- private Map<IBinder, ClientDeathRecipient> mBleApps =
- new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
-
- private int mState;
- private final BluetoothHandler mHandler;
- private int mErrorRecoveryRetryCounter;
- private final int mSystemUiUid;
-
- private boolean mIsHearingAidProfileSupported;
-
- private AppOpsManager mAppOps;
-
- // Save a ProfileServiceConnections object for each of the bound
- // bluetooth profile services
- private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>();
-
- private final boolean mWirelessConsentRequired;
-
- private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
- @Override
- public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
- Message msg =
- mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState);
- mHandler.sendMessage(msg);
- }
- };
-
- private final UserRestrictionsListener mUserRestrictionsListener =
- new UserRestrictionsListener() {
- @Override
- public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
- Bundle prevRestrictions) {
-
- if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
- UserManager.DISALLOW_BLUETOOTH_SHARING)) {
- updateOppLauncherComponentState(userId,
- newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING));
- }
-
- // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
- if (userId == USER_SYSTEM
- && UserRestrictionsUtils.restrictionsChanged(prevRestrictions,
- newRestrictions, UserManager.DISALLOW_BLUETOOTH)) {
- if (userId == USER_SYSTEM && newRestrictions.getBoolean(
- UserManager.DISALLOW_BLUETOOTH)) {
- updateOppLauncherComponentState(userId, true); // Sharing disallowed
- sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED,
- mContext.getPackageName());
- } else {
- updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
- UserManager.DISALLOW_BLUETOOTH_SHARING));
- }
- }
- }
- };
-
- @VisibleForTesting
- public void onInitFlagsChanged() {
- mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED);
- mHandler.sendEmptyMessageDelayed(
- MESSAGE_INIT_FLAGS_CHANGED,
- DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS);
- }
-
- public boolean onFactoryReset(AttributionSource attributionSource) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
- "Need BLUETOOTH_PRIVILEGED permission");
-
- // Wait for stable state if bluetooth is temporary state.
- int state = getState();
- if (state == BluetoothAdapter.STATE_BLE_TURNING_ON
- || state == BluetoothAdapter.STATE_TURNING_ON
- || state == BluetoothAdapter.STATE_TURNING_OFF) {
- if (!waitForState(Set.of(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_ON))) {
- return false;
- }
- }
-
- // Clear registered LE apps to force shut-off Bluetooth
- clearBleApps();
- state = getState();
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth == null) {
- return false;
- }
- if (state == BluetoothAdapter.STATE_BLE_ON) {
- addActiveLog(
- BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET,
- mContext.getPackageName(), false);
- mBluetooth.onBrEdrDown(attributionSource);
- return true;
- } else if (state == BluetoothAdapter.STATE_ON) {
- addActiveLog(
- BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET,
- mContext.getPackageName(), false);
- mBluetooth.disable(attributionSource);
- return true;
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to shutdown Bluetooth", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
- return false;
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void onAirplaneModeChanged() {
- synchronized (this) {
- if (isBluetoothPersistedStateOn()) {
- if (isAirplaneModeOn()) {
- persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
- } else {
- persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
- }
- }
-
- int st = BluetoothAdapter.STATE_OFF;
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- st = mBluetooth.getState();
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call getState", e);
- return;
- } finally {
- mBluetoothLock.readLock().unlock();
- }
-
- Slog.d(TAG,
- "Airplane Mode change - current state: " + BluetoothAdapter.nameForState(
- st) + ", isAirplaneModeOn()=" + isAirplaneModeOn());
-
- if (isAirplaneModeOn()) {
- // Clear registered LE apps to force shut-off
- clearBleApps();
-
- // If state is BLE_ON make sure we trigger disableBLE
- if (st == BluetoothAdapter.STATE_BLE_ON) {
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- addActiveLog(
- BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
- mContext.getPackageName(), false);
- mBluetooth.onBrEdrDown(mContext.getAttributionSource());
- mEnable = false;
- mEnableExternal = false;
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call onBrEdrDown", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
- } else if (st == BluetoothAdapter.STATE_ON) {
- sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
- mContext.getPackageName());
- }
- } else if (mEnableExternal) {
- sendEnableMsg(mQuietEnableExternal,
- BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
- mContext.getPackageName());
- }
- }
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
- String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
- if (DBG) {
- Slog.d(TAG, "Bluetooth Adapter name changed to " + newName + " by "
- + mContext.getPackageName());
- }
- if (newName != null) {
- storeNameAndAddress(newName, null);
- }
- } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) {
- String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS);
- if (newAddress != null) {
- if (DBG) {
- Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress);
- }
- storeNameAndAddress(null, newAddress);
- } else {
- if (DBG) {
- Slog.e(TAG, "No Bluetooth Adapter address parameter found");
- }
- }
- } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
- final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
- if (Settings.Global.BLUETOOTH_ON.equals(name)) {
- // The Bluetooth On state may be changed during system restore.
- final String prevValue =
- intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
- final String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
-
- if (DBG) {
- Slog.d(TAG,
- "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" + prevValue
- + ", newValue=" + newValue);
- }
-
- if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) {
- Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING,
- newValue.equals("0") ? RESTORE_SETTING_TO_OFF
- : RESTORE_SETTING_TO_ON, 0);
- mHandler.sendMessage(msg);
- }
- }
- } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(action)
- || BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(action)
- || BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED.equals(action)) {
- final int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
- BluetoothProfile.STATE_CONNECTED);
- if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED)
- && state == BluetoothProfile.STATE_DISCONNECTED
- && !mBluetoothModeChangeHelper.isMediaProfileConnected()) {
- Slog.i(TAG, "Device disconnected, reactivating pending flag changes");
- onInitFlagsChanged();
- }
- }
- }
- };
-
- BluetoothManagerService(Context context) {
- mHandler = new BluetoothHandler(IoThread.get().getLooper());
-
- mContext = context;
-
- mWirelessConsentRequired = context.getResources()
- .getBoolean(com.android.internal.R.bool.config_wirelessConsentRequired);
-
- mCrashes = 0;
- mBluetooth = null;
- mBluetoothBinder = null;
- mBluetoothGatt = null;
- mBinding = false;
- mUnbinding = false;
- mEnable = false;
- mState = BluetoothAdapter.STATE_OFF;
- mQuietEnableExternal = false;
- mEnableExternal = false;
- mAddress = null;
- mName = null;
- mErrorRecoveryRetryCounter = 0;
- mContentResolver = context.getContentResolver();
- mUserId = mContentResolver.getUserId();
- // Observe BLE scan only mode settings change.
- registerForBleScanModeChange();
- mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
- mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
-
- mIsHearingAidProfileSupported = context.getResources()
- .getBoolean(com.android.internal.R.bool.config_hearing_aid_profile_supported);
-
- // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils
- String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS);
- if (!TextUtils.isEmpty(value)) {
- boolean isHearingAidEnabled = Boolean.parseBoolean(value);
- Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled);
- FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled);
- if (isHearingAidEnabled && !mIsHearingAidProfileSupported) {
- // Overwrite to enable support by FeatureFlag
- mIsHearingAidProfileSupported = true;
- }
- }
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
- filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
- filter.addAction(Intent.ACTION_SETTING_RESTORED);
- filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
- filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiver(mReceiver, filter);
-
- loadStoredNameAndAddress();
- if (isBluetoothPersistedStateOn()) {
- if (DBG) {
- Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
- }
- mEnableExternal = true;
- }
-
- String airplaneModeRadios =
- Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
- if (airplaneModeRadios == null || airplaneModeRadios.contains(
- Settings.Global.RADIO_BLUETOOTH)) {
- mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
- this, IoThread.get().getLooper(), context);
- }
-
- int systemUiUid = -1;
- // Check if device is configured with no home screen, which implies no SystemUI.
- boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen);
- if (!noHome) {
- PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
- systemUiUid = pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(),
- MATCH_SYSTEM_ONLY, USER_SYSTEM);
- }
- if (systemUiUid >= 0) {
- Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid));
- } else {
- // Some platforms, such as wearables do not have a system ui.
- Slog.w(TAG, "Unable to resolve SystemUI's UID.");
- }
- mSystemUiUid = systemUiUid;
- }
-
- /**
- * Returns true if airplane mode is currently on
- */
- private boolean isAirplaneModeOn() {
- return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
- }
-
- private boolean supportBluetoothPersistedState() {
- return mContext.getResources().getBoolean(R.bool.config_supportBluetoothPersistedState);
- }
-
- /**
- * Returns true if the Bluetooth saved state is "on"
- */
- private boolean isBluetoothPersistedStateOn() {
- if (!supportBluetoothPersistedState()) {
- return false;
- }
- int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
- if (DBG) {
- Slog.d(TAG, "Bluetooth persisted state: " + state);
- }
- return state != BLUETOOTH_OFF;
- }
-
- private boolean isBluetoothPersistedStateOnAirplane() {
- if (!supportBluetoothPersistedState()) {
- return false;
- }
- int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
- if (DBG) {
- Slog.d(TAG, "Bluetooth persisted state: " + state);
- }
- return state == BLUETOOTH_ON_AIRPLANE;
- }
-
- /**
- * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
- */
- private boolean isBluetoothPersistedStateOnBluetooth() {
- if (!supportBluetoothPersistedState()) {
- return false;
- }
- return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON,
- BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH;
- }
-
- /**
- * Save the Bluetooth on/off state
- */
- private void persistBluetoothSetting(int value) {
- if (DBG) {
- Slog.d(TAG, "Persisting Bluetooth Setting: " + value);
- }
- // waive WRITE_SECURE_SETTINGS permission check
- final long callingIdentity = Binder.clearCallingIdentity();
- try {
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.BLUETOOTH_ON, value);
- } finally {
- Binder.restoreCallingIdentity(callingIdentity);
- }
- }
-
- /**
- * Returns true if the Bluetooth Adapter's name and address is
- * locally cached
- * @return
- */
- private boolean isNameAndAddressSet() {
- return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0;
- }
-
- /**
- * Retrieve the Bluetooth Adapter's name and address and save it in
- * in the local cache
- */
- private void loadStoredNameAndAddress() {
- if (DBG) {
- Slog.d(TAG, "Loading stored name and address");
- }
- if (mContext.getResources()
- .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation)
- && Settings.Secure.getIntForUser(mContentResolver,
- SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0, mUserId)
- == 0) {
- // if the valid flag is not set, don't load the address and name
- if (DBG) {
- Slog.d(TAG, "invalid bluetooth name and address stored");
- }
- return;
- }
- mName = Settings.Secure.getStringForUser(
- mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, mUserId);
- mAddress = Settings.Secure.getStringForUser(
- mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, mUserId);
- if (DBG) {
- Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
- }
- }
-
- /**
- * Save the Bluetooth name and address in the persistent store.
- * Only non-null values will be saved.
- * @param name
- * @param address
- */
- private void storeNameAndAddress(String name, String address) {
- if (name != null) {
- Settings.Secure.putStringForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name,
- mUserId);
- mName = name;
- if (DBG) {
- Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getStringForUser(
- mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME,
- mUserId));
- }
- }
-
- if (address != null) {
- Settings.Secure.putStringForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS,
- address, mUserId);
- mAddress = address;
- if (DBG) {
- Slog.d(TAG,
- "Stored Bluetoothaddress: " + Settings.Secure.getStringForUser(
- mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS,
- mUserId));
- }
- }
-
- if ((name != null) && (address != null)) {
- Settings.Secure.putIntForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1,
- mUserId);
- }
- }
-
- public IBluetooth registerAdapter(IBluetoothManagerCallback callback) {
- if (callback == null) {
- Slog.w(TAG, "Callback is null in registerAdapter");
- return null;
- }
- synchronized (mCallbacks) {
- mCallbacks.register(callback);
- }
- return mBluetooth;
- }
-
- public void unregisterAdapter(IBluetoothManagerCallback callback) {
- if (callback == null) {
- Slog.w(TAG, "Callback is null in unregisterAdapter");
- return;
- }
- synchronized (mCallbacks) {
- mCallbacks.unregister(callback);
- }
- }
-
- public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
- if (callback == null) {
- Slog.w(TAG, "registerStateChangeCallback: Callback is null!");
- return;
- }
- Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
- msg.obj = callback;
- mHandler.sendMessage(msg);
- }
-
- public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
- if (callback == null) {
- Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!");
- return;
- }
- Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
- msg.obj = callback;
- mHandler.sendMessage(msg);
- }
-
- public boolean isEnabled() {
- return getState() == BluetoothAdapter.STATE_ON;
- }
-
- public int getState() {
- if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
- Slog.w(TAG, "getState(): report OFF for non-active and non system user");
- return BluetoothAdapter.STATE_OFF;
- }
-
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- return mBluetooth.getState();
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "getState()", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
- return BluetoothAdapter.STATE_OFF;
- }
-
- class ClientDeathRecipient implements IBinder.DeathRecipient {
- private String mPackageName;
-
- ClientDeathRecipient(String packageName) {
- mPackageName = packageName;
- }
-
- public void binderDied() {
- if (DBG) {
- Slog.d(TAG, "Binder is dead - unregister " + mPackageName);
- }
-
- for (Map.Entry<IBinder, ClientDeathRecipient> entry : mBleApps.entrySet()) {
- IBinder token = entry.getKey();
- ClientDeathRecipient deathRec = entry.getValue();
- if (deathRec.equals(this)) {
- updateBleAppCount(token, false, mPackageName);
- break;
- }
- }
- }
-
- public String getPackageName() {
- return mPackageName;
- }
- }
-
- @Override
- public boolean isBleScanAlwaysAvailable() {
- if (isAirplaneModeOn() && !mEnable) {
- return false;
- }
- try {
- return Settings.Global.getInt(mContentResolver,
- Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0;
- } catch (SettingNotFoundException e) {
- }
- return false;
- }
-
- @Override
- public boolean isHearingAidProfileSupported() {
- return mIsHearingAidProfileSupported;
- }
-
- private boolean isDeviceProvisioned() {
- return Settings.Global.getInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED,
- 0) != 0;
- }
-
- // Monitor change of BLE scan only mode settings.
- private void registerForProvisioningStateChange() {
- ContentObserver contentObserver = new ContentObserver(null) {
- @Override
- public void onChange(boolean selfChange) {
- if (!isDeviceProvisioned()) {
- if (DBG) {
- Slog.d(TAG, "DEVICE_PROVISIONED setting changed, but device is not "
- + "provisioned");
- }
- return;
- }
- if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED)) {
- Slog.i(TAG, "Device provisioned, reactivating pending flag changes");
- onInitFlagsChanged();
- }
- }
- };
-
- mContentResolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), false,
- contentObserver);
- }
-
- // Monitor change of BLE scan only mode settings.
- private void registerForBleScanModeChange() {
- ContentObserver contentObserver = new ContentObserver(null) {
- @Override
- public void onChange(boolean selfChange) {
- if (isBleScanAlwaysAvailable()) {
- // Nothing to do
- return;
- }
- // BLE scan is not available.
- disableBleScanMode();
- clearBleApps();
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
- mContext.getPackageName(), false);
- mBluetooth.onBrEdrDown(mContext.getAttributionSource());
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "error when disabling bluetooth", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
- }
- };
-
- mContentResolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), false,
- contentObserver);
- }
-
- // Disable ble scan only mode.
- private void disableBleScanMode() {
- try {
- mBluetoothLock.writeLock().lock();
- if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
- if (DBG) {
- Slog.d(TAG, "Reseting the mEnable flag for clean disable");
- }
- mEnable = false;
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "getState()", e);
- } finally {
- mBluetoothLock.writeLock().unlock();
- }
- }
-
- private int updateBleAppCount(IBinder token, boolean enable, String packageName) {
- ClientDeathRecipient r = mBleApps.get(token);
- if (r == null && enable) {
- ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
- try {
- token.linkToDeath(deathRec, 0);
- } catch (RemoteException ex) {
- throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
- }
- mBleApps.put(token, deathRec);
- if (DBG) {
- Slog.d(TAG, "Registered for death of " + packageName);
- }
- } else if (!enable && r != null) {
- // Unregister death recipient as the app goes away.
- token.unlinkToDeath(r, 0);
- mBleApps.remove(token);
- if (DBG) {
- Slog.d(TAG, "Unregistered for death of " + packageName);
- }
- }
- int appCount = mBleApps.size();
- if (DBG) {
- Slog.d(TAG, appCount + " registered Ble Apps");
- }
- return appCount;
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private boolean checkBluetoothPermissions(AttributionSource attributionSource, String message,
- boolean requireForeground) {
- if (isBluetoothDisallowed()) {
- if (DBG) {
- Slog.d(TAG, "checkBluetoothPermissions: bluetooth disallowed");
- }
- return false;
- }
- // Check if packageName belongs to callingUid
- final int callingUid = Binder.getCallingUid();
- final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
- if (!isCallerSystem) {
- checkPackage(callingUid, attributionSource.getPackageName());
-
- if (requireForeground && !checkIfCallerIsForegroundUser()) {
- Slog.w(TAG, "Not allowed for non-active and non system user");
- return false;
- }
-
- if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, message)) {
- return false;
- }
- }
- return true;
- }
-
- public boolean enableBle(AttributionSource attributionSource, IBinder token)
- throws RemoteException {
- final String packageName = attributionSource.getPackageName();
- if (!checkBluetoothPermissions(attributionSource, "enableBle", false)) {
- if (DBG) {
- Slog.d(TAG, "enableBle(): bluetooth disallowed");
- }
- return false;
- }
-
- if (DBG) {
- Slog.d(TAG, "enableBle(" + packageName + "): mBluetooth =" + mBluetooth
- + " mBinding = " + mBinding + " mState = "
- + BluetoothAdapter.nameForState(mState));
- }
- updateBleAppCount(token, true, packageName);
-
- if (mState == BluetoothAdapter.STATE_ON
- || mState == BluetoothAdapter.STATE_BLE_ON
- || mState == BluetoothAdapter.STATE_TURNING_ON
- || mState == BluetoothAdapter.STATE_TURNING_OFF
- || mState == BluetoothAdapter.STATE_BLE_TURNING_ON) {
- Log.d(TAG, "enableBLE(): Bluetooth is already enabled or is turning on");
- return true;
- }
- synchronized (mReceiver) {
- // waive WRITE_SECURE_SETTINGS permission check
- sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
- packageName, true);
- }
- return true;
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public boolean disableBle(AttributionSource attributionSource, IBinder token)
- throws RemoteException {
- final String packageName = attributionSource.getPackageName();
- if (!checkBluetoothPermissions(attributionSource, "disableBle", false)) {
- if (DBG) {
- Slog.d(TAG, "disableBLE(): bluetooth disallowed");
- }
- return false;
- }
-
- if (DBG) {
- Slog.d(TAG, "disableBle(" + packageName + "): mBluetooth =" + mBluetooth
- + " mBinding = " + mBinding + " mState = "
- + BluetoothAdapter.nameForState(mState));
- }
-
- if (mState == BluetoothAdapter.STATE_OFF) {
- Slog.d(TAG, "disableBLE(): Already disabled");
- return false;
- }
- updateBleAppCount(token, false, packageName);
-
- if (mState == BluetoothAdapter.STATE_BLE_ON && !isBleAppPresent()) {
- if (mEnable) {
- disableBleScanMode();
- }
- if (!mEnableExternal) {
- addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
- packageName, false);
- sendBrEdrDownCallback(attributionSource);
- }
- }
- return true;
- }
-
- // Clear all apps using BLE scan only mode.
- private void clearBleApps() {
- mBleApps.clear();
- }
-
- /** @hide */
- public boolean isBleAppPresent() {
- if (DBG) {
- Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
- }
- return mBleApps.size() > 0;
- }
-
- /**
- * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on,
- * call IBluetooth.onBrEdrDown() to disable if Bluetooth should be off.
- */
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- private void continueFromBleOnState() {
- if (DBG) {
- Slog.d(TAG, "continueFromBleOnState()");
- }
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth == null) {
- Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!");
- return;
- }
- if (!mEnableExternal && !isBleAppPresent()) {
- Slog.i(TAG, "Bluetooth was disabled while enabling BLE, disable BLE now");
- mEnable = false;
- mBluetooth.onBrEdrDown(mContext.getAttributionSource());
- return;
- }
- if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
- // This triggers transition to STATE_ON
- mBluetooth.onLeServiceUp(mContext.getAttributionSource());
- persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call onServiceUp", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
- }
-
- /**
- * Inform BluetoothAdapter instances that BREDR part is down
- * and turn off all service and stack if no LE app needs it
- */
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- private void sendBrEdrDownCallback(AttributionSource attributionSource) {
- if (DBG) {
- Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks");
- }
-
- if (mBluetooth == null) {
- Slog.w(TAG, "Bluetooth handle is null");
- return;
- }
-
- if (isBleAppPresent()) {
- // Need to stay at BLE ON. Disconnect all Gatt connections
- try {
- mBluetoothGatt.unregAll(attributionSource);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to disconnect all apps.", e);
- }
- } else {
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- mBluetooth.onBrEdrDown(attributionSource);
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
- }
-
- }
-
- public boolean enableNoAutoConnect(AttributionSource attributionSource) {
- final String packageName = attributionSource.getPackageName();
- if (!checkBluetoothPermissions(attributionSource, "enableNoAutoConnect", false)) {
- if (DBG) {
- Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
- }
- return false;
- }
-
- if (DBG) {
- Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = "
- + mBinding);
- }
-
- int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
- if (callingAppId != Process.NFC_UID) {
- throw new SecurityException("no permission to enable Bluetooth quietly");
- }
-
- synchronized (mReceiver) {
- mQuietEnableExternal = true;
- mEnableExternal = true;
- sendEnableMsg(true,
- BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
- }
- return true;
- }
-
- public boolean enable(AttributionSource attributionSource) throws RemoteException {
- final String packageName = attributionSource.getPackageName();
- if (!checkBluetoothPermissions(attributionSource, "enable", true)) {
- if (DBG) {
- Slog.d(TAG, "enable(): not enabling - bluetooth disallowed");
- }
- return false;
- }
-
- final int callingUid = Binder.getCallingUid();
- final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
- if (!callerSystem && !isEnabled() && mWirelessConsentRequired
- && startConsentUiIfNeeded(packageName,
- callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
- return false;
- }
-
- if (DBG) {
- Slog.d(TAG, "enable(" + packageName + "): mBluetooth =" + mBluetooth + " mBinding = "
- + mBinding + " mState = " + BluetoothAdapter.nameForState(mState));
- }
-
- synchronized (mReceiver) {
- mQuietEnableExternal = false;
- mEnableExternal = true;
- // waive WRITE_SECURE_SETTINGS permission check
- sendEnableMsg(false,
- BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
- }
- if (DBG) {
- Slog.d(TAG, "enable returning");
- }
- return true;
- }
-
- public boolean disable(AttributionSource attributionSource, boolean persist)
- throws RemoteException {
- if (!persist) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
- "Need BLUETOOTH_PRIVILEGED permission");
- }
-
- final String packageName = attributionSource.getPackageName();
- if (!checkBluetoothPermissions(attributionSource, "disable", true)) {
- if (DBG) {
- Slog.d(TAG, "disable(): not disabling - bluetooth disallowed");
- }
- return false;
- }
-
- final int callingUid = Binder.getCallingUid();
- final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
- if (!callerSystem && isEnabled() && mWirelessConsentRequired
- && startConsentUiIfNeeded(packageName,
- callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
- return false;
- }
-
- if (DBG) {
- Slog.d(TAG, "disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding);
- }
-
- synchronized (mReceiver) {
- if (!isBluetoothPersistedStateOnAirplane()) {
- if (persist) {
- persistBluetoothSetting(BLUETOOTH_OFF);
- }
- mEnableExternal = false;
- }
- sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
- packageName);
- }
- return true;
- }
-
- private boolean startConsentUiIfNeeded(String packageName,
- int callingUid, String intentAction) throws RemoteException {
- if (checkBluetoothPermissionWhenWirelessConsentRequired()) {
- return false;
- }
- try {
- // Validate the package only if we are going to use it
- ApplicationInfo applicationInfo = mContext.getPackageManager()
- .getApplicationInfoAsUser(packageName,
- PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
- UserHandle.getUserId(callingUid));
- if (applicationInfo.uid != callingUid) {
- throw new SecurityException("Package " + packageName
- + " not in uid " + callingUid);
- }
-
- Intent intent = new Intent(intentAction);
- intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
- intent.setFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- try {
- mContext.startActivity(intent);
- } catch (ActivityNotFoundException e) {
- // Shouldn't happen
- Slog.e(TAG, "Intent to handle action " + intentAction + " missing");
- return false;
- }
- return true;
- } catch (PackageManager.NameNotFoundException e) {
- throw new RemoteException(e.getMessage());
- }
- }
-
- /**
- * Check if AppOpsManager is available and the packageName belongs to uid
- *
- * A null package belongs to any uid
- */
- private void checkPackage(int uid, String packageName) {
- if (mAppOps == null) {
- Slog.w(TAG, "checkPackage(): called before system boot up, uid "
- + uid + ", packageName " + packageName);
- throw new IllegalStateException("System has not boot yet");
- }
- if (packageName == null) {
- Slog.w(TAG, "checkPackage(): called with null packageName from " + uid);
- return;
- }
- try {
- mAppOps.checkPackage(uid, packageName);
- } catch (SecurityException e) {
- Slog.w(TAG, "checkPackage(): " + packageName + " does not belong to uid " + uid);
- throw new SecurityException(e.getMessage());
- }
- }
-
- /**
- * Check if the caller must still pass permission check or if the caller is exempted
- * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check.
- *
- * Commands from some callers may be exempted from triggering the consent UI when
- * enabling bluetooth. This exemption is checked via the
- * MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED and allows calls to skip
- * the consent UI where it may otherwise be required.
- *
- * @hide
- */
- @SuppressLint("AndroidFrameworkRequiresPermission")
- private boolean checkBluetoothPermissionWhenWirelessConsentRequired() {
- int result = mContext.checkCallingPermission(
- android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED);
- return result == PackageManager.PERMISSION_GRANTED;
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void unbindAndFinish() {
- if (DBG) {
- Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding
- + " mUnbinding = " + mUnbinding);
- }
-
- try {
- mBluetoothLock.writeLock().lock();
- if (mUnbinding) {
- return;
- }
- mUnbinding = true;
- mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
- mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE);
- if (mBluetooth != null) {
- //Unregister callback object
- try {
- mBluetooth.unregisterCallback(mBluetoothCallback,
- mContext.getAttributionSource());
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to unregister BluetoothCallback", re);
- }
- mBluetoothBinder = null;
- mBluetooth = null;
- mContext.unbindService(mConnection);
- mUnbinding = false;
- mBinding = false;
- } else {
- mUnbinding = false;
- }
- mBluetoothGatt = null;
- } finally {
- mBluetoothLock.writeLock().unlock();
- }
- }
-
- public IBluetoothGatt getBluetoothGatt() {
- // sync protection
- return mBluetoothGatt;
- }
-
- @Override
- public boolean bindBluetoothProfileService(int bluetoothProfile,
- IBluetoothProfileServiceConnection proxy) {
- if (mState != BluetoothAdapter.STATE_ON) {
- if (DBG) {
- Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile
- + ", while Bluetooth was disabled");
- }
- return false;
- }
- synchronized (mProfileServices) {
- ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
- if (psc == null) {
- if (DBG) {
- Slog.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: "
- + bluetoothProfile);
- }
-
- Intent intent;
- if (bluetoothProfile == BluetoothProfile.HEADSET) {
- intent = new Intent(IBluetoothHeadset.class.getName());
- } else if (bluetoothProfile== BluetoothProfile.LE_CALL_CONTROL) {
- intent = new Intent(IBluetoothLeCallControl.class.getName());
- } else {
- return false;
- }
-
- psc = new ProfileServiceConnections(intent);
- if (!psc.bindService()) {
- return false;
- }
-
- mProfileServices.put(new Integer(bluetoothProfile), psc);
- }
- }
-
- // Introducing a delay to give the client app time to prepare
- Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
- addProxyMsg.arg1 = bluetoothProfile;
- addProxyMsg.obj = proxy;
- mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
- return true;
- }
-
- @Override
- public void unbindBluetoothProfileService(int bluetoothProfile,
- IBluetoothProfileServiceConnection proxy) {
- synchronized (mProfileServices) {
- Integer profile = new Integer(bluetoothProfile);
- ProfileServiceConnections psc = mProfileServices.get(profile);
- if (psc == null) {
- return;
- }
- psc.removeProxy(proxy);
- if (psc.isEmpty()) {
- // All prxoies are disconnected, unbind with the service.
- try {
- mContext.unbindService(psc);
- } catch (IllegalArgumentException e) {
- Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
- }
- mProfileServices.remove(profile);
- }
- }
- }
-
- private void unbindAllBluetoothProfileServices() {
- synchronized (mProfileServices) {
- for (Integer i : mProfileServices.keySet()) {
- ProfileServiceConnections psc = mProfileServices.get(i);
- try {
- mContext.unbindService(psc);
- } catch (IllegalArgumentException e) {
- Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
- }
- psc.removeAllProxies();
- }
- mProfileServices.clear();
- }
- }
-
- /**
- * Send enable message and set adapter name and address. Called when the boot phase becomes
- * PHASE_SYSTEM_SERVICES_READY.
- */
- public void handleOnBootPhase() {
- if (DBG) {
- Slog.d(TAG, "Bluetooth boot completed");
- }
- mAppOps = mContext.getSystemService(AppOpsManager.class);
- UserManagerInternal userManagerInternal =
- LocalServices.getService(UserManagerInternal.class);
- userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
- final boolean isBluetoothDisallowed = isBluetoothDisallowed();
- if (isBluetoothDisallowed) {
- return;
- }
- final boolean isSafeMode = mContext.getPackageManager().isSafeMode();
- if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) {
- if (DBG) {
- Slog.d(TAG, "Auto-enabling Bluetooth.");
- }
- sendEnableMsg(mQuietEnableExternal,
- BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
- mContext.getPackageName());
- } else if (!isNameAndAddressSet()) {
- if (DBG) {
- Slog.d(TAG, "Getting adapter name and address");
- }
- Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
- mHandler.sendMessage(getMsg);
- }
-
- mBluetoothModeChangeHelper = new BluetoothModeChangeHelper(mContext);
- if (mBluetoothAirplaneModeListener != null) {
- mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper);
- }
- registerForProvisioningStateChange();
- mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this, DBG);
- }
-
- /**
- * Called when switching to a different foreground user.
- */
- public void handleOnSwitchUser(int userHandle) {
- if (DBG) {
- Slog.d(TAG, "User " + userHandle + " switched");
- }
- mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
- }
-
- /**
- * Called when user is unlocked.
- */
- public void handleOnUnlockUser(int userHandle) {
- if (DBG) {
- Slog.d(TAG, "User " + userHandle + " unlocked");
- }
- mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
- }
-
- /**
- * This class manages the clients connected to a given ProfileService
- * and maintains the connection with that service.
- */
- private final class ProfileServiceConnections
- implements ServiceConnection, IBinder.DeathRecipient {
- final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies =
- new RemoteCallbackList<IBluetoothProfileServiceConnection>();
- IBinder mService;
- ComponentName mClassName;
- Intent mIntent;
- boolean mInvokingProxyCallbacks = false;
-
- ProfileServiceConnections(Intent intent) {
- mService = null;
- mClassName = null;
- mIntent = intent;
- }
-
- private boolean bindService() {
- int state = BluetoothAdapter.STATE_OFF;
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- state = mBluetooth.getState();
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call getState", e);
- return false;
- } finally {
- mBluetoothLock.readLock().unlock();
- }
-
- if (state != BluetoothAdapter.STATE_ON) {
- if (DBG) {
- Slog.d(TAG, "Unable to bindService while Bluetooth is disabled");
- }
- return false;
- }
-
- if (mIntent != null && mService == null && doBind(mIntent, this, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
- msg.obj = this;
- mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
- return true;
- }
- Slog.w(TAG, "Unable to bind with intent: " + mIntent);
- return false;
- }
-
- private void addProxy(IBluetoothProfileServiceConnection proxy) {
- mProxies.register(proxy);
- if (mService != null) {
- try {
- proxy.onServiceConnected(mClassName, mService);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to connect to proxy", e);
- }
- } else {
- if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
- Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
- msg.obj = this;
- mHandler.sendMessage(msg);
- }
- }
- }
-
- private void removeProxy(IBluetoothProfileServiceConnection proxy) {
- if (proxy != null) {
- if (mProxies.unregister(proxy)) {
- try {
- proxy.onServiceDisconnected(mClassName);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to disconnect proxy", e);
- }
- }
- } else {
- Slog.w(TAG, "Trying to remove a null proxy");
- }
- }
-
- private void removeAllProxies() {
- onServiceDisconnected(mClassName);
- mProxies.kill();
- }
-
- private boolean isEmpty() {
- return mProxies.getRegisteredCallbackCount() == 0;
- }
-
- @Override
- public void onServiceConnected(ComponentName className, IBinder service) {
- // remove timeout message
- mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
- mService = service;
- mClassName = className;
- try {
- mService.linkToDeath(this, 0);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to linkToDeath", e);
- }
-
- if (mInvokingProxyCallbacks) {
- Slog.e(TAG, "Proxy callbacks already in progress.");
- return;
- }
- mInvokingProxyCallbacks = true;
-
- final int n = mProxies.beginBroadcast();
- try {
- for (int i = 0; i < n; i++) {
- try {
- mProxies.getBroadcastItem(i).onServiceConnected(className, service);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to connect to proxy", e);
- }
- }
- } finally {
- mProxies.finishBroadcast();
- mInvokingProxyCallbacks = false;
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName className) {
- if (mService == null) {
- return;
- }
- try {
- mService.unlinkToDeath(this, 0);
- } catch (NoSuchElementException e) {
- Log.e(TAG, "error unlinking to death", e);
- }
- mService = null;
- mClassName = null;
-
- if (mInvokingProxyCallbacks) {
- Slog.e(TAG, "Proxy callbacks already in progress.");
- return;
- }
- mInvokingProxyCallbacks = true;
-
- final int n = mProxies.beginBroadcast();
- try {
- for (int i = 0; i < n; i++) {
- try {
- mProxies.getBroadcastItem(i).onServiceDisconnected(className);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to disconnect from proxy", e);
- }
- }
- } finally {
- mProxies.finishBroadcast();
- mInvokingProxyCallbacks = false;
- }
- }
-
- @Override
- public void binderDied() {
- if (DBG) {
- Slog.w(TAG, "Profile service for profile: " + mClassName + " died.");
- }
- onServiceDisconnected(mClassName);
- // Trigger rebind
- Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
- msg.obj = this;
- mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
- }
- }
-
- private void sendBluetoothStateCallback(boolean isUp) {
- try {
- int n = mStateChangeCallbacks.beginBroadcast();
- if (DBG) {
- Slog.d(TAG, "Broadcasting onBluetoothStateChange(" + isUp + ") to " + n
- + " receivers.");
- }
- for (int i = 0; i < n; i++) {
- try {
- mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e);
- }
- }
- } finally {
- mStateChangeCallbacks.finishBroadcast();
- }
- }
-
- /**
- * Inform BluetoothAdapter instances that Adapter service is up
- */
- private void sendBluetoothServiceUpCallback() {
- synchronized (mCallbacks) {
- try {
- int n = mCallbacks.beginBroadcast();
- Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
- for (int i = 0; i < n; i++) {
- try {
- mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
- }
- }
- } finally {
- mCallbacks.finishBroadcast();
- }
- }
- }
-
- /**
- * Inform BluetoothAdapter instances that Adapter service is down
- */
- private void sendBluetoothServiceDownCallback() {
- synchronized (mCallbacks) {
- try {
- int n = mCallbacks.beginBroadcast();
- Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
- for (int i = 0; i < n; i++) {
- try {
- mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
- }
- }
- } finally {
- mCallbacks.finishBroadcast();
- }
- }
- }
-
- public String getAddress(AttributionSource attributionSource) {
- if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, "getAddress")) {
- return null;
- }
-
- if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
- Slog.w(TAG, "getAddress(): not allowed for non-active and non system user");
- return null;
- }
-
- if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
- != PackageManager.PERMISSION_GRANTED) {
- return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
- }
-
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- return mBluetooth.getAddressWithAttribution(attributionSource);
- }
- } catch (RemoteException e) {
- Slog.e(TAG,
- "getAddress(): Unable to retrieve address remotely. Returning cached address",
- e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
-
- // mAddress is accessed from outside.
- // It is alright without a lock. Here, bluetooth is off, no other thread is
- // changing mAddress
- return mAddress;
- }
-
- public String getName(AttributionSource attributionSource) {
- if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, "getName")) {
- return null;
- }
-
- if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
- Slog.w(TAG, "getName(): not allowed for non-active and non system user");
- return null;
- }
-
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- return mBluetooth.getName(attributionSource);
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
-
- // mName is accessed from outside.
- // It alright without a lock. Here, bluetooth is off, no other thread is
- // changing mName
- return mName;
- }
-
- private class BluetoothServiceConnection implements ServiceConnection {
- public void onServiceConnected(ComponentName componentName, IBinder service) {
- String name = componentName.getClassName();
- if (DBG) {
- Slog.d(TAG, "BluetoothServiceConnection: " + name);
- }
- Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
- if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
- msg.arg1 = SERVICE_IBLUETOOTH;
- } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
- msg.arg1 = SERVICE_IBLUETOOTHGATT;
- } else {
- Slog.e(TAG, "Unknown service connected: " + name);
- return;
- }
- msg.obj = service;
- mHandler.sendMessage(msg);
- }
-
- public void onServiceDisconnected(ComponentName componentName) {
- // Called if we unexpectedly disconnect.
- String name = componentName.getClassName();
- if (DBG) {
- Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
- }
- Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
- if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
- msg.arg1 = SERVICE_IBLUETOOTH;
- } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
- msg.arg1 = SERVICE_IBLUETOOTHGATT;
- } else {
- Slog.e(TAG, "Unknown service disconnected: " + name);
- return;
- }
- mHandler.sendMessage(msg);
- }
- }
-
- private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
-
- private class BluetoothHandler extends Handler {
- boolean mGetNameAddressOnly = false;
- private int mWaitForEnableRetry;
- private int mWaitForDisableRetry;
-
- BluetoothHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_GET_NAME_AND_ADDRESS:
- if (DBG) {
- Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
- }
- try {
- mBluetoothLock.writeLock().lock();
- if ((mBluetooth == null) && (!mBinding)) {
- if (DBG) {
- Slog.d(TAG, "Binding to service to get name and address");
- }
- mGetNameAddressOnly = true;
- Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
- mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
- Intent i = new Intent(IBluetooth.class.getName());
- if (!doBind(i, mConnection,
- Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
- UserHandle.CURRENT)) {
- mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
- } else {
- mBinding = true;
- }
- } else if (mBluetooth != null) {
- try {
- storeNameAndAddress(
- mBluetooth.getName(mContext.getAttributionSource()),
- mBluetooth.getAddressWithAttribution(
- mContext.getAttributionSource()));
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to grab names", re);
- }
- if (mGetNameAddressOnly && !mEnable) {
- unbindAndFinish();
- }
- mGetNameAddressOnly = false;
- }
- } finally {
- mBluetoothLock.writeLock().unlock();
- }
- break;
-
- case MESSAGE_ENABLE:
- int quietEnable = msg.arg1;
- int isBle = msg.arg2;
- if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
- || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
- // We are handling enable or disable right now, wait for it.
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE,
- quietEnable, isBle), ENABLE_DISABLE_DELAY_MS);
- break;
- }
-
- if (DBG) {
- Slog.d(TAG, "MESSAGE_ENABLE(" + quietEnable + "): mBluetooth = "
- + mBluetooth);
- }
- mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
- mEnable = true;
-
- if (isBle == 0) {
- persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
- }
-
- // Use service interface to get the exact state
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- boolean isHandled = true;
- int state = mBluetooth.getState();
- switch (state) {
- case BluetoothAdapter.STATE_BLE_ON:
- if (isBle == 1) {
- Slog.i(TAG, "Already at BLE_ON State");
- } else {
- Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
- mBluetooth.onLeServiceUp(mContext.getAttributionSource());
- }
- break;
- case BluetoothAdapter.STATE_BLE_TURNING_ON:
- case BluetoothAdapter.STATE_TURNING_ON:
- case BluetoothAdapter.STATE_ON:
- Slog.i(TAG, "MESSAGE_ENABLE: already enabled");
- break;
- default:
- isHandled = false;
- break;
- }
- if (isHandled) break;
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
-
- mQuietEnable = (quietEnable == 1);
- if (mBluetooth == null) {
- handleEnable(mQuietEnable);
- } else {
- //
- // We need to wait until transitioned to STATE_OFF and
- // the previous Bluetooth process has exited. The
- // waiting period has three components:
- // (a) Wait until the local state is STATE_OFF. This
- // is accomplished by sending delay a message
- // MESSAGE_HANDLE_ENABLE_DELAYED
- // (b) Wait until the STATE_OFF state is updated to
- // all components.
- // (c) Wait until the Bluetooth process exits, and
- // ActivityManager detects it.
- // The waiting for (b) and (c) is accomplished by
- // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
- // message. The delay time is backed off if Bluetooth
- // continuously failed to turn on itself.
- //
- mWaitForEnableRetry = 0;
- Message enableDelayedMsg =
- mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED);
- mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
- }
- break;
-
- case MESSAGE_DISABLE:
- if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mBinding
- || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
- // We are handling enable or disable right now, wait for it.
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_DISABLE),
- ENABLE_DISABLE_DELAY_MS);
- break;
- }
-
- if (DBG) {
- Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth
- + ", mBinding = " + mBinding);
- }
- mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
-
- if (mEnable && mBluetooth != null) {
- mWaitForDisableRetry = 0;
- Message disableDelayedMsg =
- mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0);
- mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
- } else {
- mEnable = false;
- handleDisable();
- }
- break;
-
- case MESSAGE_HANDLE_ENABLE_DELAYED: {
- // The Bluetooth is turning off, wait for STATE_OFF
- if (mState != BluetoothAdapter.STATE_OFF) {
- if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
- mWaitForEnableRetry++;
- Message enableDelayedMsg =
- mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED);
- mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
- break;
- } else {
- Slog.e(TAG, "Wait for STATE_OFF timeout");
- }
- }
- // Either state is changed to STATE_OFF or reaches the maximum retry, we
- // should move forward to the next step.
- mWaitForEnableRetry = 0;
- Message restartMsg =
- mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
- mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
- Slog.d(TAG, "Handle enable is finished");
- break;
- }
-
- case MESSAGE_HANDLE_DISABLE_DELAYED: {
- boolean disabling = (msg.arg1 == 1);
- Slog.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling);
- if (!disabling) {
- // The Bluetooth is turning on, wait for STATE_ON
- if (mState != BluetoothAdapter.STATE_ON) {
- if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
- mWaitForDisableRetry++;
- Message disableDelayedMsg = mHandler.obtainMessage(
- MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0);
- mHandler.sendMessageDelayed(disableDelayedMsg,
- ENABLE_DISABLE_DELAY_MS);
- break;
- } else {
- Slog.e(TAG, "Wait for STATE_ON timeout");
- }
- }
- // Either state is changed to STATE_ON or reaches the maximum retry, we
- // should move forward to the next step.
- mWaitForDisableRetry = 0;
- mEnable = false;
- handleDisable();
- // Wait for state exiting STATE_ON
- Message disableDelayedMsg =
- mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0);
- mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
- } else {
- // The Bluetooth is turning off, wait for exiting STATE_ON
- if (mState == BluetoothAdapter.STATE_ON) {
- if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
- mWaitForDisableRetry++;
- Message disableDelayedMsg = mHandler.obtainMessage(
- MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0);
- mHandler.sendMessageDelayed(disableDelayedMsg,
- ENABLE_DISABLE_DELAY_MS);
- break;
- } else {
- Slog.e(TAG, "Wait for exiting STATE_ON timeout");
- }
- }
- // Either state is exited from STATE_ON or reaches the maximum retry, we
- // should move forward to the next step.
- Slog.d(TAG, "Handle disable is finished");
- }
- break;
- }
-
- case MESSAGE_RESTORE_USER_SETTING:
- if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
- if (DBG) {
- Slog.d(TAG, "Restore Bluetooth state to disabled");
- }
- persistBluetoothSetting(BLUETOOTH_OFF);
- mEnableExternal = false;
- sendDisableMsg(
- BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
- mContext.getPackageName());
- } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
- if (DBG) {
- Slog.d(TAG, "Restore Bluetooth state to enabled");
- }
- mQuietEnableExternal = false;
- mEnableExternal = true;
- // waive WRITE_SECURE_SETTINGS permission check
- sendEnableMsg(false,
- BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
- mContext.getPackageName());
- }
- break;
- case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: {
- IBluetoothStateChangeCallback callback =
- (IBluetoothStateChangeCallback) msg.obj;
- mStateChangeCallbacks.register(callback);
- break;
- }
- case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: {
- IBluetoothStateChangeCallback callback =
- (IBluetoothStateChangeCallback) msg.obj;
- mStateChangeCallbacks.unregister(callback);
- break;
- }
- case MESSAGE_ADD_PROXY_DELAYED: {
- ProfileServiceConnections psc = mProfileServices.get(msg.arg1);
- if (psc == null) {
- break;
- }
- IBluetoothProfileServiceConnection proxy =
- (IBluetoothProfileServiceConnection) msg.obj;
- psc.addProxy(proxy);
- break;
- }
- case MESSAGE_BIND_PROFILE_SERVICE: {
- ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj;
- removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj);
- if (psc == null) {
- break;
- }
- psc.bindService();
- break;
- }
- case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
- if (DBG) {
- Slog.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
- }
-
- IBinder service = (IBinder) msg.obj;
- try {
- mBluetoothLock.writeLock().lock();
- if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
- mBluetoothGatt =
- IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service));
- continueFromBleOnState();
- break;
- } // else must be SERVICE_IBLUETOOTH
-
- //Remove timeout
- mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
-
- mBinding = false;
- mBluetoothBinder = service;
- mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
-
- if (!isNameAndAddressSet()) {
- Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
- mHandler.sendMessage(getMsg);
- if (mGetNameAddressOnly) {
- return;
- }
- }
-
- //Register callback object
- try {
- mBluetooth.registerCallback(mBluetoothCallback,
- mContext.getAttributionSource());
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to register BluetoothCallback", re);
- }
- //Inform BluetoothAdapter instances that service is up
- sendBluetoothServiceUpCallback();
-
- //Do enable request
- try {
- if (!mBluetooth.enable(mQuietEnable, mContext.getAttributionSource())) {
- Slog.e(TAG, "IBluetooth.enable() returned false");
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call enable()", e);
- }
- } finally {
- mBluetoothLock.writeLock().unlock();
- }
-
- if (!mEnable) {
- waitForState(Set.of(BluetoothAdapter.STATE_ON));
- handleDisable();
- waitForState(Set.of(BluetoothAdapter.STATE_OFF,
- BluetoothAdapter.STATE_TURNING_ON,
- BluetoothAdapter.STATE_TURNING_OFF,
- BluetoothAdapter.STATE_BLE_TURNING_ON,
- BluetoothAdapter.STATE_BLE_ON,
- BluetoothAdapter.STATE_BLE_TURNING_OFF));
- }
- break;
- }
- case MESSAGE_BLUETOOTH_STATE_CHANGE: {
- int prevState = msg.arg1;
- int newState = msg.arg2;
- if (DBG) {
- Slog.d(TAG,
- "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(
- prevState) + " > " + BluetoothAdapter.nameForState(
- newState));
- }
- mState = newState;
- bluetoothStateChangeHandler(prevState, newState);
- // handle error state transition case from TURNING_ON to OFF
- // unbind and rebind bluetooth service and enable bluetooth
- if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState
- == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) {
- recoverBluetoothServiceFromError(false);
- }
- if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState
- == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) {
- recoverBluetoothServiceFromError(true);
- }
- // If we tried to enable BT while BT was in the process of shutting down,
- // wait for the BT process to fully tear down and then force a restart
- // here. This is a bit of a hack (b/29363429).
- if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && (newState
- == BluetoothAdapter.STATE_OFF)) {
- if (mEnable) {
- Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
- waitForState(Set.of(BluetoothAdapter.STATE_OFF));
- Message restartMsg =
- mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
- mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
- }
- }
- if (newState == BluetoothAdapter.STATE_ON
- || newState == BluetoothAdapter.STATE_BLE_ON) {
- // bluetooth is working, reset the counter
- if (mErrorRecoveryRetryCounter != 0) {
- Slog.w(TAG, "bluetooth is recovered from error");
- mErrorRecoveryRetryCounter = 0;
- }
- }
- break;
- }
- case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: {
- Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")");
- try {
- mBluetoothLock.writeLock().lock();
- if (msg.arg1 == SERVICE_IBLUETOOTH) {
- // if service is unbinded already, do nothing and return
- if (mBluetooth == null) {
- break;
- }
- mBluetooth = null;
- } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
- mBluetoothGatt = null;
- break;
- } else {
- Slog.e(TAG, "Unknown argument for service disconnect!");
- break;
- }
- } finally {
- mBluetoothLock.writeLock().unlock();
- }
-
- // log the unexpected crash
- addCrashLog();
- addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH,
- mContext.getPackageName(), false);
- if (mEnable) {
- mEnable = false;
- // Send a Bluetooth Restart message
- Message restartMsg =
- mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
- mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
- }
-
- sendBluetoothServiceDownCallback();
-
- // Send BT state broadcast to update
- // the BT icon correctly
- if ((mState == BluetoothAdapter.STATE_TURNING_ON) || (mState
- == BluetoothAdapter.STATE_ON)) {
- bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
- BluetoothAdapter.STATE_TURNING_OFF);
- mState = BluetoothAdapter.STATE_TURNING_OFF;
- }
- if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
- bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
- BluetoothAdapter.STATE_OFF);
- }
-
- mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
- mState = BluetoothAdapter.STATE_OFF;
- break;
- }
- case MESSAGE_RESTART_BLUETOOTH_SERVICE: {
- mErrorRecoveryRetryCounter++;
- Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count="
- + mErrorRecoveryRetryCounter);
- if (mErrorRecoveryRetryCounter < MAX_ERROR_RESTART_RETRIES) {
- /* Enable without persisting the setting as
- it doesnt change when IBluetooth
- service restarts */
- mEnable = true;
- addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED,
- mContext.getPackageName(), true);
- handleEnable(mQuietEnable);
- } else {
- Slog.e(TAG, "Reach maximum retry to restart Bluetooth!");
- }
- break;
- }
- case MESSAGE_TIMEOUT_BIND: {
- Slog.e(TAG, "MESSAGE_TIMEOUT_BIND");
- mBluetoothLock.writeLock().lock();
- mBinding = false;
- mBluetoothLock.writeLock().unlock();
- break;
- }
- case MESSAGE_TIMEOUT_UNBIND: {
- Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
- mBluetoothLock.writeLock().lock();
- mUnbinding = false;
- mBluetoothLock.writeLock().unlock();
- break;
- }
-
- case MESSAGE_USER_SWITCHED: {
- if (DBG) {
- Slog.d(TAG, "MESSAGE_USER_SWITCHED");
- }
- mHandler.removeMessages(MESSAGE_USER_SWITCHED);
-
- /* disable and enable BT when detect a user switch */
- if (mBluetooth != null && isEnabled()) {
- restartForReason(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH);
- } else if (mBinding || mBluetooth != null) {
- Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
- userMsg.arg2 = 1 + msg.arg2;
- // if user is switched when service is binding retry after a delay
- mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
- if (DBG) {
- Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2);
- }
- }
- break;
- }
- case MESSAGE_USER_UNLOCKED: {
- if (DBG) {
- Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
- }
- mHandler.removeMessages(MESSAGE_USER_SWITCHED);
-
- if (mEnable && !mBinding && (mBluetooth == null)) {
- // We should be connected, but we gave up for some
- // reason; maybe the Bluetooth service wasn't encryption
- // aware, so try binding again.
- if (DBG) {
- Slog.d(TAG, "Enabled but not bound; retrying after unlock");
- }
- handleEnable(mQuietEnable);
- }
- break;
- }
- case MESSAGE_INIT_FLAGS_CHANGED: {
- if (DBG) {
- Slog.d(TAG, "MESSAGE_INIT_FLAGS_CHANGED");
- }
- mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED);
- if (mBluetoothModeChangeHelper.isMediaProfileConnected()) {
- Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by "
- + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS
- + " ms due to existing connections");
- mHandler.sendEmptyMessageDelayed(
- MESSAGE_INIT_FLAGS_CHANGED,
- DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS);
- break;
- }
- if (!isDeviceProvisioned()) {
- Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by "
- + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS
- + "ms because device is not provisioned");
- mHandler.sendEmptyMessageDelayed(
- MESSAGE_INIT_FLAGS_CHANGED,
- DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS);
- break;
- }
- if (mBluetooth != null && isEnabled()) {
- Slog.i(TAG, "Restarting Bluetooth due to init flag change");
- restartForReason(
- BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED);
- }
- break;
- }
- }
- }
-
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED
- })
- private void restartForReason(int reason) {
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- mBluetooth.unregisterCallback(mBluetoothCallback,
- mContext.getAttributionSource());
- }
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to unregister", re);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
-
- if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
- // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE
- bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF);
- mState = BluetoothAdapter.STATE_OFF;
- }
- if (mState == BluetoothAdapter.STATE_OFF) {
- bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON);
- mState = BluetoothAdapter.STATE_TURNING_ON;
- }
-
- waitForState(Set.of(BluetoothAdapter.STATE_ON));
-
- if (mState == BluetoothAdapter.STATE_TURNING_ON) {
- bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
- }
-
- unbindAllBluetoothProfileServices();
- // disable
- addActiveLog(reason, mContext.getPackageName(), false);
- handleDisable();
- // Pbap service need receive STATE_TURNING_OFF intent to close
- bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
- BluetoothAdapter.STATE_TURNING_OFF);
-
- boolean didDisableTimeout =
- !waitForState(Set.of(BluetoothAdapter.STATE_OFF));
-
- bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
- BluetoothAdapter.STATE_OFF);
- sendBluetoothServiceDownCallback();
-
- try {
- mBluetoothLock.writeLock().lock();
- if (mBluetooth != null) {
- mBluetooth = null;
- // Unbind
- mContext.unbindService(mConnection);
- }
- mBluetoothGatt = null;
- } finally {
- mBluetoothLock.writeLock().unlock();
- }
-
- //
- // If disabling Bluetooth times out, wait for an
- // additional amount of time to ensure the process is
- // shut down completely before attempting to restart.
- //
- if (didDisableTimeout) {
- SystemClock.sleep(3000);
- } else {
- SystemClock.sleep(100);
- }
-
- mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
- mState = BluetoothAdapter.STATE_OFF;
- // enable
- addActiveLog(reason, mContext.getPackageName(), true);
- // mEnable flag could have been reset on disableBLE. Reenable it.
- mEnable = true;
- handleEnable(mQuietEnable);
- }
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private void handleEnable(boolean quietMode) {
- mQuietEnable = quietMode;
-
- try {
- mBluetoothLock.writeLock().lock();
- if ((mBluetooth == null) && (!mBinding)) {
- Slog.d(TAG, "binding Bluetooth service");
- //Start bind timeout and bind
- Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
- mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
- Intent i = new Intent(IBluetooth.class.getName());
- if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
- UserHandle.CURRENT)) {
- mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
- } else {
- mBinding = true;
- }
- } else if (mBluetooth != null) {
- //Enable bluetooth
- try {
- if (!mBluetooth.enable(mQuietEnable, mContext.getAttributionSource())) {
- Slog.e(TAG, "IBluetooth.enable() returned false");
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call enable()", e);
- }
- }
- } finally {
- mBluetoothLock.writeLock().unlock();
- }
- }
-
- boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
- Slog.e(TAG, "Fail to bind to: " + intent);
- return false;
- }
- return true;
- }
-
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- private void handleDisable() {
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- if (DBG) {
- Slog.d(TAG, "Sending off request.");
- }
- if (!mBluetooth.disable(mContext.getAttributionSource())) {
- Slog.e(TAG, "IBluetooth.disable() returned false");
- }
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to call disable()", e);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
- }
-
- private boolean checkIfCallerIsForegroundUser() {
- int foregroundUser;
- int callingUser = UserHandle.getCallingUserId();
- int callingUid = Binder.getCallingUid();
- final long callingIdentity = Binder.clearCallingIdentity();
- UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- UserInfo ui = um.getProfileParent(callingUser);
- int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
- int callingAppId = UserHandle.getAppId(callingUid);
- boolean valid = false;
- try {
- foregroundUser = ActivityManager.getCurrentUser();
- valid = (callingUser == foregroundUser) || parentUser == foregroundUser
- || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid
- || callingAppId == Process.SHELL_UID;
- if (DBG && !valid) {
- Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser="
- + callingUser + " parentUser=" + parentUser + " foregroundUser="
- + foregroundUser);
- }
- } finally {
- Binder.restoreCallingIdentity(callingIdentity);
- }
- return valid;
- }
-
- private void sendBleStateChanged(int prevState, int newState) {
- if (DBG) {
- Slog.d(TAG,
- "Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + " > "
- + BluetoothAdapter.nameForState(newState));
- }
- // Send broadcast message to everyone else
- Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
- intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
- intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, getTempAllowlistBroadcastOptions());
- }
-
- private boolean isBleState(int state) {
- switch (state) {
- case BluetoothAdapter.STATE_BLE_ON:
- case BluetoothAdapter.STATE_BLE_TURNING_ON:
- case BluetoothAdapter.STATE_BLE_TURNING_OFF:
- return true;
- }
- return false;
- }
-
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- private void bluetoothStateChangeHandler(int prevState, int newState) {
- boolean isStandardBroadcast = true;
- if (prevState == newState) { // No change. Nothing to do.
- return;
- }
- // Notify all proxy objects first of adapter state change
- if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) {
- boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
- && newState == BluetoothAdapter.STATE_BLE_ON);
-
- if (newState == BluetoothAdapter.STATE_OFF) {
- // If Bluetooth is off, send service down event to proxy objects, and unbind
- if (DBG) {
- Slog.d(TAG, "Bluetooth is complete send Service Down");
- }
- sendBluetoothServiceDownCallback();
- unbindAndFinish();
- sendBleStateChanged(prevState, newState);
-
- /* Currently, the OFF intent is broadcasted externally only when we transition
- * from TURNING_OFF to BLE_ON state. So if the previous state is a BLE state,
- * we are guaranteed that the OFF intent has been broadcasted earlier and we
- * can safely skip it.
- * Conversely, if the previous state is not a BLE state, it indicates that some
- * sort of crash has occurred, moving us directly to STATE_OFF without ever
- * passing through BLE_ON. We should broadcast the OFF intent in this case. */
- isStandardBroadcast = !isBleState(prevState);
-
- } else if (!intermediate_off) {
- // connect to GattService
- if (DBG) {
- Slog.d(TAG, "Bluetooth is in LE only mode");
- }
- if (mBluetoothGatt != null || !mContext.getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
- continueFromBleOnState();
- } else {
- if (DBG) {
- Slog.d(TAG, "Binding Bluetooth GATT service");
- }
- Intent i = new Intent(IBluetoothGatt.class.getName());
- doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
- UserHandle.CURRENT);
- }
- sendBleStateChanged(prevState, newState);
- //Don't broadcase this as std intent
- isStandardBroadcast = false;
-
- } else if (intermediate_off) {
- if (DBG) {
- Slog.d(TAG, "Intermediate off, back to LE only mode");
- }
- // For LE only mode, broadcast as is
- sendBleStateChanged(prevState, newState);
- sendBluetoothStateCallback(false); // BT is OFF for general users
- // Broadcast as STATE_OFF
- newState = BluetoothAdapter.STATE_OFF;
- sendBrEdrDownCallback(mContext.getAttributionSource());
- }
- } else if (newState == BluetoothAdapter.STATE_ON) {
- boolean isUp = (newState == BluetoothAdapter.STATE_ON);
- sendBluetoothStateCallback(isUp);
- sendBleStateChanged(prevState, newState);
-
- } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON
- || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
- sendBleStateChanged(prevState, newState);
- isStandardBroadcast = false;
-
- } else if (newState == BluetoothAdapter.STATE_TURNING_ON
- || newState == BluetoothAdapter.STATE_TURNING_OFF) {
- sendBleStateChanged(prevState, newState);
- }
-
- if (isStandardBroadcast) {
- if (prevState == BluetoothAdapter.STATE_BLE_ON) {
- // Show prevState of BLE_ON as OFF to standard users
- prevState = BluetoothAdapter.STATE_OFF;
- }
- if (DBG) {
- Slog.d(TAG,
- "Sending State Change: " + BluetoothAdapter.nameForState(prevState) + " > "
- + BluetoothAdapter.nameForState(newState));
- }
- Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
- intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
- intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null,
- getTempAllowlistBroadcastOptions());
- }
- }
-
- private boolean waitForState(Set<Integer> states) {
- int i = 0;
- while (i < 10) {
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth == null) {
- break;
- }
- if (states.contains(mBluetooth.getState())) {
- return true;
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "getState()", e);
- break;
- } finally {
- mBluetoothLock.readLock().unlock();
- }
- SystemClock.sleep(300);
- i++;
- }
- Slog.e(TAG, "waitForState " + states + " time out");
- return false;
- }
-
- private void sendDisableMsg(int reason, String packageName) {
- mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
- addActiveLog(reason, packageName, false);
- }
-
- private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
- sendEnableMsg(quietMode, reason, packageName, false);
- }
-
- private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) {
- mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0,
- isBle ? 1 : 0));
- addActiveLog(reason, packageName, true);
- mLastEnabledTime = SystemClock.elapsedRealtime();
- }
-
- private void addActiveLog(int reason, String packageName, boolean enable) {
- synchronized (mActiveLogs) {
- if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
- mActiveLogs.remove();
- }
- mActiveLogs.add(
- new ActiveLog(reason, packageName, enable, System.currentTimeMillis()));
- }
-
- int state = enable ? FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED :
- FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED;
- FrameworkStatsLog.write_non_chained(FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED,
- Binder.getCallingUid(), null, state, reason, packageName);
- }
-
- private void addCrashLog() {
- synchronized (mCrashTimestamps) {
- if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) {
- mCrashTimestamps.removeFirst();
- }
- mCrashTimestamps.add(System.currentTimeMillis());
- mCrashes++;
- }
- }
-
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- private void recoverBluetoothServiceFromError(boolean clearBle) {
- Slog.e(TAG, "recoverBluetoothServiceFromError");
- try {
- mBluetoothLock.readLock().lock();
- if (mBluetooth != null) {
- //Unregister callback object
- mBluetooth.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource());
- }
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to unregister", re);
- } finally {
- mBluetoothLock.readLock().unlock();
- }
-
- SystemClock.sleep(500);
-
- // disable
- addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR,
- mContext.getPackageName(), false);
- handleDisable();
-
- waitForState(Set.of(BluetoothAdapter.STATE_OFF));
-
- sendBluetoothServiceDownCallback();
-
- try {
- mBluetoothLock.writeLock().lock();
- if (mBluetooth != null) {
- mBluetooth = null;
- // Unbind
- mContext.unbindService(mConnection);
- }
- mBluetoothGatt = null;
- } finally {
- mBluetoothLock.writeLock().unlock();
- }
-
- mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
- mState = BluetoothAdapter.STATE_OFF;
-
- if (clearBle) {
- clearBleApps();
- }
-
- mEnable = false;
-
- // Send a Bluetooth Restart message to reenable bluetooth
- Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
- mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS);
- }
-
- private boolean isBluetoothDisallowed() {
- final long callingIdentity = Binder.clearCallingIdentity();
- try {
- return mContext.getSystemService(UserManager.class)
- .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
- } finally {
- Binder.restoreCallingIdentity(callingIdentity);
- }
- }
-
- /**
- * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
- * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default
- * state if Bluetooth is not disallowed.
- *
- * @param userId user to disable bluetooth sharing for.
- * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed.
- */
- private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) {
- final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
- "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
- final int newState =
- bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
- : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
- try {
- final IPackageManager imp = AppGlobals.getPackageManager();
- imp.setComponentEnabledSetting(oppLauncherComponent, newState,
- PackageManager.DONT_KILL_APP, userId);
- } catch (Exception e) {
- // The component was not found, do nothing.
- }
- }
-
- private int getServiceRestartMs() {
- return (mErrorRecoveryRetryCounter + 1) * SERVICE_RESTART_TIME_MS;
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) {
- return;
- }
- if ((args.length > 0) && args[0].startsWith("--proto")) {
- dumpProto(fd);
- return;
- }
- String errorMsg = null;
-
- writer.println("Bluetooth Status");
- writer.println(" enabled: " + isEnabled());
- writer.println(" state: " + BluetoothAdapter.nameForState(mState));
- writer.println(" address: " + mAddress);
- writer.println(" name: " + mName);
- if (mEnable) {
- long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime;
- String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d",
- (int) (onDuration / (1000 * 60 * 60)),
- (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60),
- (int) (onDuration % 1000));
- writer.println(" time since enabled: " + onDurationString);
- }
-
- if (mActiveLogs.size() == 0) {
- writer.println("\nBluetooth never enabled!");
- } else {
- writer.println("\nEnable log:");
- for (ActiveLog log : mActiveLogs) {
- writer.println(" " + log);
- }
- }
-
- writer.println(
- "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
- if (mCrashes == CRASH_LOG_MAX_SIZE) {
- writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
- }
- for (Long time : mCrashTimestamps) {
- writer.println(" " + timeToLog(time));
- }
-
- writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s")
- + " registered");
- for (ClientDeathRecipient app : mBleApps.values()) {
- writer.println(" " + app.getPackageName());
- }
-
- writer.println("\nBluetoothManagerService:");
- writer.println(" mEnable:" + mEnable);
- writer.println(" mQuietEnable:" + mQuietEnable);
- writer.println(" mEnableExternal:" + mEnableExternal);
- writer.println(" mQuietEnableExternal:" + mQuietEnableExternal);
-
- writer.println("");
- writer.flush();
- if (args.length == 0) {
- // Add arg to produce output
- args = new String[1];
- args[0] = "--print";
- }
-
- if (mBluetoothBinder == null) {
- errorMsg = "Bluetooth Service not connected";
- } else {
- try {
- mBluetoothBinder.dump(fd, args);
- } catch (RemoteException re) {
- errorMsg = "RemoteException while dumping Bluetooth Service";
- }
- }
- if (errorMsg != null) {
- writer.println(errorMsg);
- }
- }
-
- private void dumpProto(FileDescriptor fd) {
- final ProtoOutputStream proto = new ProtoOutputStream(fd);
- proto.write(BluetoothManagerServiceDumpProto.ENABLED, isEnabled());
- proto.write(BluetoothManagerServiceDumpProto.STATE, mState);
- proto.write(BluetoothManagerServiceDumpProto.STATE_NAME,
- BluetoothAdapter.nameForState(mState));
- proto.write(BluetoothManagerServiceDumpProto.ADDRESS, mAddress);
- proto.write(BluetoothManagerServiceDumpProto.NAME, mName);
- if (mEnable) {
- proto.write(BluetoothManagerServiceDumpProto.LAST_ENABLED_TIME_MS, mLastEnabledTime);
- }
- proto.write(BluetoothManagerServiceDumpProto.CURR_TIMESTAMP_MS,
- SystemClock.elapsedRealtime());
- for (ActiveLog log : mActiveLogs) {
- long token = proto.start(BluetoothManagerServiceDumpProto.ACTIVE_LOGS);
- log.dump(proto);
- proto.end(token);
- }
- proto.write(BluetoothManagerServiceDumpProto.NUM_CRASHES, mCrashes);
- proto.write(BluetoothManagerServiceDumpProto.CRASH_LOG_MAXED,
- mCrashes == CRASH_LOG_MAX_SIZE);
- for (Long time : mCrashTimestamps) {
- proto.write(BluetoothManagerServiceDumpProto.CRASH_TIMESTAMPS_MS, time);
- }
- proto.write(BluetoothManagerServiceDumpProto.NUM_BLE_APPS, mBleApps.size());
- for (ClientDeathRecipient app : mBleApps.values()) {
- proto.write(BluetoothManagerServiceDumpProto.BLE_APP_PACKAGE_NAMES,
- app.getPackageName());
- }
- proto.flush();
- }
-
- private static String getEnableDisableReasonString(int reason) {
- switch (reason) {
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST:
- return "APPLICATION_REQUEST";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE:
- return "AIRPLANE_MODE";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED:
- return "DISALLOWED";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED:
- return "RESTARTED";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR:
- return "START_ERROR";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT:
- return "SYSTEM_BOOT";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH:
- return "CRASH";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH:
- return "USER_SWITCH";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
- return "RESTORE_USER_SETTING";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET:
- return "FACTORY_RESET";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED:
- return "INIT_FLAGS_CHANGED";
- case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
- default: return "UNKNOWN[" + reason + "]";
- }
- }
-
- @SuppressLint("AndroidFrameworkRequiresPermission")
- private static boolean checkPermissionForDataDelivery(Context context, String permission,
- AttributionSource attributionSource, String message) {
- final int result = PermissionChecker.checkPermissionForDataDeliveryFromDataSource(
- context, permission, PID_UNKNOWN,
- new AttributionSource(context.getAttributionSource(), attributionSource), message);
- if (result == PERMISSION_GRANTED) {
- return true;
- }
-
- final String msg = "Need " + permission + " permission for " + attributionSource + ": "
- + message;
- if (result == PERMISSION_HARD_DENIED) {
- throw new SecurityException(msg);
- } else {
- Log.w(TAG, msg);
- return false;
- }
- }
-
- /**
- * Returns true if the BLUETOOTH_CONNECT permission is granted for the calling app. Returns
- * false if the result is a soft denial. Throws SecurityException if the result is a hard
- * denial.
- *
- * <p>Should be used in situations where the app op should not be noted.
- */
- @SuppressLint("AndroidFrameworkRequiresPermission")
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public static boolean checkConnectPermissionForDataDelivery(
- Context context, AttributionSource attributionSource, String message) {
- return checkPermissionForDataDelivery(context, BLUETOOTH_CONNECT,
- attributionSource, message);
- }
-
- static @NonNull Bundle getTempAllowlistBroadcastOptions() {
- final long duration = 10_000;
- final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
- bOptions.setTemporaryAppAllowlist(duration,
- TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
- PowerExemptionManager.REASON_BLUETOOTH_BROADCAST, "");
- return bOptions.toBundle();
- }
-}
diff --git a/services/core/java/com/android/server/BluetoothModeChangeHelper.java b/services/core/java/com/android/server/BluetoothModeChangeHelper.java
deleted file mode 100644
index e5854c9..0000000
--- a/services/core/java/com/android/server/BluetoothModeChangeHelper.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.annotation.RequiresPermission;
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothHearingAid;
-import android.bluetooth.BluetoothLeAudio;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProfile.ServiceListener;
-import android.content.Context;
-import android.content.res.Resources;
-import android.provider.Settings;
-import android.widget.Toast;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Helper class that handles callout and callback methods without
- * complex logic.
- */
-public class BluetoothModeChangeHelper {
- private volatile BluetoothA2dp mA2dp;
- private volatile BluetoothHearingAid mHearingAid;
- private volatile BluetoothLeAudio mLeAudio;
- private final BluetoothAdapter mAdapter;
- private final Context mContext;
-
- BluetoothModeChangeHelper(Context context) {
- mAdapter = BluetoothAdapter.getDefaultAdapter();
- mContext = context;
-
- mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP);
- mAdapter.getProfileProxy(mContext, mProfileServiceListener,
- BluetoothProfile.HEARING_AID);
- mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.LE_AUDIO);
- }
-
- private final ServiceListener mProfileServiceListener = new ServiceListener() {
- @Override
- public void onServiceConnected(int profile, BluetoothProfile proxy) {
- // Setup Bluetooth profile proxies
- switch (profile) {
- case BluetoothProfile.A2DP:
- mA2dp = (BluetoothA2dp) proxy;
- break;
- case BluetoothProfile.HEARING_AID:
- mHearingAid = (BluetoothHearingAid) proxy;
- break;
- case BluetoothProfile.LE_AUDIO:
- mLeAudio = (BluetoothLeAudio) proxy;
- break;
- default:
- break;
- }
- }
-
- @Override
- public void onServiceDisconnected(int profile) {
- // Clear Bluetooth profile proxies
- switch (profile) {
- case BluetoothProfile.A2DP:
- mA2dp = null;
- break;
- case BluetoothProfile.HEARING_AID:
- mHearingAid = null;
- break;
- case BluetoothProfile.LE_AUDIO:
- mLeAudio = null;
- break;
- default:
- break;
- }
- }
- };
-
- @VisibleForTesting
- public boolean isMediaProfileConnected() {
- return isA2dpConnected() || isHearingAidConnected() || isLeAudioConnected();
- }
-
- @VisibleForTesting
- public boolean isBluetoothOn() {
- final BluetoothAdapter adapter = mAdapter;
- if (adapter == null) {
- return false;
- }
- return adapter.getLeState() == BluetoothAdapter.STATE_ON;
- }
-
- @VisibleForTesting
- public boolean isAirplaneModeOn() {
- return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
- }
-
- @VisibleForTesting
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
- public void onAirplaneModeChanged(BluetoothManagerService managerService) {
- managerService.onAirplaneModeChanged();
- }
-
- @VisibleForTesting
- public int getSettingsInt(String name) {
- return Settings.Global.getInt(mContext.getContentResolver(),
- name, 0);
- }
-
- @VisibleForTesting
- public void setSettingsInt(String name, int value) {
- Settings.Global.putInt(mContext.getContentResolver(),
- name, value);
- }
-
- @VisibleForTesting
- public void showToastMessage() {
- Resources r = mContext.getResources();
- final CharSequence text = r.getString(
- R.string.bluetooth_airplane_mode_toast, 0);
- Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
- }
-
- private boolean isA2dpConnected() {
- final BluetoothA2dp a2dp = mA2dp;
- if (a2dp == null) {
- return false;
- }
- return a2dp.getConnectedDevices().size() > 0;
- }
-
- private boolean isHearingAidConnected() {
- final BluetoothHearingAid hearingAid = mHearingAid;
- if (hearingAid == null) {
- return false;
- }
- return hearingAid.getConnectedDevices().size() > 0;
- }
-
- private boolean isLeAudioConnected() {
- final BluetoothLeAudio leAudio = mLeAudio;
- if (leAudio == null) {
- return false;
- }
- return leAudio.getConnectedDevices().size() > 0;
- }
-}
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
deleted file mode 100644
index 1a1eecd..0000000
--- a/services/core/java/com/android/server/BluetoothService.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2015 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.annotation.NonNull;
-import android.annotation.Nullable;
-import android.bluetooth.BluetoothAdapter;
-import android.content.Context;
-import android.os.UserManager;
-
-import com.android.server.SystemService.TargetUser;
-
-class BluetoothService extends SystemService {
- private BluetoothManagerService mBluetoothManagerService;
- private boolean mInitialized = false;
-
- public BluetoothService(Context context) {
- super(context);
- mBluetoothManagerService = new BluetoothManagerService(context);
- }
-
- private void initialize() {
- if (!mInitialized) {
- mBluetoothManagerService.handleOnBootPhase();
- mInitialized = true;
- }
- }
-
- @Override
- public void onStart() {
- }
-
- @Override
- public void onBootPhase(int phase) {
- if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
- publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
- mBluetoothManagerService);
- } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY &&
- !UserManager.isHeadlessSystemUserMode()) {
- initialize();
- }
- }
-
- @Override
- public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
- if (!mInitialized) {
- initialize();
- } else {
- mBluetoothManagerService.handleOnSwitchUser(to.getUserIdentifier());
- }
- }
-
- @Override
- public void onUserUnlocking(@NonNull TargetUser user) {
- mBluetoothManagerService.handleOnUnlockUser(user.getUserIdentifier());
- }
-}
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/SerialService.java b/services/core/java/com/android/server/SerialService.java
index 1abe458..e915fa1 100644
--- a/services/core/java/com/android/server/SerialService.java
+++ b/services/core/java/com/android/server/SerialService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.annotation.EnforcePermission;
import android.content.Context;
import android.hardware.ISerialManager;
import android.os.ParcelFileDescriptor;
@@ -34,9 +35,8 @@
com.android.internal.R.array.config_serialPorts);
}
+ @EnforcePermission(android.Manifest.permission.SERIAL_PORT)
public String[] getSerialPorts() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SERIAL_PORT, null);
-
ArrayList<String> ports = new ArrayList<String>();
for (int i = 0; i < mSerialPorts.length; i++) {
String path = mSerialPorts[i];
@@ -49,8 +49,8 @@
return result;
}
+ @EnforcePermission(android.Manifest.permission.SERIAL_PORT)
public ParcelFileDescriptor openSerialPort(String path) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SERIAL_PORT, null);
for (int i = 0; i < mSerialPorts.length; i++) {
if (mSerialPorts[i].equals(path)) {
return native_open(path);
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/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/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index ffc1aed..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/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index e1cbdb7..c05138f 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;
@@ -102,7 +100,6 @@
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 +128,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;
@@ -185,7 +181,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 +1008,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 +1217,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 +1236,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;
}
};
@@ -1474,7 +1467,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 +1511,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 +1748,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 +1980,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 +2088,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 +2287,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 +2317,7 @@
if (dataWarningConfig == WARNING_DISABLED) {
return WARNING_DISABLED;
} else {
- return dataWarningConfig * MB_IN_BYTES;
+ return DataUnit.MEBIBYTES.toBytes(dataWarningConfig);
}
}
@@ -2707,7 +2701,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");
@@ -3472,7 +3466,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 +3486,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 +3496,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 +3513,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 +3539,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 +3571,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 +3581,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 +3591,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 +3601,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 +3613,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 +5092,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 +5464,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);
}
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/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/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index c7bf8ec..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/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/Android.bp b/services/tests/servicestests/Android.bp
index f182b66..428327c 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -25,6 +25,7 @@
"test-apps/JobTestApp/src/**/*.java",
"test-apps/SuspendTestApp/src/**/*.java",
+ ":service-bluetooth-tests-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready
],
static_libs: [
"frameworks-base-testutils",
diff --git a/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java b/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
deleted file mode 100644
index a1d4c20..0000000
--- a/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import static org.mockito.Mockito.*;
-
-import android.bluetooth.BluetoothAdapter;
-import android.content.Context;
-import android.os.Looper;
-import android.provider.Settings;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class BluetoothAirplaneModeListenerTest {
- private Context mContext;
- private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
- private BluetoothAdapter mBluetoothAdapter;
- private BluetoothModeChangeHelper mHelper;
-
- @Mock BluetoothManagerService mBluetoothManagerService;
-
- @Before
- public void setUp() throws Exception {
- mContext = InstrumentationRegistry.getTargetContext();
-
- mHelper = mock(BluetoothModeChangeHelper.class);
- when(mHelper.getSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT))
- .thenReturn(BluetoothAirplaneModeListener.MAX_TOAST_COUNT);
- doNothing().when(mHelper).setSettingsInt(anyString(), anyInt());
- doNothing().when(mHelper).showToastMessage();
- doNothing().when(mHelper).onAirplaneModeChanged(any(BluetoothManagerService.class));
-
- mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
- mBluetoothManagerService, Looper.getMainLooper(), mContext);
- mBluetoothAirplaneModeListener.start(mHelper);
- }
-
- @Test
- public void testIgnoreOnAirplanModeChange() {
- Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
-
- when(mHelper.isBluetoothOn()).thenReturn(true);
- Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
-
- when(mHelper.isMediaProfileConnected()).thenReturn(true);
- Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
-
- when(mHelper.isAirplaneModeOn()).thenReturn(true);
- Assert.assertTrue(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
- }
-
- @Test
- public void testHandleAirplaneModeChange_InvokeAirplaneModeChanged() {
- mBluetoothAirplaneModeListener.handleAirplaneModeChange();
- verify(mHelper).onAirplaneModeChanged(mBluetoothManagerService);
- }
-
- @Test
- public void testHandleAirplaneModeChange_NotInvokeAirplaneModeChanged_NotPopToast() {
- mBluetoothAirplaneModeListener.mToastCount = BluetoothAirplaneModeListener.MAX_TOAST_COUNT;
- when(mHelper.isBluetoothOn()).thenReturn(true);
- when(mHelper.isMediaProfileConnected()).thenReturn(true);
- when(mHelper.isAirplaneModeOn()).thenReturn(true);
- mBluetoothAirplaneModeListener.handleAirplaneModeChange();
-
- verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON,
- BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
- verify(mHelper, times(0)).showToastMessage();
- verify(mHelper, times(0)).onAirplaneModeChanged(mBluetoothManagerService);
- }
-
- @Test
- public void testHandleAirplaneModeChange_NotInvokeAirplaneModeChanged_PopToast() {
- mBluetoothAirplaneModeListener.mToastCount = 0;
- when(mHelper.isBluetoothOn()).thenReturn(true);
- when(mHelper.isMediaProfileConnected()).thenReturn(true);
- when(mHelper.isAirplaneModeOn()).thenReturn(true);
- mBluetoothAirplaneModeListener.handleAirplaneModeChange();
-
- verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON,
- BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
- verify(mHelper).showToastMessage();
- verify(mHelper, times(0)).onAirplaneModeChanged(mBluetoothManagerService);
- }
-
- @Test
- public void testIsPopToast_PopToast() {
- mBluetoothAirplaneModeListener.mToastCount = 0;
- Assert.assertTrue(mBluetoothAirplaneModeListener.shouldPopToast());
- verify(mHelper).setSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT, 1);
- }
-
- @Test
- public void testIsPopToast_NotPopToast() {
- mBluetoothAirplaneModeListener.mToastCount = BluetoothAirplaneModeListener.MAX_TOAST_COUNT;
- Assert.assertFalse(mBluetoothAirplaneModeListener.shouldPopToast());
- verify(mHelper, times(0)).setSettingsInt(anyString(), anyInt());
- }
-}
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/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 9a6f61e..e80721a 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -51,6 +51,7 @@
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.MATCH_MOBILE;
import static android.net.NetworkTemplate.buildTemplateCarrierMetered;
import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.MB_IN_BYTES;
@@ -71,7 +72,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 +95,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;
@@ -495,8 +496,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;
@@ -1746,7 +1753,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();
@@ -2046,7 +2053,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 +2099,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/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/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 77c12bb..9a764a0 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2459,6 +2459,10 @@
*
* Note: If {@code *} is specified for the original code, any ImsReasonInfo with the matching
* {@code MESSAGE} will be remapped to {@code NEW_CODE}.
+ * If {@code *} is specified for the message, any ImsReasonInfo with the matching
+ * {@code ORIGINAL_CODE} will be remapped to {@code NEW_CODE}.
+ * The wildcard for {@code ORIGINAL_CODE} takes precedence to the wildcard for {@code MESSAGE}.
+ * A mapping with both wildcards has no effect.
*
* Example: "501|call completion elsewhere|1014"
* When the {@link ImsReasonInfo#getCode()} is {@link ImsReasonInfo#CODE_USER_TERMINATED} and
@@ -4879,6 +4883,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 {}
@@ -5025,6 +5033,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;
}
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..aab6daa 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -11487,7 +11487,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;
}
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/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 409c838..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/test-base/Android.bp b/test-base/Android.bp
index 97ebba6..8be7324 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -26,7 +26,19 @@
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
// SPDX-license-identifier-CPL-1.0
- default_applicable_licenses: ["frameworks_base_license"],
+ default_applicable_licenses: ["frameworks_base_test-base_license"],
+}
+
+license {
+ name: "frameworks_base_test-base_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-CPL-1.0",
+ ],
+ license_text: [
+ "src/junit/cpl-v10.html",
+ ],
}
java_sdk_library {
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
index 0f56bb3..2a19af9 100644
--- a/test-runner/Android.bp
+++ b/test-runner/Android.bp
@@ -18,12 +18,19 @@
// =====================================
package {
// See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-CPL-1.0
- default_applicable_licenses: ["frameworks_base_license"],
+ default_applicable_licenses: ["frameworks_base_test-runner_license"],
+}
+
+license {
+ name: "frameworks_base_test-runner_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-CPL-1.0",
+ ],
+ license_text: [
+ "src/junit/cpl-v10.html",
+ ],
}
java_sdk_library {
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/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 */);
}
}