Merge "Ims: Add support for Adhoc Conference calls"
diff --git a/Android.bp b/Android.bp
index 808879f..3046b20 100644
--- a/Android.bp
+++ b/Android.bp
@@ -53,6 +53,7 @@
"core/java/android/view/DisplayAdjustments.java",
],
path: "core/java",
+ visibility: ["//frameworks/base/test-mock"],
}
filegroup {
@@ -73,6 +74,14 @@
}
filegroup {
+ name: "framework-identity-sources",
+ srcs: [
+ "identity/java/**/*.java",
+ ],
+ path: "identity/java",
+}
+
+filegroup {
name: "framework-keystore-sources",
srcs: [
"keystore/java/**/*.java",
@@ -216,6 +225,7 @@
":framework-drm-sources",
":framework-graphics-sources",
":framework-keystore-sources",
+ ":framework-identity-sources",
":framework-location-sources",
":framework-lowpan-sources",
":framework-media-sources",
@@ -232,11 +242,13 @@
":framework-wifi-sources",
":PacProcessor-aidl-sources",
":ProxyHandler-aidl-sources",
+ ":net-utils-framework-common-srcs",
// AIDL from frameworks/base/native/
":platform-compat-native-aidl",
// AIDL sources from external directories
+ ":credstore_aidl",
":dumpstate_aidl",
":framework_native_aidl",
":gatekeeper_aidl",
@@ -265,9 +277,10 @@
filegroup {
name: "framework-updatable-sources",
srcs: [
- ":framework-sdkext-sources",
+ ":framework-sdkextensions-sources",
":framework-tethering-srcs",
":updatable-media-srcs",
+ ":ike-srcs",
]
}
@@ -287,6 +300,7 @@
"core/java",
"drm/java",
"graphics/java",
+ "identity/java",
"keystore/java",
"location/java",
"lowpan/java",
@@ -430,6 +444,7 @@
name: "framework-minus-apex",
defaults: ["framework-defaults"],
srcs: [":framework-non-updatable-sources"],
+ libs: ["ike-stubs"],
installable: true,
javac_shard_size: 150,
required: [
@@ -463,8 +478,10 @@
static_libs: [
"framework-minus-apex",
"updatable_media_stubs",
- "framework-sdkext-stubs-systemapi",
- // TODO(jiyong): add more stubs for APEXes here
+ "framework-sdkextensions-stubs-systemapi",
+ // TODO(b/147200698): should be the stub of framework-tethering
+ "framework-tethering",
+ "ike-stubs",
],
sdk_version: "core_platform",
apex_available: ["//apex_available:platform"],
@@ -587,6 +604,19 @@
}
filegroup {
+ name: "framework-ike-shared-srcs",
+ visibility: ["//frameworks/opt/net/ike"],
+ srcs: [
+ "core/java/android/annotation/StringDef.java",
+ "core/java/android/net/annotations/PolicyDirection.java",
+ "core/java/com/android/internal/util/IState.java",
+ "core/java/com/android/internal/util/State.java",
+ "core/java/com/android/internal/util/StateMachine.java",
+ "telephony/java/android/telephony/Annotation.java",
+ ],
+}
+
+filegroup {
name: "framework-networkstack-shared-srcs",
srcs: [
// TODO: remove these annotations as soon as we can use andoid.support.annotations.*
@@ -603,6 +633,7 @@
"core/java/com/android/internal/util/StateMachine.java",
"core/java/com/android/internal/util/TrafficStatsConstants.java",
"core/java/com/android/internal/util/WakeupMessage.java",
+ "core/java/com/android/internal/util/TokenBucket.java",
"core/java/android/net/shared/*.java",
],
}
@@ -612,13 +643,14 @@
name: "framework-tethering-shared-srcs",
srcs: [
"core/java/android/util/LocalLog.java",
- "core/java/com/android/internal/util/BitUtils.java",
"core/java/com/android/internal/util/IndentingPrintWriter.java",
"core/java/com/android/internal/util/IState.java",
"core/java/com/android/internal/util/MessageUtils.java",
"core/java/com/android/internal/util/Preconditions.java",
"core/java/com/android/internal/util/State.java",
"core/java/com/android/internal/util/StateMachine.java",
+ "core/java/com/android/internal/util/TrafficStatsConstants.java",
+ "core/java/android/net/shared/Inet4AddressUtils.java",
],
}
@@ -905,6 +937,7 @@
"core/java/android/os/RemoteException.java",
"core/java/android/util/AndroidException.java",
],
+ libs: [ "unsupportedappusage" ],
dxflags: ["--core-library"],
installable: false,
@@ -1005,6 +1038,7 @@
"core/java/android/util/TimeUtils.java",
"core/java/com/android/internal/os/SomeArgs.java",
"core/java/com/android/internal/util/AsyncChannel.java",
+ "core/java/com/android/internal/util/AsyncService.java",
"core/java/com/android/internal/util/BitwiseInputStream.java",
"core/java/com/android/internal/util/FastXmlSerializer.java",
"core/java/com/android/internal/util/HexDump.java",
diff --git a/ApiDocs.bp b/ApiDocs.bp
index e373db6..c40004c 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -121,8 +121,10 @@
doc_defaults {
name: "framework-docs-default",
- libs: framework_docs_only_libs +
- ["stub-annotations"],
+ libs: framework_docs_only_libs + [
+ "stub-annotations",
+ "unsupportedappusage",
+ ],
html_dirs: [
"docs/html",
],
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 78f1b9c..baa3c61 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -41,10 +41,9 @@
]
stubs_defaults {
- name: "metalava-api-stubs-default",
+ name: "metalava-non-updatable-api-stubs-default",
srcs: [
":framework-non-updatable-sources",
- ":framework-updatable-sources",
"core/java/**/*.logtags",
":opt-telephony-srcs",
":opt-net-voip-srcs",
@@ -64,14 +63,23 @@
"sdk-dir",
"api-versions-jars-dir",
],
- sdk_version: "core_platform",
filter_packages: packages_to_document,
}
+stubs_defaults {
+ name: "metalava-api-stubs-default",
+ defaults: ["metalava-non-updatable-api-stubs-default"],
+ srcs: [":framework-updatable-sources"],
+ sdk_version: "core_platform",
+}
+
/////////////////////////////////////////////////////////////////////
// *-api-stubs-docs modules providing source files for the stub libraries
/////////////////////////////////////////////////////////////////////
+// api-stubs-docs, system-api-stubs-docs, and test-api-stubs-docs have APIs
+// from the non-updatable part of the platform as well as from the updatable
+// modules
droidstubs {
name: "api-stubs-docs",
defaults: ["metalava-api-stubs-default"],
@@ -112,7 +120,10 @@
arg_files: [
"core/res/AndroidManifest.xml",
],
- args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
+ args: metalava_framework_docs_args +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\)",
check_api: {
current: {
api_file: "api/system-current.txt",
@@ -155,6 +166,111 @@
}
/////////////////////////////////////////////////////////////////////
+// Following droidstubs modules are for extra APIs for modules.
+// The framework currently have two more API surfaces for modules:
+// @SystemApi(client=MODULE_APPS) and @SystemApi(client=MODULE_LIBRARIES)
+/////////////////////////////////////////////////////////////////////
+
+// TODO(b/146727827) remove the *-api modules when we can teach metalava
+// about the relationship among the API surfaces. Currently, these modules are only to generate
+// the API signature files and ensure that the APIs evolve in a backwards compatible manner.
+// They however are NOT used for building the API stub.
+droidstubs {
+ name: "module-app-api",
+ defaults: ["metalava-non-updatable-api-stubs-default"],
+ libs: ["framework-all"],
+ arg_files: ["core/res/AndroidManifest.xml"],
+ args: metalava_framework_docs_args +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.MODULE_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\)",
+ check_api: {
+ current: {
+ api_file: "api/module-app-current.txt",
+ removed_api_file: "api/module-app-removed.txt",
+ },
+ // TODO(b/147559833) enable the compatibility check against the last release API
+ // and the API lint
+ //last_released: {
+ // api_file: ":last-released-module-app-api",
+ // removed_api_file: "api/module-app-removed.txt",
+ // baseline_file: ":module-app-api-incompatibilities-with-last-released"
+ //},
+ //api_lint: {
+ // enabled: true,
+ // new_since: ":last-released-module-app-api",
+ // baseline_file: "api/module-app-lint-baseline.txt",
+ //},
+ },
+ //jdiff_enabled: true,
+}
+
+droidstubs {
+ name: "module-lib-api",
+ defaults: ["metalava-non-updatable-api-stubs-default"],
+ libs: ["framework-all"],
+ arg_files: ["core/res/AndroidManifest.xml"],
+ args: metalava_framework_docs_args +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.MODULE_LIBRARIES," +
+ "process=android.annotation.SystemApi.Process.ALL\\)",
+ check_api: {
+ current: {
+ api_file: "api/module-lib-current.txt",
+ removed_api_file: "api/module-lib-removed.txt",
+ },
+ // TODO(b/147559833) enable the compatibility check against the last release API
+ // and the API lint
+ //last_released: {
+ // api_file: ":last-released-module-lib-api",
+ // removed_api_file: "api/module-lib-removed.txt",
+ // baseline_file: ":module-lib-api-incompatibilities-with-last-released"
+ //},
+ //api_lint: {
+ // enabled: true,
+ // new_since: ":last-released-module-lib-api",
+ // baseline_file: "api/module-lib-lint-baseline.txt",
+ //},
+ },
+ //jdiff_enabled: true,
+}
+
+// The following two droidstubs modules generate source files for the API stub libraries for
+// modules. Note that they not only include their own APIs but also other APIs that have
+// narrower scope. For example, module-lib-api-stubs-docs includes all @SystemApis not just
+// the ones with 'client=MODULE_LIBRARIES'.
+droidstubs {
+ name: "module-app-api-stubs-docs",
+ defaults: ["metalava-non-updatable-api-stubs-default"],
+ libs: ["framework-all"],
+ arg_files: ["core/res/AndroidManifest.xml"],
+ args: metalava_framework_docs_args +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\)" +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.MODULE_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\)",
+}
+
+droidstubs {
+ name: "module-lib-api-stubs-docs",
+ defaults: ["metalava-non-updatable-api-stubs-default"],
+ libs: ["framework-all"],
+ arg_files: ["core/res/AndroidManifest.xml"],
+ args: metalava_framework_docs_args +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\)" +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.MODULE_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\)" +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.MODULE_LIBRARIES," +
+ "process=android.annotation.SystemApi.Process.ALL\\)",
+}
+
+/////////////////////////////////////////////////////////////////////
// android_*_stubs_current modules are the stubs libraries compiled
// from *-api-stubs-docs
/////////////////////////////////////////////////////////////////////
@@ -169,7 +285,6 @@
java_resources: [
":notices-for-framework-stubs",
],
- sdk_version: "core_current",
system_modules: "none",
java_version: "1.8",
compile_dex: true,
@@ -187,6 +302,7 @@
"private-stub-annotations-jar",
],
defaults: ["framework-stubs-default"],
+ sdk_version: "core_current",
}
java_library_static {
@@ -201,6 +317,7 @@
"private-stub-annotations-jar",
],
defaults: ["framework-stubs-default"],
+ sdk_version: "core_current",
}
java_library_static {
@@ -215,21 +332,37 @@
"private-stub-annotations-jar",
],
defaults: ["framework-stubs-default"],
+ sdk_version: "core_current",
}
-java_system_modules {
- name: "android_stubs_current_system_modules",
- libs: ["android_stubs_current"],
+java_library_static {
+ name: "framework_module_app_stubs_current",
+ srcs: [
+ ":module-app-api-stubs-docs",
+ ],
+ libs: [
+ "stub-annotations",
+ "framework-all",
+ ],
+ static_libs: [
+ "private-stub-annotations-jar",
+ ],
+ defaults: ["framework-stubs-default"],
}
-java_system_modules {
- name: "android_system_stubs_current_system_modules",
- libs: ["android_system_stubs_current"],
-}
-
-java_system_modules {
- name: "android_test_stubs_current_system_modules",
- libs: ["android_test_stubs_current"],
+java_library_static {
+ name: "framework_module_lib_stubs_current",
+ srcs: [
+ ":module-lib-api-stubs-docs",
+ ],
+ libs: [
+ "stub-annotations",
+ "framework-all",
+ ],
+ static_libs: [
+ "private-stub-annotations-jar",
+ ],
+ defaults: ["framework-stubs-default"],
}
/////////////////////////////////////////////////////////////////////
diff --git a/apex/Android.bp b/apex/Android.bp
index 9ea3953..c3b0014 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -34,6 +34,36 @@
stubs_defaults {
name: "framework-module-stubs-defaults-systemapi",
- args: mainline_stubs_args + " --show-annotation android.annotation.SystemApi ",
+ args: mainline_stubs_args +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\) ",
+ installable: false,
+}
+
+stubs_defaults {
+ name: "framework-module-stubs-defaults-module_apps_api",
+ args: mainline_stubs_args +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\) " +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.MODULE_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\) ",
+ installable: false,
+}
+
+stubs_defaults {
+ name: "framework-module-stubs-defaults-module_libs_api",
+ args: mainline_stubs_args +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\) " +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.MODULE_APPS," +
+ "process=android.annotation.SystemApi.Process.ALL\\) " +
+ " --show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.MODULE_LIBRARIES," +
+ "process=android.annotation.SystemApi.Process.ALL\\) ",
installable: false,
}
diff --git a/apex/sdkext/TEST_MAPPING b/apex/sdkext/TEST_MAPPING
deleted file mode 100644
index 91947f3..0000000
--- a/apex/sdkext/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "presubmit": [
- {
- "name": "CtsSdkExtTestCases"
- }
- ]
-}
diff --git a/apex/sdkext/framework/Android.bp b/apex/sdkext/framework/Android.bp
deleted file mode 100644
index a50dc3d..0000000
--- a/apex/sdkext/framework/Android.bp
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_visibility: [ ":__pkg__" ]
-}
-
-filegroup {
- name: "framework-sdkext-sources",
- srcs: [
- "java/**/*.java",
- ],
- path: "java",
- visibility: [ "//frameworks/base:__pkg__" ] // For the "global" stubs.
-}
-
-java_library {
- name: "framework-sdkext",
- srcs: [ ":framework-sdkext-sources" ],
- sdk_version: "system_current",
- libs: [ "framework-annotations-lib" ],
- permitted_packages: [ "android.os.ext" ],
- installable: true,
- visibility: [ "//frameworks/base/apex/sdkext:__pkg__" ],
-}
-
-droidstubs {
- name: "framework-sdkext-droidstubs-publicapi",
- defaults: [
- "framework-sdkext-stubs-defaults",
- "framework-module-stubs-defaults-publicapi",
- ]
-}
-
-droidstubs {
- name: "framework-sdkext-droidstubs-systemapi",
- defaults: [
- "framework-sdkext-stubs-defaults",
- "framework-module-stubs-defaults-systemapi",
- ]
-}
-
-stubs_defaults {
- name: "framework-sdkext-stubs-defaults",
- srcs: [
- ":framework-sdkext-sources",
- ":framework-annotations",
- ],
- sdk_version: "system_current",
-}
-
-java_library {
- name: "framework-sdkext-stubs-systemapi",
- srcs: [":framework-sdkext-droidstubs-systemapi"],
- sdk_version: "system_current",
- visibility: [
- "//frameworks/base:__pkg__", // Framework
- "//frameworks/base/apex/sdkext:__pkg__", // sdkext SDK
- ]
-}
diff --git a/apex/sdkext/Android.bp b/apex/sdkextensions/Android.bp
similarity index 83%
rename from apex/sdkext/Android.bp
rename to apex/sdkextensions/Android.bp
index f62f167..4c5c2b2 100644
--- a/apex/sdkext/Android.bp
+++ b/apex/sdkextensions/Android.bp
@@ -18,21 +18,26 @@
apex {
name: "com.android.sdkext",
- manifest: "manifest.json",
+ defaults: [ "com.android.sdkext-defaults" ],
binaries: [ "derive_sdk" ],
- java_libs: [ "framework-sdkext" ],
+ prebuilts: [ "cur_sdkinfo" ],
+ manifest: "manifest.json",
+}
+
+apex_defaults {
+ name: "com.android.sdkext-defaults",
+ java_libs: [ "framework-sdkextensions" ],
prebuilts: [
- "com.android.sdkext.ldconfig",
- "cur_sdkinfo",
- "derive_sdk.rc",
+ "com.android.sdkext.ldconfig",
+ "derive_sdk.rc",
],
key: "com.android.sdkext.key",
certificate: ":com.android.sdkext.certificate",
}
sdk {
- name: "sdkext-sdk",
- java_header_libs: [ "framework-sdkext-stubs-systemapi" ],
+ name: "sdkextensions-sdk",
+ java_header_libs: [ "framework-sdkextensions-stubs-systemapi" ],
}
apex_key {
diff --git a/apex/sdkext/OWNERS b/apex/sdkextensions/OWNERS
similarity index 100%
rename from apex/sdkext/OWNERS
rename to apex/sdkextensions/OWNERS
diff --git a/apex/sdkextensions/TEST_MAPPING b/apex/sdkextensions/TEST_MAPPING
new file mode 100644
index 0000000..4e18833
--- /dev/null
+++ b/apex/sdkextensions/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsSdkExtensionsTestCases"
+ },
+ {
+ "name": "apiextensions_e2e_tests"
+ }
+ ]
+}
diff --git a/apex/sdkext/com.android.sdkext.avbpubkey b/apex/sdkextensions/com.android.sdkext.avbpubkey
similarity index 100%
rename from apex/sdkext/com.android.sdkext.avbpubkey
rename to apex/sdkextensions/com.android.sdkext.avbpubkey
Binary files differ
diff --git a/apex/sdkext/com.android.sdkext.pem b/apex/sdkextensions/com.android.sdkext.pem
similarity index 100%
rename from apex/sdkext/com.android.sdkext.pem
rename to apex/sdkextensions/com.android.sdkext.pem
diff --git a/apex/sdkext/com.android.sdkext.pk8 b/apex/sdkextensions/com.android.sdkext.pk8
similarity index 100%
rename from apex/sdkext/com.android.sdkext.pk8
rename to apex/sdkextensions/com.android.sdkext.pk8
Binary files differ
diff --git a/apex/sdkext/com.android.sdkext.x509.pem b/apex/sdkextensions/com.android.sdkext.x509.pem
similarity index 100%
rename from apex/sdkext/com.android.sdkext.x509.pem
rename to apex/sdkextensions/com.android.sdkext.x509.pem
diff --git a/apex/sdkext/derive_sdk/Android.bp b/apex/sdkextensions/derive_sdk/Android.bp
similarity index 63%
rename from apex/sdkext/derive_sdk/Android.bp
rename to apex/sdkextensions/derive_sdk/Android.bp
index c4e3c29..cf49902 100644
--- a/apex/sdkext/derive_sdk/Android.bp
+++ b/apex/sdkextensions/derive_sdk/Android.bp
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_binary {
- name: "derive_sdk",
+cc_defaults {
+ name: "derive_sdk-defaults",
srcs: [
"derive_sdk.cpp",
"sdk.proto",
@@ -30,6 +30,24 @@
],
}
+cc_binary {
+ name: "derive_sdk",
+ defaults: [ "derive_sdk-defaults" ],
+ apex_available: [ "com.android.sdkext" ],
+ visibility: [ "//frameworks/base/apex/sdkextensions" ]
+}
+
+// Work around testing using a 64-bit test suite on 32-bit test device by
+// using a prefer32 version of derive_sdk in testing.
+cc_binary {
+ name: "derive_sdk_prefer32",
+ defaults: [ "derive_sdk-defaults" ],
+ compile_multilib: "prefer32",
+ stem: "derive_sdk",
+ apex_available: [ "test_com.android.sdkext" ],
+ visibility: [ "//frameworks/base/apex/sdkextensions/testing" ]
+}
+
prebuilt_etc {
name: "derive_sdk.rc",
src: "derive_sdk.rc",
diff --git a/apex/sdkext/derive_sdk/derive_sdk.cpp b/apex/sdkextensions/derive_sdk/derive_sdk.cpp
similarity index 97%
rename from apex/sdkext/derive_sdk/derive_sdk.cpp
rename to apex/sdkextensions/derive_sdk/derive_sdk.cpp
index 0a97116..6fb7ef4 100644
--- a/apex/sdkext/derive_sdk/derive_sdk.cpp
+++ b/apex/sdkextensions/derive_sdk/derive_sdk.cpp
@@ -26,7 +26,7 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
-#include "frameworks/base/apex/sdkext/derive_sdk/sdk.pb.h"
+#include "frameworks/base/apex/sdkextensions/derive_sdk/sdk.pb.h"
using com::android::sdkext::proto::SdkVersion;
diff --git a/apex/sdkext/derive_sdk/derive_sdk.rc b/apex/sdkextensions/derive_sdk/derive_sdk.rc
similarity index 100%
rename from apex/sdkext/derive_sdk/derive_sdk.rc
rename to apex/sdkextensions/derive_sdk/derive_sdk.rc
diff --git a/apex/sdkext/derive_sdk/sdk.proto b/apex/sdkextensions/derive_sdk/sdk.proto
similarity index 100%
rename from apex/sdkext/derive_sdk/sdk.proto
rename to apex/sdkextensions/derive_sdk/sdk.proto
diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp
new file mode 100644
index 0000000..dd17473
--- /dev/null
+++ b/apex/sdkextensions/framework/Android.bp
@@ -0,0 +1,79 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_visibility: [ ":__pkg__" ]
+}
+
+filegroup {
+ name: "framework-sdkextensions-sources",
+ srcs: [
+ "java/**/*.java",
+ ],
+ path: "java",
+ visibility: [ "//frameworks/base" ] // For the "global" stubs.
+}
+
+java_library {
+ name: "framework-sdkextensions",
+ srcs: [ ":framework-sdkextensions-sources" ],
+ sdk_version: "system_current",
+ libs: [ "framework-annotations-lib" ],
+ permitted_packages: [ "android.os.ext" ],
+ installable: true,
+ visibility: [
+ "//frameworks/base/apex/sdkextensions",
+ "//frameworks/base/apex/sdkextensions/testing",
+ ],
+ hostdex: true, // for hiddenapi check
+ apex_available: [
+ "com.android.sdkext",
+ "test_com.android.sdkext",
+ ],
+}
+
+droidstubs {
+ name: "framework-sdkextensions-droidstubs-publicapi",
+ defaults: [
+ "framework-sdkextensions-stubs-defaults",
+ "framework-module-stubs-defaults-publicapi",
+ ]
+}
+
+droidstubs {
+ name: "framework-sdkextensions-droidstubs-systemapi",
+ defaults: [
+ "framework-sdkextensions-stubs-defaults",
+ "framework-module-stubs-defaults-systemapi",
+ ]
+}
+
+stubs_defaults {
+ name: "framework-sdkextensions-stubs-defaults",
+ srcs: [
+ ":framework-sdkextensions-sources",
+ ":framework-annotations",
+ ],
+ sdk_version: "system_current",
+}
+
+java_library {
+ name: "framework-sdkextensions-stubs-systemapi",
+ srcs: [":framework-sdkextensions-droidstubs-systemapi"],
+ sdk_version: "system_current",
+ visibility: [
+ "//frameworks/base", // Framework
+ "//frameworks/base/apex/sdkextensions", // sdkextensions SDK
+ ]
+}
diff --git a/apex/sdkext/framework/java/android/os/ext/SdkExtensions.java b/apex/sdkextensions/framework/java/android/os/ext/SdkExtensions.java
similarity index 100%
rename from apex/sdkext/framework/java/android/os/ext/SdkExtensions.java
rename to apex/sdkextensions/framework/java/android/os/ext/SdkExtensions.java
diff --git a/apex/sdkext/framework/java/android/os/ext/package.html b/apex/sdkextensions/framework/java/android/os/ext/package.html
similarity index 100%
rename from apex/sdkext/framework/java/android/os/ext/package.html
rename to apex/sdkextensions/framework/java/android/os/ext/package.html
diff --git a/apex/sdkext/gen_sdkinfo.py b/apex/sdkextensions/gen_sdkinfo.py
similarity index 100%
rename from apex/sdkext/gen_sdkinfo.py
rename to apex/sdkextensions/gen_sdkinfo.py
diff --git a/apex/sdkext/ld.config.txt b/apex/sdkextensions/ld.config.txt
similarity index 91%
rename from apex/sdkext/ld.config.txt
rename to apex/sdkextensions/ld.config.txt
index b447068..dcc69b8 100644
--- a/apex/sdkext/ld.config.txt
+++ b/apex/sdkextensions/ld.config.txt
@@ -1,10 +1,10 @@
# Copyright (C) 2019 The Android Open Source Project
#
-# Bionic loader config file for the sdkext apex.
+# Bionic loader config file for the sdkextensions apex.
-dir.sdkext = /apex/com.android.sdkext/bin/
+dir.sdkextensions = /apex/com.android.sdkext/bin/
-[sdkext]
+[sdkextensions]
additional.namespaces = platform
namespace.default.isolated = true
diff --git a/apex/sdkext/manifest.json b/apex/sdkextensions/manifest.json
similarity index 100%
rename from apex/sdkext/manifest.json
rename to apex/sdkextensions/manifest.json
diff --git a/apex/sdkext/sdk.proto b/apex/sdkextensions/sdk.proto
similarity index 100%
rename from apex/sdkext/sdk.proto
rename to apex/sdkextensions/sdk.proto
diff --git a/apex/sdkextensions/testing/Android.bp b/apex/sdkextensions/testing/Android.bp
new file mode 100644
index 0000000..e6451cc
--- /dev/null
+++ b/apex/sdkextensions/testing/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+apex {
+ name: "test_com.android.sdkext",
+ visibility: [ "//system/apex/tests" ],
+ defaults: ["com.android.sdkext-defaults"],
+ manifest: "test_manifest.json",
+ prebuilts: [ "sdkinfo_45" ],
+ file_contexts: ":com.android.sdkext-file_contexts",
+ installable: false, // Should never be installed on the systemimage
+ multilib: {
+ prefer32: {
+ binaries: ["derive_sdk_prefer32"],
+ },
+ },
+ // The automated test infra ends up building this apex for 64+32-bit and
+ // then installs it on a 32-bit-only device. Work around this weirdness
+ // by preferring 32-bit.
+ compile_multilib: "prefer32",
+}
+
+genrule {
+ name: "sdkinfo_45_src",
+ out: [ "sdkinfo.binarypb" ],
+ tools: [ "gen_sdkinfo" ],
+ cmd: "$(location) -v 45 -o $(out)",
+}
+
+prebuilt_etc {
+ name: "sdkinfo_45",
+ src: ":sdkinfo_45_src",
+ filename: "sdkinfo.binarypb",
+ installable: false,
+}
diff --git a/apex/sdkextensions/testing/test_manifest.json b/apex/sdkextensions/testing/test_manifest.json
new file mode 100644
index 0000000..1b4a2b0
--- /dev/null
+++ b/apex/sdkextensions/testing/test_manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.sdkext",
+ "version": 2147483647
+}
diff --git a/api/current.txt b/api/current.txt
index 7ae64b4..bba6586 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -112,6 +112,7 @@
field public static final String READ_LOGS = "android.permission.READ_LOGS";
field public static final String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
field public static final String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
+ field public static final String READ_PRECISE_PHONE_STATE = "android.permission.READ_PRECISE_PHONE_STATE";
field public static final String READ_SMS = "android.permission.READ_SMS";
field public static final String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
field public static final String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
@@ -16636,7 +16637,9 @@
ctor public BiometricPrompt.CryptoObject(@NonNull java.security.Signature);
ctor public BiometricPrompt.CryptoObject(@NonNull javax.crypto.Cipher);
ctor public BiometricPrompt.CryptoObject(@NonNull javax.crypto.Mac);
+ ctor public BiometricPrompt.CryptoObject(@NonNull android.security.identity.IdentityCredential);
method public javax.crypto.Cipher getCipher();
+ method @Nullable public android.security.identity.IdentityCredential getIdentityCredential();
method public javax.crypto.Mac getMac();
method public java.security.Signature getSignature();
}
@@ -17574,7 +17577,9 @@
ctor @Deprecated public FingerprintManager.CryptoObject(@NonNull java.security.Signature);
ctor @Deprecated public FingerprintManager.CryptoObject(@NonNull javax.crypto.Cipher);
ctor @Deprecated public FingerprintManager.CryptoObject(@NonNull javax.crypto.Mac);
+ ctor @Deprecated public FingerprintManager.CryptoObject(@NonNull android.security.identity.IdentityCredential);
method @Deprecated public javax.crypto.Cipher getCipher();
+ method @Deprecated @Nullable public android.security.identity.IdentityCredential getIdentityCredential();
method @Deprecated public javax.crypto.Mac getMac();
method @Deprecated public java.security.Signature getSignature();
}
@@ -17963,6 +17968,7 @@
field public static final int RIGHT = 7; // 0x7
field public static final int TOP = 8; // 0x8
field public static final int TOP_AND_BOTTOM = 9; // 0x9
+ field public static final int TOP_AND_BOTTOM_AND_LEFT = 15; // 0xf
field public static final int TOP_AND_BOTTOM_AND_RIGHT = 10; // 0xa
field public static final int TOP_AND_LEFT = 11; // 0xb
field public static final int TOP_AND_LEFT_AND_RIGHT = 12; // 0xc
@@ -18285,6 +18291,8 @@
field public static final int CHEROKEE_SUPPLEMENT_ID = 255; // 0xff
field public static final android.icu.lang.UCharacter.UnicodeBlock CHESS_SYMBOLS;
field public static final int CHESS_SYMBOLS_ID = 281; // 0x119
+ field public static final android.icu.lang.UCharacter.UnicodeBlock CHORASMIAN;
+ field public static final int CHORASMIAN_ID = 301; // 0x12d
field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY;
field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY_FORMS;
field public static final int CJK_COMPATIBILITY_FORMS_ID = 83; // 0x53
@@ -18312,6 +18320,8 @@
field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E_ID = 256; // 0x100
field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F;
field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F_ID = 274; // 0x112
+ field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G;
+ field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G_ID = 302; // 0x12e
field public static final int CJK_UNIFIED_IDEOGRAPHS_ID = 71; // 0x47
field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_DIACRITICAL_MARKS;
field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_DIACRITICAL_MARKS_EXTENDED;
@@ -18361,6 +18371,8 @@
field public static final int DEVANAGARI_ID = 15; // 0xf
field public static final android.icu.lang.UCharacter.UnicodeBlock DINGBATS;
field public static final int DINGBATS_ID = 56; // 0x38
+ field public static final android.icu.lang.UCharacter.UnicodeBlock DIVES_AKURU;
+ field public static final int DIVES_AKURU_ID = 303; // 0x12f
field public static final android.icu.lang.UCharacter.UnicodeBlock DOGRA;
field public static final int DOGRA_ID = 282; // 0x11a
field public static final android.icu.lang.UCharacter.UnicodeBlock DOMINO_TILES;
@@ -18489,6 +18501,8 @@
field public static final int KAYAH_LI_ID = 162; // 0xa2
field public static final android.icu.lang.UCharacter.UnicodeBlock KHAROSHTHI;
field public static final int KHAROSHTHI_ID = 137; // 0x89
+ field public static final android.icu.lang.UCharacter.UnicodeBlock KHITAN_SMALL_SCRIPT;
+ field public static final int KHITAN_SMALL_SCRIPT_ID = 304; // 0x130
field public static final android.icu.lang.UCharacter.UnicodeBlock KHMER;
field public static final int KHMER_ID = 36; // 0x24
field public static final android.icu.lang.UCharacter.UnicodeBlock KHMER_SYMBOLS;
@@ -18527,6 +18541,8 @@
field public static final int LINEAR_B_SYLLABARY_ID = 117; // 0x75
field public static final android.icu.lang.UCharacter.UnicodeBlock LISU;
field public static final int LISU_ID = 176; // 0xb0
+ field public static final android.icu.lang.UCharacter.UnicodeBlock LISU_SUPPLEMENT;
+ field public static final int LISU_SUPPLEMENT_ID = 305; // 0x131
field public static final android.icu.lang.UCharacter.UnicodeBlock LOW_SURROGATES;
field public static final int LOW_SURROGATES_ID = 77; // 0x4d
field public static final android.icu.lang.UCharacter.UnicodeBlock LYCIAN;
@@ -18738,6 +18754,8 @@
field public static final int SYLOTI_NAGRI_ID = 143; // 0x8f
field public static final android.icu.lang.UCharacter.UnicodeBlock SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A;
field public static final int SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A_ID = 298; // 0x12a
+ field public static final android.icu.lang.UCharacter.UnicodeBlock SYMBOLS_FOR_LEGACY_COMPUTING;
+ field public static final int SYMBOLS_FOR_LEGACY_COMPUTING_ID = 306; // 0x132
field public static final android.icu.lang.UCharacter.UnicodeBlock SYRIAC;
field public static final int SYRIAC_ID = 13; // 0xd
field public static final android.icu.lang.UCharacter.UnicodeBlock SYRIAC_SUPPLEMENT;
@@ -18766,6 +18784,8 @@
field public static final android.icu.lang.UCharacter.UnicodeBlock TANGUT_COMPONENTS;
field public static final int TANGUT_COMPONENTS_ID = 273; // 0x111
field public static final int TANGUT_ID = 272; // 0x110
+ field public static final android.icu.lang.UCharacter.UnicodeBlock TANGUT_SUPPLEMENT;
+ field public static final int TANGUT_SUPPLEMENT_ID = 307; // 0x133
field public static final android.icu.lang.UCharacter.UnicodeBlock TELUGU;
field public static final int TELUGU_ID = 21; // 0x15
field public static final android.icu.lang.UCharacter.UnicodeBlock THAANA;
@@ -18800,6 +18820,8 @@
field public static final int WANCHO_ID = 300; // 0x12c
field public static final android.icu.lang.UCharacter.UnicodeBlock WARANG_CITI;
field public static final int WARANG_CITI_ID = 252; // 0xfc
+ field public static final android.icu.lang.UCharacter.UnicodeBlock YEZIDI;
+ field public static final int YEZIDI_ID = 308; // 0x134
field public static final android.icu.lang.UCharacter.UnicodeBlock YIJING_HEXAGRAM_SYMBOLS;
field public static final int YIJING_HEXAGRAM_SYMBOLS_ID = 116; // 0x74
field public static final android.icu.lang.UCharacter.UnicodeBlock YI_RADICALS;
@@ -19096,6 +19118,7 @@
field public static final int CHAKMA = 118; // 0x76
field public static final int CHAM = 66; // 0x42
field public static final int CHEROKEE = 6; // 0x6
+ field public static final int CHORASMIAN = 189; // 0xbd
field public static final int CIRTH = 67; // 0x43
field public static final int COMMON = 0; // 0x0
field public static final int COPTIC = 7; // 0x7
@@ -19105,6 +19128,7 @@
field public static final int DEMOTIC_EGYPTIAN = 69; // 0x45
field public static final int DESERET = 9; // 0x9
field public static final int DEVANAGARI = 10; // 0xa
+ field public static final int DIVES_AKURU = 190; // 0xbe
field public static final int DOGRA = 178; // 0xb2
field public static final int DUPLOYAN = 135; // 0x87
field public static final int EASTERN_SYRIAC = 97; // 0x61
@@ -19146,6 +19170,7 @@
field public static final int KATAKANA_OR_HIRAGANA = 54; // 0x36
field public static final int KAYAH_LI = 79; // 0x4f
field public static final int KHAROSHTHI = 57; // 0x39
+ field public static final int KHITAN_SMALL_SCRIPT = 191; // 0xbf
field public static final int KHMER = 23; // 0x17
field public static final int KHOJKI = 157; // 0x9d
field public static final int KHUDAWADI = 145; // 0x91
@@ -19263,6 +19288,7 @@
field public static final int WARANG_CITI = 146; // 0x92
field public static final int WESTERN_SYRIAC = 96; // 0x60
field public static final int WOLEAI = 155; // 0x9b
+ field public static final int YEZIDI = 192; // 0xc0
field public static final int YI = 41; // 0x29
field public static final int ZANABAZAR_SQUARE = 177; // 0xb1
}
@@ -22518,6 +22544,7 @@
field public static final android.icu.util.VersionInfo UNICODE_11_0;
field public static final android.icu.util.VersionInfo UNICODE_12_0;
field public static final android.icu.util.VersionInfo UNICODE_12_1;
+ field public static final android.icu.util.VersionInfo UNICODE_13_0;
field public static final android.icu.util.VersionInfo UNICODE_1_0;
field public static final android.icu.util.VersionInfo UNICODE_1_0_1;
field public static final android.icu.util.VersionInfo UNICODE_1_1_0;
@@ -28327,7 +28354,10 @@
method public int getVideoHeight();
method public float getVideoPixelAspectRatio();
method public int getVideoWidth();
+ method public boolean isAudioDescription();
method public boolean isEncrypted();
+ method public boolean isHardOfHearing();
+ method public boolean isSpokenSubtitle();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.TvTrackInfo> CREATOR;
field public static final int TYPE_AUDIO = 0; // 0x0
@@ -28339,11 +28369,14 @@
ctor public TvTrackInfo.Builder(int, @NonNull String);
method public android.media.tv.TvTrackInfo build();
method public android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int);
+ method @NonNull public android.media.tv.TvTrackInfo.Builder setAudioDescription(boolean);
method public android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
method public android.media.tv.TvTrackInfo.Builder setDescription(CharSequence);
method @NonNull public android.media.tv.TvTrackInfo.Builder setEncrypted(boolean);
method public android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
+ method @NonNull public android.media.tv.TvTrackInfo.Builder setHardOfHearing(boolean);
method public android.media.tv.TvTrackInfo.Builder setLanguage(String);
+ method @NonNull public android.media.tv.TvTrackInfo.Builder setSpokenSubtitle(boolean);
method public android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte);
method public android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
method public android.media.tv.TvTrackInfo.Builder setVideoHeight(int);
@@ -28655,6 +28688,37 @@
field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortal> CREATOR;
}
+ public class ConnectivityDiagnosticsManager {
+ method public void registerConnectivityDiagnosticsCallback(@NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
+ method public void unregisterConnectivityDiagnosticsCallback(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
+ field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1
+ field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2
+ }
+
+ public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback {
+ ctor public ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback();
+ method public void onConnectivityReport(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport);
+ method public void onDataStallSuspected(@NonNull android.net.ConnectivityDiagnosticsManager.DataStallReport);
+ method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean);
+ }
+
+ public static class ConnectivityDiagnosticsManager.ConnectivityReport {
+ ctor public ConnectivityDiagnosticsManager.ConnectivityReport(@NonNull android.net.Network, long, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle);
+ field @NonNull public final android.os.PersistableBundle additionalInfo;
+ field @NonNull public final android.net.LinkProperties linkProperties;
+ field @NonNull public final android.net.Network network;
+ field @NonNull public final android.net.NetworkCapabilities networkCapabilities;
+ field public final long reportTimestamp;
+ }
+
+ public static class ConnectivityDiagnosticsManager.DataStallReport {
+ ctor public ConnectivityDiagnosticsManager.DataStallReport(@NonNull android.net.Network, long, int, @NonNull android.os.PersistableBundle);
+ field public final int detectionMethod;
+ field @NonNull public final android.net.Network network;
+ field public final long reportTimestamp;
+ field @NonNull public final android.os.PersistableBundle stallDetails;
+ }
+
public class ConnectivityManager {
method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public boolean bindProcessToNetwork(@Nullable android.net.Network);
@@ -28759,6 +28823,7 @@
ctor public DhcpInfo();
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.DhcpInfo> CREATOR;
field public int dns1;
field public int dns2;
field public int gateway;
@@ -28888,6 +28953,7 @@
method public boolean addRoute(@NonNull android.net.RouteInfo);
method public void clear();
method public int describeContents();
+ method @Nullable public java.net.Inet4Address getDhcpServerAddress();
method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
method @Nullable public String getDomains();
method @Nullable public android.net.ProxyInfo getHttpProxy();
@@ -28899,6 +28965,7 @@
method @NonNull public java.util.List<android.net.RouteInfo> getRoutes();
method public boolean isPrivateDnsActive();
method public boolean isWakeOnLanSupported();
+ method public void setDhcpServerAddress(@Nullable java.net.Inet4Address);
method public void setDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
method public void setDomains(@Nullable String);
method public void setHttpProxy(@Nullable android.net.ProxyInfo);
@@ -29123,9 +29190,10 @@
method public android.net.NetworkRequest.Builder addCapability(int);
method public android.net.NetworkRequest.Builder addTransportType(int);
method public android.net.NetworkRequest build();
+ method @NonNull public android.net.NetworkRequest.Builder clearCapabilities();
method public android.net.NetworkRequest.Builder removeCapability(int);
method public android.net.NetworkRequest.Builder removeTransportType(int);
- method public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
+ method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
}
@@ -29224,6 +29292,19 @@
method public void onStopped();
}
+ public final class TelephonyNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getSubscriptionId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.TelephonyNetworkSpecifier> CREATOR;
+ }
+
+ public static final class TelephonyNetworkSpecifier.Builder {
+ ctor public TelephonyNetworkSpecifier.Builder();
+ method @NonNull public android.net.TelephonyNetworkSpecifier build();
+ method @NonNull public android.net.TelephonyNetworkSpecifier.Builder setSubscriptionId(int);
+ }
+
public class TrafficStats {
ctor public TrafficStats();
method public static void clearThreadStatsTag();
@@ -29637,6 +29718,7 @@
method public void close();
method public void continueCall(int) throws android.net.sip.SipException;
method public void endCall() throws android.net.sip.SipException;
+ method @Nullable public android.net.rtp.AudioGroup getAudioGroup();
method public android.net.sip.SipProfile getLocalProfile();
method public android.net.sip.SipProfile getPeerProfile();
method public int getState();
@@ -29647,6 +29729,7 @@
method public void makeCall(android.net.sip.SipProfile, android.net.sip.SipSession, int) throws android.net.sip.SipException;
method public void sendDtmf(int);
method public void sendDtmf(int, android.os.Message);
+ method public void setAudioGroup(@NonNull android.net.rtp.AudioGroup);
method public void setListener(android.net.sip.SipAudioCall.Listener);
method public void setListener(android.net.sip.SipAudioCall.Listener, boolean);
method public void setSpeakerMode(boolean);
@@ -29695,6 +29778,7 @@
method public void close(String) throws android.net.sip.SipException;
method public android.net.sip.SipSession createSipSession(android.net.sip.SipProfile, android.net.sip.SipSession.Listener) throws android.net.sip.SipException;
method public static String getCallId(android.content.Intent);
+ method @NonNull public java.util.List<android.net.sip.SipProfile> getListOfProfiles() throws android.net.sip.SipException;
method public static String getOfferSessionDescription(android.content.Intent);
method public android.net.sip.SipSession getSessionFor(android.content.Intent) throws android.net.sip.SipException;
method public static boolean isApiSupported(android.content.Context);
@@ -29712,6 +29796,11 @@
method public void setRegistrationListener(String, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException;
method public android.net.sip.SipAudioCall takeAudioCall(android.content.Intent, android.net.sip.SipAudioCall.Listener) throws android.net.sip.SipException;
method public void unregister(android.net.sip.SipProfile, android.net.sip.SipRegistrationListener) throws android.net.sip.SipException;
+ field public static final String ACTION_SIP_CALL_OPTION_CHANGED = "android.net.sip.action.SIP_CALL_OPTION_CHANGED";
+ field public static final String ACTION_SIP_INCOMING_CALL = "android.net.sip.action.SIP_INCOMING_CALL";
+ field public static final String ACTION_SIP_REMOVE_PROFILE = "android.net.sip.action.SIP_REMOVE_PROFILE";
+ field public static final String ACTION_SIP_SERVICE_UP = "android.net.sip.action.SIP_SERVICE_UP";
+ field public static final String ACTION_START_SIP = "android.net.sip.action.START_SIP";
field public static final String EXTRA_CALL_ID = "android:sipCallID";
field public static final String EXTRA_OFFER_SD = "android:sipOfferSD";
field public static final int INCOMING_CALL_RESULT_CODE = 101; // 0x65
@@ -29721,6 +29810,7 @@
method public int describeContents();
method public String getAuthUserName();
method public boolean getAutoRegistration();
+ method public int getCallingUid();
method public String getDisplayName();
method public String getPassword();
method public int getPort();
@@ -29731,6 +29821,7 @@
method public String getSipDomain();
method public String getUriString();
method public String getUserName();
+ method public void setCallingUid(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.sip.SipProfile> CREATOR;
}
@@ -35218,7 +35309,9 @@
method public int describeContents();
method @Nullable public android.os.PersistableBundle getPersistableBundle(@Nullable String);
method public void putPersistableBundle(@Nullable String, @Nullable android.os.PersistableBundle);
+ method @NonNull public static android.os.PersistableBundle readFromStream(@NonNull java.io.InputStream) throws java.io.IOException;
method public void writeToParcel(android.os.Parcel, int);
+ method public void writeToStream(@NonNull java.io.OutputStream) throws java.io.IOException;
field @NonNull public static final android.os.Parcelable.Creator<android.os.PersistableBundle> CREATOR;
field public static final android.os.PersistableBundle EMPTY;
}
@@ -40836,6 +40929,7 @@
public final class SEService {
ctor public SEService(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.se.omapi.SEService.OnConnectedListener);
method @NonNull public android.se.omapi.Reader[] getReaders();
+ method @NonNull public android.se.omapi.Reader getUiccReader(int);
method @NonNull public String getVersion();
method public boolean isConnected();
method public void shutdown();
@@ -40973,6 +41067,138 @@
}
+package android.security.identity {
+
+ public class AccessControlProfile {
+ }
+
+ public static final class AccessControlProfile.Builder {
+ ctor public AccessControlProfile.Builder(@NonNull android.security.identity.AccessControlProfileId);
+ method @NonNull public android.security.identity.AccessControlProfile build();
+ method @NonNull public android.security.identity.AccessControlProfile.Builder setReaderCertificate(@NonNull java.security.cert.X509Certificate);
+ method @NonNull public android.security.identity.AccessControlProfile.Builder setUserAuthenticationRequired(boolean);
+ method @NonNull public android.security.identity.AccessControlProfile.Builder setUserAuthenticationTimeout(long);
+ }
+
+ public class AccessControlProfileId {
+ ctor public AccessControlProfileId(int);
+ method public int getId();
+ }
+
+ public class AlreadyPersonalizedException extends android.security.identity.IdentityCredentialException {
+ ctor public AlreadyPersonalizedException(@NonNull String);
+ ctor public AlreadyPersonalizedException(@NonNull String, @NonNull Throwable);
+ }
+
+ public class CipherSuiteNotSupportedException extends android.security.identity.IdentityCredentialException {
+ ctor public CipherSuiteNotSupportedException(@NonNull String);
+ ctor public CipherSuiteNotSupportedException(@NonNull String, @NonNull Throwable);
+ }
+
+ public class DocTypeNotSupportedException extends android.security.identity.IdentityCredentialException {
+ ctor public DocTypeNotSupportedException(@NonNull String);
+ ctor public DocTypeNotSupportedException(@NonNull String, @NonNull Throwable);
+ }
+
+ public class EphemeralPublicKeyNotFoundException extends android.security.identity.IdentityCredentialException {
+ ctor public EphemeralPublicKeyNotFoundException(@NonNull String);
+ ctor public EphemeralPublicKeyNotFoundException(@NonNull String, @NonNull Throwable);
+ }
+
+ public abstract class IdentityCredential {
+ method @NonNull public abstract java.security.KeyPair createEphemeralKeyPair();
+ method @NonNull public abstract byte[] decryptMessageFromReader(@NonNull byte[]) throws android.security.identity.MessageDecryptionException;
+ method @NonNull public abstract byte[] encryptMessageToReader(@NonNull byte[]);
+ method @NonNull public abstract java.util.Collection<java.security.cert.X509Certificate> getAuthKeysNeedingCertification();
+ method @NonNull public abstract int[] getAuthenticationDataUsageCount();
+ method @NonNull public abstract java.util.Collection<java.security.cert.X509Certificate> getCredentialKeyCertificateChain();
+ method @NonNull public abstract android.security.identity.ResultData getEntries(@Nullable byte[], @NonNull java.util.Map<java.lang.String,java.util.Collection<java.lang.String>>, @Nullable byte[], @Nullable byte[]) throws android.security.identity.EphemeralPublicKeyNotFoundException, android.security.identity.InvalidReaderSignatureException, android.security.identity.InvalidRequestMessageException, android.security.identity.NoAuthenticationKeyAvailableException, android.security.identity.SessionTranscriptMismatchException;
+ method public abstract void setAllowUsingExhaustedKeys(boolean);
+ method public abstract void setAvailableAuthenticationKeys(int, int);
+ method public abstract void setReaderEphemeralPublicKey(@NonNull java.security.PublicKey) throws java.security.InvalidKeyException;
+ method public abstract void storeStaticAuthenticationData(@NonNull java.security.cert.X509Certificate, @NonNull byte[]) throws android.security.identity.UnknownAuthenticationKeyException;
+ }
+
+ public class IdentityCredentialException extends java.lang.Exception {
+ ctor public IdentityCredentialException(@NonNull String);
+ ctor public IdentityCredentialException(@NonNull String, @NonNull Throwable);
+ }
+
+ public abstract class IdentityCredentialStore {
+ method @NonNull public abstract android.security.identity.WritableIdentityCredential createCredential(@NonNull String, @NonNull String) throws android.security.identity.AlreadyPersonalizedException, android.security.identity.DocTypeNotSupportedException;
+ method @Nullable public abstract byte[] deleteCredentialByName(@NonNull String);
+ method @Nullable public abstract android.security.identity.IdentityCredential getCredentialByName(@NonNull String, int) throws android.security.identity.CipherSuiteNotSupportedException;
+ method @Nullable public static android.security.identity.IdentityCredentialStore getDirectAccessInstance(@NonNull android.content.Context);
+ method @Nullable public static android.security.identity.IdentityCredentialStore getInstance(@NonNull android.content.Context);
+ method @NonNull public abstract String[] getSupportedDocTypes();
+ field public static final int CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1; // 0x1
+ }
+
+ public class InvalidReaderSignatureException extends android.security.identity.IdentityCredentialException {
+ ctor public InvalidReaderSignatureException(@NonNull String);
+ ctor public InvalidReaderSignatureException(@NonNull String, @NonNull Throwable);
+ }
+
+ public class InvalidRequestMessageException extends android.security.identity.IdentityCredentialException {
+ ctor public InvalidRequestMessageException(@NonNull String);
+ ctor public InvalidRequestMessageException(@NonNull String, @NonNull Throwable);
+ }
+
+ public class MessageDecryptionException extends android.security.identity.IdentityCredentialException {
+ ctor public MessageDecryptionException(@NonNull String);
+ ctor public MessageDecryptionException(@NonNull String, @NonNull Throwable);
+ }
+
+ public class NoAuthenticationKeyAvailableException extends android.security.identity.IdentityCredentialException {
+ ctor public NoAuthenticationKeyAvailableException(@NonNull String);
+ ctor public NoAuthenticationKeyAvailableException(@NonNull String, @NonNull Throwable);
+ }
+
+ public class PersonalizationData {
+ }
+
+ public static final class PersonalizationData.Builder {
+ ctor public PersonalizationData.Builder();
+ method @NonNull public android.security.identity.PersonalizationData.Builder addAccessControlProfile(@NonNull android.security.identity.AccessControlProfile);
+ method @NonNull public android.security.identity.PersonalizationData build();
+ method @NonNull public android.security.identity.PersonalizationData.Builder setEntry(@NonNull String, @NonNull String, @NonNull java.util.Collection<android.security.identity.AccessControlProfileId>, @NonNull byte[]);
+ }
+
+ public abstract class ResultData {
+ method @NonNull public abstract byte[] getAuthenticatedData();
+ method @Nullable public abstract byte[] getEntry(@NonNull String, @NonNull String);
+ method @Nullable public abstract java.util.Collection<java.lang.String> getEntryNames(@NonNull String);
+ method @Nullable public abstract byte[] getMessageAuthenticationCode();
+ method @NonNull public abstract java.util.Collection<java.lang.String> getNamespaceNames();
+ method @Nullable public abstract java.util.Collection<java.lang.String> getRetrievedEntryNames(@NonNull String);
+ method @NonNull public abstract byte[] getStaticAuthenticationData();
+ method public abstract int getStatus(@NonNull String, @NonNull String);
+ field public static final int STATUS_NOT_IN_REQUEST_MESSAGE = 3; // 0x3
+ field public static final int STATUS_NOT_REQUESTED = 2; // 0x2
+ field public static final int STATUS_NO_ACCESS_CONTROL_PROFILES = 6; // 0x6
+ field public static final int STATUS_NO_SUCH_ENTRY = 1; // 0x1
+ field public static final int STATUS_OK = 0; // 0x0
+ field public static final int STATUS_READER_AUTHENTICATION_FAILED = 5; // 0x5
+ field public static final int STATUS_USER_AUTHENTICATION_FAILED = 4; // 0x4
+ }
+
+ public class SessionTranscriptMismatchException extends android.security.identity.IdentityCredentialException {
+ ctor public SessionTranscriptMismatchException(@NonNull String);
+ ctor public SessionTranscriptMismatchException(@NonNull String, @NonNull Throwable);
+ }
+
+ public class UnknownAuthenticationKeyException extends android.security.identity.IdentityCredentialException {
+ ctor public UnknownAuthenticationKeyException(@NonNull String);
+ ctor public UnknownAuthenticationKeyException(@NonNull String, @NonNull Throwable);
+ }
+
+ public abstract class WritableIdentityCredential {
+ method @NonNull public abstract java.util.Collection<java.security.cert.X509Certificate> getCredentialKeyCertificateChain(@NonNull byte[]);
+ method @NonNull public abstract byte[] personalize(@NonNull android.security.identity.PersonalizationData);
+ }
+
+}
+
package android.security.keystore {
public class KeyExpiredException extends java.security.InvalidKeyException {
@@ -42575,6 +42801,7 @@
method public static void execve(String, String[], String[]) throws android.system.ErrnoException;
method public static void fchmod(java.io.FileDescriptor, int) throws android.system.ErrnoException;
method public static void fchown(java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
+ method public static int fcntlInt(@NonNull java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
method public static void fdatasync(java.io.FileDescriptor) throws android.system.ErrnoException;
method public static android.system.StructStat fstat(java.io.FileDescriptor) throws android.system.ErrnoException;
method public static android.system.StructStatVfs fstatvfs(java.io.FileDescriptor) throws android.system.ErrnoException;
@@ -43255,6 +43482,7 @@
method public java.util.List<android.telecom.Call> getChildren();
method public java.util.List<android.telecom.Call> getConferenceableCalls();
method public android.telecom.Call.Details getDetails();
+ method @Nullable public android.telecom.Call getGenericConferenceActiveChildCall();
method public android.telecom.Call getParent();
method public String getRemainingPostDialSequence();
method @Nullable public android.telecom.Call.RttCall getRttCall();
@@ -43338,6 +43566,7 @@
method public int getCallerDisplayNamePresentation();
method public int getCallerNumberVerificationStatus();
method public final long getConnectTimeMillis();
+ method @Nullable public String getContactDisplayName();
method public long getCreationTimeMillis();
method public android.telecom.DisconnectCause getDisconnectCause();
method public android.os.Bundle getExtras();
@@ -44201,6 +44430,8 @@
package android.telephony {
public final class AccessNetworkConstants {
+ field public static final int TRANSPORT_TYPE_WLAN = 2; // 0x2
+ field public static final int TRANSPORT_TYPE_WWAN = 1; // 0x1
}
public static final class AccessNetworkConstants.AccessNetworkType {
@@ -44375,6 +44606,9 @@
field public static final int DATA_CYCLE_USE_PLATFORM_DEFAULT = -1; // 0xffffffff
field public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX";
field public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
+ field public static final String IMSI_KEY_AVAILABILITY_INT = "imsi_key_availability_int";
+ field public static final String KEY_5G_ICON_CONFIGURATION_STRING = "5g_icon_configuration_string";
+ field public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT = "5g_icon_display_grace_period_sec_int";
field public static final String KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY = "5g_nr_ssrsrp_thresholds_int_array";
field public static final String KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY = "5g_nr_ssrsrq_thresholds_int_array";
field public static final String KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY = "5g_nr_sssinr_thresholds_int_array";
@@ -44388,18 +44622,32 @@
field public static final String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool";
field public static final String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool";
field public static final String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool";
- field public static final String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool";
+ field public static final String KEY_ALLOW_VIDEO_CALLING_FALLBACK_BOOL = "allow_video_calling_fallback_bool";
+ field public static final String KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL = "always_show_data_rat_icon_bool";
+ field @Deprecated public static final String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool";
+ field public static final String KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN = "always_show_primary_signal_bar_in_opportunistic_network_boolean";
field public static final String KEY_APN_EXPAND_BOOL = "apn_expand_bool";
+ field public static final String KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY = "apn_settings_default_apn_types_string_array";
field public static final String KEY_AUTO_RETRY_ENABLED_BOOL = "auto_retry_enabled_bool";
field public static final String KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL = "call_barring_supports_deactivate_all_bool";
field public static final String KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL = "call_barring_supports_password_change_bool";
field public static final String KEY_CALL_BARRING_VISIBILITY_BOOL = "call_barring_visibility_bool";
field public static final String KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY = "call_forwarding_blocks_while_roaming_string_array";
+ field public static final String KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING = "call_redirection_service_component_name_string";
+ field public static final String KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL = "carrier_allow_deflect_ims_call_bool";
field public static final String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool";
field public static final String KEY_CARRIER_APP_REQUIRED_DURING_SIM_SETUP_BOOL = "carrier_app_required_during_setup_bool";
field public static final String KEY_CARRIER_CALL_SCREENING_APP_STRING = "call_screening_app";
+ field public static final String KEY_CARRIER_CERTIFICATE_STRING_ARRAY = "carrier_certificate_string_array";
+ field public static final String KEY_CARRIER_CONFIG_APPLIED_BOOL = "carrier_config_applied_bool";
field public static final String KEY_CARRIER_CONFIG_VERSION_STRING = "carrier_config_version_string";
field public static final String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS = "carrier_data_call_permanent_failure_strings";
+ field public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DCFAILURE_STRING_ARRAY = "carrier_default_actions_on_dcfailure_string_array";
+ field public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE = "carrier_default_actions_on_default_network_available_string_array";
+ field public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY = "carrier_default_actions_on_redirection_string_array";
+ field public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET = "carrier_default_actions_on_reset_string_array";
+ field public static final String KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY = "carrier_default_redirection_url_string_array";
+ field public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL = "carrier_default_wfc_ims_enabled_bool";
field public static final String KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT = "carrier_default_wfc_ims_mode_int";
field public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT = "carrier_default_wfc_ims_roaming_mode_int";
field @Deprecated public static final String KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL = "carrier_force_disable_etws_cmas_test_bool";
@@ -44411,11 +44659,14 @@
field public static final String KEY_CARRIER_INSTANT_LETTERING_LENGTH_LIMIT_INT = "carrier_instant_lettering_length_limit_int";
field public static final String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
field public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
+ field public static final String KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL = "carrier_rcs_provisioning_required_bool";
+ field public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string";
field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
field public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL = "carrier_supports_ss_over_ut_bool";
field public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
field public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool";
field public static final String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
+ field public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL = "carrier_volte_override_wfc_provisioning_bool";
field public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
field public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
field public static final String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
@@ -44429,6 +44680,7 @@
field public static final String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
field public static final String KEY_CDMA_ROAMING_MODE_INT = "cdma_roaming_mode_int";
field public static final String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
+ field public static final String KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL = "check_pricing_with_carrier_data_roaming_bool";
field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_BOOL = "ci_action_on_sys_update_bool";
field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING = "ci_action_on_sys_update_extra_string";
field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
@@ -44438,6 +44690,7 @@
field public static final String KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING = "config_ims_rcs_package_override_string";
field public static final String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
field public static final String KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL = "config_telephony_use_own_number_for_voicemail_bool";
+ field public static final String KEY_CONFIG_WIFI_DISABLE_IN_ECBM = "config_wifi_disable_in_ecbm";
field public static final String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
field public static final String KEY_DATA_LIMIT_NOTIFICATION_BOOL = "data_limit_notification_bool";
field public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
@@ -44449,6 +44702,7 @@
field public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
field public static final String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array";
field public static final String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+ field public static final String KEY_DISABLE_CHARGE_INDICATION_BOOL = "disable_charge_indication_bool";
field public static final String KEY_DISABLE_SUPPLEMENTARY_SERVICES_IN_AIRPLANE_MODE_BOOL = "disable_supplementary_services_in_airplane_mode_bool";
field public static final String KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY = "disconnect_cause_play_busytone_int_array";
field public static final String KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL = "display_hd_audio_property_bool";
@@ -44458,9 +44712,13 @@
field public static final String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
field public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool";
field public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_SETTING_BOOL = "editable_voicemail_number_setting_bool";
+ field public static final String KEY_EDITABLE_WFC_MODE_BOOL = "editable_wfc_mode_bool";
+ field public static final String KEY_EDITABLE_WFC_ROAMING_MODE_BOOL = "editable_wfc_roaming_mode_bool";
+ field public static final String KEY_EMERGENCY_NOTIFICATION_DELAY_INT = "emergency_notification_delay_int";
field public static final String KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY = "emergency_number_prefix_string_array";
field public static final String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
field public static final String KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL = "enhanced_4g_lte_on_by_default_bool";
+ field public static final String KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT = "enhanced_4g_lte_title_variant_int";
field public static final String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
field public static final String KEY_GSM_DTMF_TONE_DELAY_INT = "gsm_dtmf_tone_delay_int";
field public static final String KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
@@ -44469,13 +44727,17 @@
field public static final String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
field public static final String KEY_HIDE_ENHANCED_4G_LTE_BOOL = "hide_enhanced_4g_lte_bool";
field public static final String KEY_HIDE_IMS_APN_BOOL = "hide_ims_apn_bool";
+ field public static final String KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL = "hide_lte_plus_data_icon_bool";
field public static final String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final String KEY_HIDE_PRESET_APN_DETAILS_BOOL = "hide_preset_apn_details_bool";
field public static final String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
+ field public static final String KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS = "ignore_data_enabled_changed_for_video_calls";
+ field public static final String KEY_IGNORE_RTT_MODE_SETTING_BOOL = "ignore_rtt_mode_setting_bool";
field public static final String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
field public static final String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
field public static final String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
field public static final String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+ field public static final String KEY_LTE_ENABLED_BOOL = "lte_enabled_bool";
field public static final String KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY = "lte_rsrq_thresholds_int_array";
field public static final String KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY = "lte_rssnr_thresholds_int_array";
field public static final String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL = "mdn_is_additional_voicemail_number_bool";
@@ -44484,6 +44746,7 @@
field public static final String KEY_MMS_ALIAS_MIN_CHARS_INT = "aliasMinChars";
field public static final String KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL = "allowAttachAudio";
field public static final String KEY_MMS_APPEND_TRANSACTION_ID_BOOL = "enabledTransID";
+ field public static final String KEY_MMS_CLOSE_CONNECTION_BOOL = "mmsCloseConnection";
field public static final String KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING = "emailGatewayNumber";
field public static final String KEY_MMS_GROUP_MMS_ENABLED_BOOL = "enableGroupMms";
field public static final String KEY_MMS_HTTP_PARAMS_STRING = "httpParams";
@@ -44511,6 +44774,7 @@
field public static final String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
field public static final String KEY_MMS_USER_AGENT_STRING = "userAgent";
field public static final String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
+ field public static final String KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL = "only_auto_select_in_home_network";
field public static final String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
field public static final String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
field public static final String KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG = "opportunistic_network_data_switch_hysteresis_time_long";
@@ -44524,15 +44788,24 @@
field public static final String KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL = "prevent_clir_activation_and_deactivation_code_bool";
field public static final String KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY = "radio_restart_failure_causes_int_array";
field public static final String KEY_RCS_CONFIG_SERVER_URL_STRING = "rcs_config_server_url_string";
+ field public static final String KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY = "read_only_apn_fields_string_array";
+ field public static final String KEY_READ_ONLY_APN_TYPES_STRING_ARRAY = "read_only_apn_types_string_array";
field public static final String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
field @Deprecated public static final String KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL = "restart_radio_on_pdp_fail_regular_deactivation_bool";
field public static final String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool";
+ field public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL = "show_4g_for_3g_data_icon_bool";
+ field public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL = "show_4g_for_lte_data_icon_bool";
field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
+ field public static final String KEY_SHOW_BLOCKING_PAY_PHONE_OPTION_BOOL = "show_blocking_pay_phone_option_bool";
field public static final String KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL = "show_call_blocking_disabled_notification_always_bool";
+ field public static final String KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING = "show_carrier_data_icon_pattern_string";
field public static final String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
field public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
+ field public static final String KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL = "show_ims_registration_status_bool";
field public static final String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
field public static final String KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL = "show_signal_strength_in_sim_status_bool";
+ field public static final String KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL = "show_video_call_charges_alert_dialog_bool";
+ field public static final String KEY_SHOW_WFC_LOCATION_PRIVACY_POLICY_BOOL = "show_wfc_location_privacy_policy_bool";
field public static final String KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL = "simplified_network_settings_bool";
field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
@@ -44541,14 +44814,20 @@
field public static final String KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL = "support_clir_network_default_bool";
field public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
field public static final String KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL = "support_emergency_sms_over_ims_bool";
+ field public static final String KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL = "support_enhanced_call_blocking_bool";
+ field public static final String KEY_SUPPORT_IMS_CONFERENCE_EVENT_PACKAGE_BOOL = "support_ims_conference_event_package_bool";
field public static final String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool";
field public static final String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
+ field public static final String KEY_SUPPORT_TDSCDMA_BOOL = "support_tdscdma_bool";
+ field public static final String KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY = "support_tdscdma_roaming_networks_string_array";
field public static final String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool";
field public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool";
+ field public static final String KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY = "unloggable_numbers_string_array";
field public static final String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
field public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
field public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
field public static final String KEY_USE_RCS_SIP_OPTIONS_BOOL = "use_rcs_sip_options_bool";
+ field public static final String KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL = "use_wfc_home_network_mode_in_roaming_network_bool";
field public static final String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
field public static final String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
field public static final String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
@@ -44561,6 +44840,8 @@
field public static final String KEY_VVM_PREFETCH_BOOL = "vvm_prefetch_bool";
field public static final String KEY_VVM_SSL_ENABLED_BOOL = "vvm_ssl_enabled_bool";
field public static final String KEY_VVM_TYPE_STRING = "vvm_type_string";
+ field public static final String KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING = "wfc_emergency_address_carrier_app_string";
+ field public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
@@ -44663,7 +44944,8 @@
method public int getCellConnectionStatus();
method @NonNull public abstract android.telephony.CellIdentity getCellIdentity();
method @NonNull public abstract android.telephony.CellSignalStrength getCellSignalStrength();
- method public long getTimeStamp();
+ method @Deprecated public long getTimeStamp();
+ method public long getTimestampNanos();
method public boolean isRegistered();
field public static final int CONNECTION_NONE = 0; // 0x0
field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
@@ -44898,6 +45180,35 @@
field @Deprecated public static final int UNKNOWN_RSSI = 99; // 0x63
}
+ public final class NetworkRegistrationInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getAccessNetworkTechnology();
+ method @NonNull public java.util.List<java.lang.Integer> getAvailableServices();
+ method @Nullable public android.telephony.CellIdentity getCellIdentity();
+ method public int getDomain();
+ method public int getNrState();
+ method public int getTransportType();
+ method public boolean isRegistered();
+ method public boolean isRoaming();
+ method public boolean isSearching();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationInfo> CREATOR;
+ field public static final int DOMAIN_CS = 1; // 0x1
+ field public static final int DOMAIN_CS_PS = 3; // 0x3
+ field public static final int DOMAIN_PS = 2; // 0x2
+ field public static final int DOMAIN_UNKNOWN = 0; // 0x0
+ field public static final int NR_STATE_CONNECTED = 3; // 0x3
+ field public static final int NR_STATE_NONE = 0; // 0x0
+ field public static final int NR_STATE_NOT_RESTRICTED = 2; // 0x2
+ field public static final int NR_STATE_RESTRICTED = 1; // 0x1
+ field public static final int SERVICE_TYPE_DATA = 2; // 0x2
+ field public static final int SERVICE_TYPE_EMERGENCY = 5; // 0x5
+ field public static final int SERVICE_TYPE_SMS = 3; // 0x3
+ field public static final int SERVICE_TYPE_UNKNOWN = 0; // 0x0
+ field public static final int SERVICE_TYPE_VIDEO = 4; // 0x4
+ field public static final int SERVICE_TYPE_VOICE = 1; // 0x1
+ }
+
public class NetworkScan {
method public void stopScan();
field public static final int ERROR_INTERRUPTED = 10002; // 0x2712
@@ -45013,6 +45324,7 @@
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
method public void onMessageWaitingIndicatorChanged(boolean);
method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
+ method public void onRegistrationFailed(@NonNull android.telephony.CellIdentity, @NonNull String, int, int, int);
method public void onServiceStateChanged(android.telephony.ServiceState);
method @Deprecated public void onSignalStrengthChanged(int);
method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
@@ -45029,7 +45341,8 @@
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
field public static final int LISTEN_NONE = 0; // 0x0
- field @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
+ field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000
field public static final int LISTEN_SERVICE_STATE = 1; // 0x1
field @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 2; // 0x2
field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100
@@ -45068,11 +45381,13 @@
method public int getChannelNumber();
method public int getDuplexMode();
method public boolean getIsManualSelection();
+ method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
method public String getOperatorAlphaLong();
method public String getOperatorAlphaShort();
method public String getOperatorNumeric();
method public boolean getRoaming();
method public int getState();
+ method public boolean isSearching();
method public void setIsManualSelection(boolean);
method public void setOperatorName(String, String, String);
method public void setRoaming(boolean);
@@ -45103,8 +45418,10 @@
method @Deprecated public int getGsmBitErrorRate();
method @Deprecated public int getGsmSignalStrength();
method public int getLevel();
+ method public long getTimestampNanos();
method @Deprecated public boolean isGsm();
method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SignalStrength> CREATOR;
field public static final int INVALID = 2147483647; // 0x7fffffff
}
@@ -45113,7 +45430,7 @@
method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent);
method public java.util.ArrayList<java.lang.String> divideMessage(String);
method public void downloadMultimediaMessage(android.content.Context, String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
- method public android.os.Bundle getCarrierConfigValues();
+ method @Nullable public android.os.Bundle getCarrierConfigValues();
method public static android.telephony.SmsManager getDefault();
method public static int getDefaultSmsSubscriptionId();
method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
@@ -45251,6 +45568,7 @@
method public byte[] getPdu();
method public int getProtocolIdentifier();
method public String getPseudoSubject();
+ method @Nullable public String getRecipientAddress();
method public String getServiceCenterAddress();
method public int getStatus();
method public int getStatusOnIcc();
@@ -45322,6 +45640,7 @@
public class SubscriptionManager {
method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+ method public void addOnSubscriptionsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void addSubscriptionsIntoGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid);
method public boolean canManageSubscription(android.telephony.SubscriptionInfo);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>);
@@ -45387,6 +45706,7 @@
method public long getDataLimitBytes();
method public long getDataUsageBytes();
method public long getDataUsageTime();
+ method @Nullable public int[] getNetworkTypes();
method @Nullable public CharSequence getSummary();
method @Nullable public CharSequence getTitle();
method public void writeToParcel(android.os.Parcel, int);
@@ -45406,6 +45726,7 @@
method public static android.telephony.SubscriptionPlan.Builder createRecurring(java.time.ZonedDateTime, java.time.Period);
method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
+ method @NonNull public android.telephony.SubscriptionPlan.Builder setNetworkTypes(@Nullable int[]);
method public android.telephony.SubscriptionPlan.Builder setSummary(@Nullable CharSequence);
method public android.telephony.SubscriptionPlan.Builder setTitle(@Nullable CharSequence);
}
@@ -45447,6 +45768,7 @@
method public String getNetworkCountryIso();
method public String getNetworkOperator();
method public String getNetworkOperatorName();
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public int getNetworkSelectionMode();
method public String getNetworkSpecifier();
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getNetworkType();
method @Deprecated public int getPhoneCount();
@@ -45477,12 +45799,12 @@
method public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
method public boolean hasCarrierPrivileges();
method public boolean hasIccCard();
- method public boolean iccCloseLogicalChannel(int);
- method public byte[] iccExchangeSimIO(int, int, int, int, int, String);
+ method @Deprecated public boolean iccCloseLogicalChannel(int);
+ method @Deprecated public byte[] iccExchangeSimIO(int, int, int, int, int, String);
method @Deprecated public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(String);
- method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(String, int);
- method public String iccTransmitApduBasicChannel(int, int, int, int, int, String);
- method public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String);
+ method @Deprecated public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(String, int);
+ method @Deprecated public String iccTransmitApduBasicChannel(int, int, int, int, int, String);
+ method @Deprecated public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String);
method public boolean isConcurrentVoiceAndDataSupported();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean isDataEnabled();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled();
@@ -45500,7 +45822,7 @@
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
method public void sendDialerSpecialCode(String);
- method public String sendEnvelopeWithStatus(String);
+ method @Deprecated public String sendEnvelopeWithStatus(String);
method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean);
@@ -45579,6 +45901,9 @@
field public static final int MULTISIM_ALLOWED = 0; // 0x0
field public static final int MULTISIM_NOT_SUPPORTED_BY_CARRIER = 2; // 0x2
field public static final int MULTISIM_NOT_SUPPORTED_BY_HARDWARE = 1; // 0x1
+ field public static final int NETWORK_SELECTION_MODE_AUTO = 1; // 0x1
+ field public static final int NETWORK_SELECTION_MODE_MANUAL = 2; // 0x2
+ field public static final int NETWORK_SELECTION_MODE_UNKNOWN = 0; // 0x0
field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
@@ -45601,6 +45926,7 @@
field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
field public static final int PHONE_TYPE_CDMA = 2; // 0x2
field public static final int PHONE_TYPE_GSM = 1; // 0x1
+ field public static final int PHONE_TYPE_IMS = 5; // 0x5
field public static final int PHONE_TYPE_NONE = 0; // 0x0
field public static final int PHONE_TYPE_SIP = 3; // 0x3
field public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2; // 0x2
@@ -45989,6 +46315,37 @@
package android.telephony.ims {
+ public final class ImsException extends java.lang.Exception {
+ method public int getCode();
+ field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1
+ field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0
+ field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2
+ }
+
+ public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
+ method @NonNull @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public int getVoWiFiModeSetting();
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isAdvancedCallingSettingEnabled();
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isTtyOverVolteEnabled();
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isVoWiFiRoamingSettingEnabled();
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isVoWiFiSettingEnabled();
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isVtSettingEnabled();
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
+ method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback);
+ field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1
+ field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0
+ field public static final int WIFI_MODE_WIFI_PREFERRED = 2; // 0x2
+ }
+
+ public static class ImsMmTelManager.CapabilityCallback {
+ ctor public ImsMmTelManager.CapabilityCallback();
+ method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
+ }
+
public final class ImsReasonInfo implements android.os.Parcelable {
ctor public ImsReasonInfo(int, int, @Nullable String);
method public int describeContents();
@@ -46172,6 +46529,38 @@
field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2
}
+ public interface RegistrationManager {
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
+ field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0
+ field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2
+ field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1
+ }
+
+ public static class RegistrationManager.RegistrationCallback {
+ ctor public RegistrationManager.RegistrationCallback();
+ method public void onRegistered(int);
+ method public void onRegistering(int);
+ method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo);
+ method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo);
+ }
+
+}
+
+package android.telephony.ims.feature {
+
+ public class MmTelFeature {
+ }
+
+ public static class MmTelFeature.MmTelCapabilities {
+ field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8
+ field public static final int CAPABILITY_TYPE_UT = 4; // 0x4
+ field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2
+ field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1
+ }
+
}
package android.telephony.mbms {
@@ -49197,6 +49586,71 @@
}
+package android.util.proto {
+
+ public final class ProtoOutputStream {
+ ctor public ProtoOutputStream();
+ ctor public ProtoOutputStream(int);
+ ctor public ProtoOutputStream(@NonNull java.io.OutputStream);
+ method public static int checkFieldId(long, long);
+ method public void dump(@NonNull String);
+ method public void end(long);
+ method public void flush();
+ method @NonNull public byte[] getBytes();
+ method @Nullable public static String getFieldCountString(long);
+ method @NonNull public static String getFieldIdString(long);
+ method @Nullable public static String getFieldTypeString(long);
+ method public int getRawSize();
+ method @Nullable public static String getWireTypeString(int);
+ method public static long makeFieldId(int, long);
+ method public static long makeToken(int, boolean, int, int, int);
+ method public long start(long);
+ method @NonNull public static String token2String(long);
+ method public void write(long, double);
+ method public void write(long, float);
+ method public void write(long, int);
+ method public void write(long, long);
+ method public void write(long, boolean);
+ method public void write(long, @Nullable String);
+ method public void write(long, @Nullable byte[]);
+ method public void writeTag(int, int);
+ field public static final long FIELD_COUNT_MASK = 16492674416640L; // 0xf0000000000L
+ field public static final long FIELD_COUNT_PACKED = 5497558138880L; // 0x50000000000L
+ field public static final long FIELD_COUNT_REPEATED = 2199023255552L; // 0x20000000000L
+ field public static final int FIELD_COUNT_SHIFT = 40; // 0x28
+ field public static final long FIELD_COUNT_SINGLE = 1099511627776L; // 0x10000000000L
+ field public static final long FIELD_COUNT_UNKNOWN = 0L; // 0x0L
+ field public static final int FIELD_ID_SHIFT = 3; // 0x3
+ field public static final long FIELD_TYPE_BOOL = 34359738368L; // 0x800000000L
+ field public static final long FIELD_TYPE_BYTES = 51539607552L; // 0xc00000000L
+ field public static final long FIELD_TYPE_DOUBLE = 4294967296L; // 0x100000000L
+ field public static final long FIELD_TYPE_ENUM = 60129542144L; // 0xe00000000L
+ field public static final long FIELD_TYPE_FIXED32 = 30064771072L; // 0x700000000L
+ field public static final long FIELD_TYPE_FIXED64 = 25769803776L; // 0x600000000L
+ field public static final long FIELD_TYPE_FLOAT = 8589934592L; // 0x200000000L
+ field public static final long FIELD_TYPE_INT32 = 21474836480L; // 0x500000000L
+ field public static final long FIELD_TYPE_INT64 = 12884901888L; // 0x300000000L
+ field public static final long FIELD_TYPE_MASK = 1095216660480L; // 0xff00000000L
+ field public static final long FIELD_TYPE_MESSAGE = 47244640256L; // 0xb00000000L
+ field public static final long FIELD_TYPE_SFIXED32 = 64424509440L; // 0xf00000000L
+ field public static final long FIELD_TYPE_SFIXED64 = 68719476736L; // 0x1000000000L
+ field public static final int FIELD_TYPE_SHIFT = 32; // 0x20
+ field public static final long FIELD_TYPE_SINT32 = 73014444032L; // 0x1100000000L
+ field public static final long FIELD_TYPE_SINT64 = 77309411328L; // 0x1200000000L
+ field public static final long FIELD_TYPE_STRING = 38654705664L; // 0x900000000L
+ field public static final long FIELD_TYPE_UINT32 = 55834574848L; // 0xd00000000L
+ field public static final long FIELD_TYPE_UINT64 = 17179869184L; // 0x400000000L
+ field public static final int WIRE_TYPE_END_GROUP = 4; // 0x4
+ field public static final int WIRE_TYPE_FIXED32 = 5; // 0x5
+ field public static final int WIRE_TYPE_FIXED64 = 1; // 0x1
+ field public static final int WIRE_TYPE_LENGTH_DELIMITED = 2; // 0x2
+ field public static final int WIRE_TYPE_MASK = 7; // 0x7
+ field public static final int WIRE_TYPE_START_GROUP = 3; // 0x3
+ field public static final int WIRE_TYPE_VARINT = 0; // 0x0
+ }
+
+}
+
package android.view {
public abstract class AbsSavedState implements android.os.Parcelable {
@@ -70690,6 +71144,18 @@
method public int lastIndexOf(@Nullable Object);
method @NonNull public java.util.ListIterator<E> listIterator();
method @NonNull public java.util.ListIterator<E> listIterator(int);
+ method @NonNull public static <E> java.util.List<E> of();
+ method @NonNull public static <E> java.util.List<E> of(@NonNull E);
+ method @NonNull public static <E> java.util.List<E> of(@NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.List<E> of(@NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.List<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.List<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.List<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.List<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.List<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.List<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.List<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull @java.lang.SafeVarargs public static <E> java.util.List<E> of(@NonNull E...);
method public E remove(int);
method public default void replaceAll(@NonNull java.util.function.UnaryOperator<E>);
method public E set(int, E);
@@ -70844,6 +71310,7 @@
method @Nullable public default V computeIfPresent(K, @NonNull java.util.function.BiFunction<? super K,? super V,? extends V>);
method public boolean containsKey(@Nullable Object);
method public boolean containsValue(@Nullable Object);
+ method @NonNull public static <K, V> java.util.Map.Entry<K,V> entry(@NonNull K, @NonNull V);
method @NonNull public java.util.Set<java.util.Map.Entry<K,V>> entrySet();
method public boolean equals(@Nullable Object);
method public default void forEach(@NonNull java.util.function.BiConsumer<? super K,? super V>);
@@ -70853,6 +71320,18 @@
method public boolean isEmpty();
method @NonNull public java.util.Set<K> keySet();
method @Nullable public default V merge(K, @NonNull V, @NonNull java.util.function.BiFunction<? super V,? super V,? extends V>);
+ method @NonNull public static <K, V> java.util.Map<K,V> of();
+ method @NonNull public static <K, V> java.util.Map<K,V> of(@NonNull K, @NonNull V);
+ method @NonNull public static <K, V> java.util.Map<K,V> of(@NonNull K, @NonNull V, @NonNull K, @NonNull V);
+ method @NonNull public static <K, V> java.util.Map<K,V> of(@NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V);
+ method @NonNull public static <K, V> java.util.Map<K,V> of(@NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V);
+ method @NonNull public static <K, V> java.util.Map<K,V> of(@NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V);
+ method @NonNull public static <K, V> java.util.Map<K,V> of(@NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V);
+ method @NonNull public static <K, V> java.util.Map<K,V> of(@NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V);
+ method @NonNull public static <K, V> java.util.Map<K,V> of(@NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V);
+ method @NonNull public static <K, V> java.util.Map<K,V> of(@NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V);
+ method @NonNull public static <K, V> java.util.Map<K,V> of(@NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V, @NonNull K, @NonNull V);
+ method @NonNull @java.lang.SafeVarargs public static <K, V> java.util.Map<K,V> ofEntries(@NonNull java.util.Map.Entry<? extends K,? extends V>...);
method @Nullable public V put(K, V);
method public void putAll(@NonNull java.util.Map<? extends K,? extends V>);
method @Nullable public default V putIfAbsent(K, V);
@@ -70934,6 +71413,9 @@
}
public final class Objects {
+ method public static int checkFromIndexSize(int, int, int);
+ method public static int checkFromToIndex(int, int, int);
+ method public static int checkIndex(int, int);
method public static <T> int compare(T, T, @NonNull java.util.Comparator<? super T>);
method public static boolean deepEquals(@Nullable Object, @Nullable Object);
method public static boolean equals(@Nullable Object, @Nullable Object);
@@ -70944,6 +71426,8 @@
method @NonNull public static <T> T requireNonNull(@Nullable T);
method @NonNull public static <T> T requireNonNull(@Nullable T, @NonNull String);
method @NonNull public static <T> T requireNonNull(@Nullable T, @NonNull java.util.function.Supplier<java.lang.String>);
+ method @NonNull public static <T> T requireNonNullElse(@Nullable T, @NonNull T);
+ method @NonNull public static <T> T requireNonNullElseGet(@Nullable T, @NonNull java.util.function.Supplier<? extends T>);
method @NonNull public static String toString(@Nullable Object);
method @NonNull public static String toString(@Nullable Object, @NonNull String);
}
@@ -71248,6 +71732,18 @@
}
public interface Set<E> extends java.util.Collection<E> {
+ method @NonNull public static <E> java.util.Set<E> of();
+ method @NonNull public static <E> java.util.Set<E> of(@NonNull E);
+ method @NonNull public static <E> java.util.Set<E> of(@NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.Set<E> of(@NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.Set<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.Set<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.Set<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.Set<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.Set<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.Set<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull public static <E> java.util.Set<E> of(@NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E, @NonNull E);
+ method @NonNull @java.lang.SafeVarargs public static <E> java.util.Set<E> of(@NonNull E...);
}
public class SimpleTimeZone extends java.util.TimeZone {
@@ -72186,6 +72682,29 @@
method public static java.util.concurrent.ScheduledExecutorService unconfigurableScheduledExecutorService(java.util.concurrent.ScheduledExecutorService);
}
+ public final class Flow {
+ method public static int defaultBufferSize();
+ }
+
+ public static interface Flow.Processor<T, R> extends java.util.concurrent.Flow.Subscriber<T> java.util.concurrent.Flow.Publisher<R> {
+ }
+
+ @java.lang.FunctionalInterface public static interface Flow.Publisher<T> {
+ method public void subscribe(java.util.concurrent.Flow.Subscriber<? super T>);
+ }
+
+ public static interface Flow.Subscriber<T> {
+ method public void onComplete();
+ method public void onError(Throwable);
+ method public void onNext(T);
+ method public void onSubscribe(java.util.concurrent.Flow.Subscription);
+ }
+
+ public static interface Flow.Subscription {
+ method public void cancel();
+ method public void request(long);
+ }
+
public class ForkJoinPool extends java.util.concurrent.AbstractExecutorService {
ctor public ForkJoinPool();
ctor public ForkJoinPool(int);
diff --git a/api/lint-baseline.txt b/api/lint-baseline.txt
index 2720498..5c31f41 100644
--- a/api/lint-baseline.txt
+++ b/api/lint-baseline.txt
@@ -485,10 +485,20 @@
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#CHORASMIAN:
+ Missing nullability on field `CHORASMIAN` in class `class android.icu.lang.UCharacter.UnicodeBlock`
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G:
+ Missing nullability on field `CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G` in class `class android.icu.lang.UCharacter.UnicodeBlock`
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#DIVES_AKURU:
+ Missing nullability on field `DIVES_AKURU` in class `class android.icu.lang.UCharacter.UnicodeBlock`
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS:
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#ELYMAIC:
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#KHITAN_SMALL_SCRIPT:
+
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#LISU_SUPPLEMENT:
+
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#NANDINAGARI:
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#NYIAKENG_PUACHUE_HMONG:
@@ -499,26 +509,34 @@
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A:
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#SYMBOLS_FOR_LEGACY_COMPUTING:
+
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#TAMIL_SUPPLEMENT:
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#TANGUT_SUPPLEMENT:
+
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#WANCHO:
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#YEZIDI:
+
MissingNullability: android.icu.text.DateTimePatternGenerator#getFieldDisplayName(int, android.icu.text.DateTimePatternGenerator.DisplayWidth):
MissingNullability: android.icu.text.DateTimePatternGenerator#getFieldDisplayName(int, android.icu.text.DateTimePatternGenerator.DisplayWidth) parameter #1:
MissingNullability: android.icu.util.MeasureUnit#ATMOSPHERE:
- Missing nullability on field `ATMOSPHERE` in class `class android.icu.util.MeasureUnit`
+
MissingNullability: android.icu.util.MeasureUnit#PERCENT:
- Missing nullability on field `PERCENT` in class `class android.icu.util.MeasureUnit`
+
MissingNullability: android.icu.util.MeasureUnit#PERMILLE:
- Missing nullability on field `PERMILLE` in class `class android.icu.util.MeasureUnit`
+
MissingNullability: android.icu.util.MeasureUnit#PETABYTE:
- Missing nullability on field `PETABYTE` in class `class android.icu.util.MeasureUnit`
+
MissingNullability: android.icu.util.VersionInfo#UNICODE_12_0:
MissingNullability: android.icu.util.VersionInfo#UNICODE_12_1:
+MissingNullability: android.icu.util.VersionInfo#UNICODE_13_0:
+ Missing nullability on field `UNICODE_13_0` in class `class android.icu.util.VersionInfo`
RequiresPermission: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
diff --git a/api/module-app-current.txt b/api/module-app-current.txt
new file mode 100644
index 0000000..4307e67
--- /dev/null
+++ b/api/module-app-current.txt
@@ -0,0 +1,9 @@
+// Signature format: 2.0
+package android.app {
+
+ public final class NotificationChannel implements android.os.Parcelable {
+ method public void setBlockableSystem(boolean);
+ }
+
+}
+
diff --git a/api/module-app-removed.txt b/api/module-app-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/api/module-app-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
new file mode 100644
index 0000000..c657e00
--- /dev/null
+++ b/api/module-lib-current.txt
@@ -0,0 +1,148 @@
+// Signature format: 2.0
+package android.app.timedetector {
+
+ public final class PhoneTimeSuggestion implements android.os.Parcelable {
+ method public void addDebugInfo(@NonNull String);
+ method public void addDebugInfo(@NonNull java.util.List<java.lang.String>);
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getDebugInfo();
+ method public int getPhoneId();
+ method @Nullable public android.os.TimestampedValue<java.lang.Long> getUtcTime();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.timedetector.PhoneTimeSuggestion> CREATOR;
+ }
+
+ public static final class PhoneTimeSuggestion.Builder {
+ ctor public PhoneTimeSuggestion.Builder(int);
+ method @NonNull public android.app.timedetector.PhoneTimeSuggestion.Builder addDebugInfo(@NonNull String);
+ method @NonNull public android.app.timedetector.PhoneTimeSuggestion build();
+ method @NonNull public android.app.timedetector.PhoneTimeSuggestion.Builder setUtcTime(@Nullable android.os.TimestampedValue<java.lang.Long>);
+ }
+
+ public class TimeDetector {
+ method @RequiresPermission("android.permission.SUGGEST_PHONE_TIME_AND_ZONE") public void suggestPhoneTime(@NonNull android.app.timedetector.PhoneTimeSuggestion);
+ }
+
+}
+
+package android.app.timezonedetector {
+
+ public final class PhoneTimeZoneSuggestion implements android.os.Parcelable {
+ method public void addDebugInfo(@NonNull String);
+ method public void addDebugInfo(@NonNull java.util.List<java.lang.String>);
+ method @NonNull public static android.app.timezonedetector.PhoneTimeZoneSuggestion createEmptySuggestion(int, @NonNull String);
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getDebugInfo();
+ method public int getMatchType();
+ method public int getPhoneId();
+ method public int getQuality();
+ method @Nullable public String getZoneId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.timezonedetector.PhoneTimeZoneSuggestion> CREATOR;
+ field public static final int MATCH_TYPE_EMULATOR_ZONE_ID = 4; // 0x4
+ field public static final int MATCH_TYPE_NA = 0; // 0x0
+ field public static final int MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET = 3; // 0x3
+ field public static final int MATCH_TYPE_NETWORK_COUNTRY_ONLY = 2; // 0x2
+ field public static final int MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY = 5; // 0x5
+ field public static final int QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS = 3; // 0x3
+ field public static final int QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET = 2; // 0x2
+ field public static final int QUALITY_NA = 0; // 0x0
+ field public static final int QUALITY_SINGLE_ZONE = 1; // 0x1
+ }
+
+ public static final class PhoneTimeZoneSuggestion.Builder {
+ ctor public PhoneTimeZoneSuggestion.Builder(int);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder addDebugInfo(@NonNull String);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion build();
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder setMatchType(int);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder setQuality(int);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder setZoneId(@Nullable String);
+ }
+
+ public class TimeZoneDetector {
+ method @RequiresPermission("android.permission.SUGGEST_PHONE_TIME_AND_ZONE") public void suggestPhoneTimeZone(@NonNull android.app.timezonedetector.PhoneTimeZoneSuggestion);
+ }
+
+}
+
+package android.os {
+
+ public final class TimestampedValue<T> implements android.os.Parcelable {
+ ctor public TimestampedValue(long, @Nullable T);
+ method public int describeContents();
+ method public long getReferenceTimeMillis();
+ method @Nullable public T getValue();
+ method public static long referenceTimeDifference(@NonNull android.os.TimestampedValue<?>, @NonNull android.os.TimestampedValue<?>);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.TimestampedValue<?>> CREATOR;
+ }
+
+}
+
+package android.timezone {
+
+ public final class CountryTimeZones {
+ method @Nullable public android.icu.util.TimeZone getDefaultTimeZone();
+ method @Nullable public String getDefaultTimeZoneId();
+ method @NonNull public java.util.List<android.timezone.CountryTimeZones.TimeZoneMapping> getEffectiveTimeZoneMappingsAt(long);
+ method public boolean hasUtcZone(long);
+ method public boolean isDefaultTimeZoneBoosted();
+ method public boolean isForCountryCode(@NonNull String);
+ method @Nullable public android.timezone.CountryTimeZones.OffsetResult lookupByOffsetWithBias(int, @Nullable Boolean, @Nullable Integer, long, @Nullable android.icu.util.TimeZone);
+ }
+
+ public static final class CountryTimeZones.OffsetResult {
+ ctor public CountryTimeZones.OffsetResult(@NonNull android.icu.util.TimeZone, boolean);
+ method @NonNull public android.icu.util.TimeZone getTimeZone();
+ method public boolean isOnlyMatch();
+ }
+
+ public static final class CountryTimeZones.TimeZoneMapping {
+ method @Nullable public android.icu.util.TimeZone getTimeZone();
+ method @NonNull public String getTimeZoneId();
+ }
+
+ public class TelephonyLookup {
+ method @NonNull public static android.timezone.TelephonyLookup getInstance();
+ method @Nullable public android.timezone.TelephonyNetworkFinder getTelephonyNetworkFinder();
+ }
+
+ public class TelephonyNetwork {
+ method @NonNull public String getCountryIsoCode();
+ method @NonNull public String getMcc();
+ method @NonNull public String getMnc();
+ }
+
+ public class TelephonyNetworkFinder {
+ method @Nullable public android.timezone.TelephonyNetwork findNetworkByMccMnc(@NonNull String, @NonNull String);
+ }
+
+ public final class TimeZoneFinder {
+ method @Nullable public String getIanaVersion();
+ method @NonNull public static android.timezone.TimeZoneFinder getInstance();
+ method @Nullable public android.timezone.CountryTimeZones lookupCountryTimeZones(@NonNull String);
+ }
+
+ public final class TzDataSetVersion {
+ method public static int currentFormatMajorVersion();
+ method public static int currentFormatMinorVersion();
+ method public int getFormatMajorVersion();
+ method public int getFormatMinorVersion();
+ method public int getRevision();
+ method @NonNull public String getRulesVersion();
+ method public static boolean isCompatibleWithThisDevice(android.timezone.TzDataSetVersion);
+ method @NonNull public static android.timezone.TzDataSetVersion read() throws java.io.IOException, android.timezone.TzDataSetVersion.TzDataSetException;
+ }
+
+ public static class TzDataSetVersion.TzDataSetException extends java.lang.Exception {
+ ctor public TzDataSetVersion.TzDataSetException(String);
+ ctor public TzDataSetVersion.TzDataSetException(String, Throwable);
+ }
+
+ public final class ZoneInfoDb {
+ method @NonNull public static android.timezone.ZoneInfoDb getInstance();
+ method @NonNull public String getVersion();
+ }
+
+}
+
diff --git a/api/module-lib-removed.txt b/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/api/system-current.txt b/api/system-current.txt
index 0edf9ab..558907c 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8,6 +8,7 @@
field public static final String ACCESS_DRM_CERTIFICATES = "android.permission.ACCESS_DRM_CERTIFICATES";
field @Deprecated public static final String ACCESS_FM_RADIO = "android.permission.ACCESS_FM_RADIO";
field public static final String ACCESS_INSTANT_APPS = "android.permission.ACCESS_INSTANT_APPS";
+ field public static final String ACCESS_MESSAGES_ON_ICC = "android.permission.ACCESS_MESSAGES_ON_ICC";
field public static final String ACCESS_MOCK_LOCATION = "android.permission.ACCESS_MOCK_LOCATION";
field public static final String ACCESS_MTP = "android.permission.ACCESS_MTP";
field public static final String ACCESS_NETWORK_CONDITIONS = "android.permission.ACCESS_NETWORK_CONDITIONS";
@@ -181,6 +182,7 @@
field public static final String REVIEW_ACCESSIBILITY_SERVICES = "android.permission.REVIEW_ACCESSIBILITY_SERVICES";
field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
+ field public static final String SECURE_ELEMENT_PRIVILEGED = "android.permission.SECURE_ELEMENT_PRIVILEGED";
field public static final String SEND_DEVICE_CUSTOMIZATION_READY = "android.permission.SEND_DEVICE_CUSTOMIZATION_READY";
field public static final String SEND_SHOW_SUSPENDED_APP_DETAILS = "android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS";
field public static final String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
@@ -198,6 +200,7 @@
field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
field public static final String SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON = "android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON";
+ field public static final String SUGGEST_PHONE_TIME_AND_ZONE = "android.permission.SUGGEST_PHONE_TIME_AND_ZONE";
field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
field public static final String TV_INPUT_HARDWARE = "android.permission.TV_INPUT_HARDWARE";
@@ -596,6 +599,7 @@
public class StatusBarManager {
method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo();
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSetup(boolean);
+ method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSimNetworkLock(boolean);
}
public static final class StatusBarManager.DisableInfo {
@@ -680,6 +684,7 @@
package android.app.admin {
public class DevicePolicyManager {
+ method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean getBluetoothContactSharingDisabled(@NonNull android.os.UserHandle);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwner();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwnerNameOnAnyUser();
@@ -1162,6 +1167,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+ method @Nullable public String getDefaultSmsPackage(int);
method @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List<java.lang.String> getHeldRolesFromController(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
@@ -1205,6 +1211,10 @@
field public static final String SERVICE_INTERFACE = "android.app.usage.CacheQuotaService";
}
+ public class NetworkStatsManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.net.netstats.provider.NetworkStatsProviderCallback registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.AbstractNetworkStatsProvider);
+ }
+
public static final class UsageEvents.Event {
method public int getInstanceId();
method @Nullable public String getNotificationChannelId();
@@ -1411,12 +1421,33 @@
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
}
- public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
- method protected void finalize();
+ public final class BluetoothHidDevice implements android.bluetooth.BluetoothProfile {
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+ }
+
+ public final class BluetoothHidHost implements android.bluetooth.BluetoothProfile {
method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice);
method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
- method public boolean isTetheringOn();
- method public void setBluetoothTethering(boolean);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice, int);
+ field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
+ }
+
+ public final class BluetoothMap implements android.bluetooth.BluetoothProfile {
+ method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice, int);
+ field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
+ }
+
+ public final class BluetoothPan implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public void close();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) protected void finalize();
+ method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isTetheringOn();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public void setBluetoothTethering(boolean);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
field public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
field public static final int LOCAL_NAP_ROLE = 1; // 0x1
@@ -1428,14 +1459,19 @@
public class BluetoothPbap implements android.bluetooth.BluetoothProfile {
method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
field 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 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
}
@@ -1543,7 +1579,9 @@
field public static final String EUICC_CARD_SERVICE = "euicc_card";
field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
field public static final String NETD_SERVICE = "netd";
+ field public static final String NETWORK_POLICY_SERVICE = "netpolicy";
field public static final String NETWORK_SCORE_SERVICE = "network_score";
+ field public static final String NETWORK_STACK_SERVICE = "network_stack";
field public static final String OEM_LOCK_SERVICE = "oem_lock";
field public static final String PERMISSION_SERVICE = "permission";
field public static final String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
@@ -1620,6 +1658,7 @@
field public static final String EXTRA_PERMISSION_GROUP_NAME = "android.intent.extra.PERMISSION_GROUP_NAME";
field public static final String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME";
field public static final String EXTRA_REASON = "android.intent.extra.REASON";
+ field @Deprecated public static final String EXTRA_REBROADCAST_ON_UNLOCK = "rebroadcastOnUnlock";
field public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
field public static final String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
field public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
@@ -2054,6 +2093,15 @@
}
+package android.debug {
+
+ public class AdbManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING) public boolean isAdbWifiQrSupported();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING) public boolean isAdbWifiSupported();
+ }
+
+}
+
package android.hardware {
public final class Sensor {
@@ -3229,9 +3277,17 @@
}
public class UsbManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public long getCurrentFunctions();
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_USB) public java.util.List<android.hardware.usb.UsbPort> getPorts();
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void grantPermission(android.hardware.usb.UsbDevice, String);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long);
field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED";
+ field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE";
+ field public static final long FUNCTION_NONE = 0L; // 0x0L
+ field public static final long FUNCTION_RNDIS = 32L; // 0x20L
+ field public static final String USB_CONFIGURED = "configured";
+ field public static final String USB_CONNECTED = "connected";
+ field public static final String USB_FUNCTION_RNDIS = "rndis";
}
public final class UsbPort {
@@ -3665,6 +3721,19 @@
method public android.media.AudioAttributes.Builder setInternalCapturePreset(int);
}
+ public final class AudioDeviceAddress implements android.os.Parcelable {
+ ctor public AudioDeviceAddress(@NonNull android.media.AudioDeviceInfo);
+ ctor public AudioDeviceAddress(int, int, @NonNull String);
+ method public int describeContents();
+ method @NonNull public String getAddress();
+ method public int getRole();
+ method public int getType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioDeviceAddress> CREATOR;
+ field public static final int ROLE_INPUT = 1; // 0x1
+ field public static final int ROLE_OUTPUT = 2; // 0x2
+ }
+
public final class AudioFocusInfo implements android.os.Parcelable {
method public int describeContents();
method @NonNull public android.media.AudioAttributes getAttributes();
@@ -3786,6 +3855,14 @@
}
+package android.media.audiofx {
+
+ public class AudioEffect {
+ ctor @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public AudioEffect(@NonNull java.util.UUID, @NonNull android.media.AudioDeviceAddress);
+ }
+
+}
+
package android.media.audiopolicy {
public class AudioMix {
@@ -3972,6 +4049,15 @@
package android.media.tv {
+ public final class DvbDeviceInfo implements android.os.Parcelable {
+ ctor public DvbDeviceInfo(int, int);
+ method public int describeContents();
+ method public int getAdapterId();
+ method public int getDeviceId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.DvbDeviceInfo> CREATOR;
+ }
+
public final class TvContentRatingSystemInfo implements android.os.Parcelable {
method public static android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo);
method public int describeContents();
@@ -4086,12 +4172,14 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating);
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig);
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String);
+ method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList();
method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList();
method @RequiresPermission(android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS) public java.util.List<android.media.tv.TvContentRatingSystemInfo> getTvContentRatingSystemList();
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean isSingleSessionActive();
method @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) public void notifyPreviewProgramAddedToWatchNext(String, long, long);
method @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) public void notifyPreviewProgramBrowsableDisabled(String, long);
method @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) public void notifyWatchNextProgramBrowsableDisabled(String, long);
+ method @Nullable @RequiresPermission("android.permission.DVB_DEVICE") public android.os.ParcelFileDescriptor openDvbDevice(@NonNull android.media.tv.DvbDeviceInfo, int);
method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public void releaseTvInputHardware(int, android.media.tv.TvInputManager.Hardware);
method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void removeBlockedRating(@NonNull android.media.tv.TvContentRating);
method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void setParentalControlsEnabled(boolean);
@@ -4212,25 +4300,56 @@
public class CaptivePortal implements android.os.Parcelable {
method public void logEvent(int, @NonNull String);
+ method public void reevaluateNetwork();
method public void useNetwork();
+ field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64
field public static final int APP_RETURN_DISMISSED = 0; // 0x0
field public static final int APP_RETURN_UNWANTED = 1; // 0x1
field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
}
+ public final class CaptivePortalData implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getByteLimit();
+ method public long getExpiryTimeMillis();
+ method public long getRefreshTimeMillis();
+ method @Nullable public android.net.Uri getUserPortalUrl();
+ method @Nullable public android.net.Uri getVenueInfoUrl();
+ method public boolean isCaptive();
+ method public boolean isSessionExtendable();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
+ }
+
+ public static class CaptivePortalData.Builder {
+ ctor public CaptivePortalData.Builder();
+ ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
+ method @NonNull public android.net.CaptivePortalData build();
+ method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
+ method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
+ method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
+ method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
+ method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
+ method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
+ method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
+ }
+
public class ConnectivityManager {
method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
method @Deprecated @RequiresPermission("android.permission.NETWORK_SETTINGS") public String getCaptivePortalServerUrl();
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public int registerNetworkProvider(@NonNull android.net.NetworkProvider);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
+ method @Deprecated public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, int, int, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, "android.permission.NETWORK_STACK"}) public boolean shouldAvoidBadWifi();
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider);
method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
@@ -4240,6 +4359,8 @@
field public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd
field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
field public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
+ field public static final int TYPE_NONE = -1; // 0xffffffff
+ field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd
}
public abstract static class ConnectivityManager.OnStartTetheringCallback {
@@ -4257,6 +4378,14 @@
method public void onUpstreamChanged(@Nullable android.net.Network);
}
+ public class InvalidPacketException extends java.lang.Exception {
+ ctor public InvalidPacketException(int);
+ field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb
+ field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9
+ field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea
+ field public final int error;
+ }
+
public final class IpConfiguration implements android.os.Parcelable {
ctor public IpConfiguration();
ctor public IpConfiguration(@NonNull android.net.IpConfiguration);
@@ -4307,6 +4436,15 @@
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecTransform buildTunnelModeTransform(@NonNull java.net.InetAddress, @NonNull android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
}
+ public class KeepalivePacketData {
+ ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException;
+ method @NonNull public byte[] getPacket();
+ field @NonNull public final java.net.InetAddress dstAddress;
+ field public final int dstPort;
+ field @NonNull public final java.net.InetAddress srcAddress;
+ field public final int srcPort;
+ }
+
public class LinkAddress implements android.os.Parcelable {
ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int);
ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
@@ -4327,6 +4465,8 @@
method @NonNull public java.util.List<java.lang.String> getAllInterfaceNames();
method @NonNull public java.util.List<android.net.LinkAddress> getAllLinkAddresses();
method @NonNull public java.util.List<android.net.RouteInfo> getAllRoutes();
+ method @Nullable public android.net.Uri getCaptivePortalApiUrl();
+ method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
method @Nullable public String getTcpBufferSizes();
method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
@@ -4340,9 +4480,12 @@
method public boolean isIpv6Provisioned();
method public boolean isProvisioned();
method public boolean isReachable(@NonNull java.net.InetAddress);
+ method @NonNull public android.net.LinkProperties makeSensitiveFieldsParcelingCopy();
method public boolean removeDnsServer(@NonNull java.net.InetAddress);
method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
method public boolean removeRoute(@NonNull android.net.RouteInfo);
+ method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
+ method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
method public void setPrivateDnsServerName(@Nullable String);
method public void setTcpBufferSizes(@Nullable String);
@@ -4353,17 +4496,44 @@
public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
ctor public MatchAllNetworkSpecifier();
method public int describeContents();
+ method public boolean satisfiedBy(android.net.NetworkSpecifier);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.MatchAllNetworkSpecifier> CREATOR;
}
+ public final class NattKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
+ ctor public NattKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException;
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NattKeepalivePacketData> CREATOR;
+ }
+
public class Network implements android.os.Parcelable {
ctor public Network(@NonNull android.net.Network);
method @NonNull public android.net.Network getPrivateDnsBypassingCopy();
field public final int netId;
}
+ public final class NetworkAgentConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getSubscriberId();
+ method public boolean isNat64DetectionEnabled();
+ method public boolean isProvisioningNotificationEnabled();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkAgentConfig> CREATOR;
+ }
+
+ public static class NetworkAgentConfig.Builder {
+ ctor public NetworkAgentConfig.Builder();
+ method @NonNull public android.net.NetworkAgentConfig build();
+ method @NonNull public android.net.NetworkAgentConfig.Builder disableNat64Detection();
+ method @NonNull public android.net.NetworkAgentConfig.Builder disableProvisioningNotification();
+ method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
+ }
+
public final class NetworkCapabilities implements android.os.Parcelable {
+ method public boolean deduceRestrictedCapability();
+ method @Nullable public String getSSID();
method @NonNull public int[] getTransportTypes();
method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
method @NonNull public android.net.NetworkCapabilities setSSID(@Nullable String);
@@ -4383,12 +4553,27 @@
field public final android.net.WifiKey wifiKey;
}
+ public class NetworkProvider {
+ ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest);
+ method @Nullable public android.os.Messenger getMessenger();
+ method @NonNull public String getName();
+ method public int getProviderId();
+ method public void onNetworkRequested(@NonNull android.net.NetworkRequest, int, int);
+ method public void onRequestWithdrawn(@NonNull android.net.NetworkRequest);
+ field public static final int ID_NONE = -1; // 0xffffffff
+ }
+
public abstract class NetworkRecommendationProvider {
ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor);
method public final android.os.IBinder getBinder();
method public abstract void onRequestScores(android.net.NetworkKey[]);
}
+ public class NetworkRequest implements android.os.Parcelable {
+ method public boolean satisfiedBy(@Nullable android.net.NetworkCapabilities);
+ }
+
public static class NetworkRequest.Builder {
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int);
}
@@ -4409,6 +4594,9 @@
field @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
field public static final String EXTRA_NEW_SCORER = "newScorer";
field @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName";
+ field public static final int SCORE_FILTER_CURRENT_NETWORK = 1; // 0x1
+ field public static final int SCORE_FILTER_NONE = 0; // 0x0
+ field public static final int SCORE_FILTER_SCAN_RESULTS = 2; // 0x2
}
public static interface NetworkScoreManager.NetworkScoreCallback {
@@ -4416,10 +4604,43 @@
method public void updateScores(@NonNull java.util.List<android.net.ScoredNetwork>);
}
+ public abstract class NetworkSpecifier {
+ method public void assertValidFromUid(int);
+ method @Nullable public android.net.NetworkSpecifier redact();
+ method public abstract boolean satisfiedBy(@Nullable android.net.NetworkSpecifier);
+ }
+
public class NetworkStack {
field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
}
+ public final class NetworkStats implements 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 addValues(@NonNull android.net.NetworkStats.Entry);
+ method public int describeContents();
+ 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;
+ field public static final int DEFAULT_NETWORK_NO = 0; // 0x0
+ field public static final int DEFAULT_NETWORK_YES = 1; // 0x1
+ field @Nullable public static final String IFACE_ALL;
+ field public static final String IFACE_VT = "vt_data0";
+ field public static final int METERED_NO = 0; // 0x0
+ field public static final int METERED_YES = 1; // 0x1
+ field public static final int ROAMING_NO = 0; // 0x0
+ field public static final int ROAMING_YES = 1; // 0x1
+ field public static final int SET_DEFAULT = 0; // 0x0
+ field public static final int SET_FOREGROUND = 1; // 0x1
+ field public static final int TAG_NONE = 0; // 0x0
+ field public static final int UID_ALL = -1; // 0xffffffff
+ field public static final int UID_TETHERING = -5; // 0xfffffffb
+ }
+
+ public static class NetworkStats.Entry {
+ ctor public NetworkStats.Entry(@Nullable String, int, int, int, int, int, int, long, long, long, long, long);
+ }
+
public final class RouteInfo implements android.os.Parcelable {
ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int);
method public int getType();
@@ -4459,6 +4680,10 @@
field public final android.net.RssiCurve rssiCurve;
}
+ public abstract class SocketKeepalive implements java.lang.AutoCloseable {
+ field public static final int SUCCESS = 0; // 0x0
+ }
+
public final class StaticIpConfiguration implements android.os.Parcelable {
ctor public StaticIpConfiguration();
ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
@@ -4486,11 +4711,16 @@
public final class StringNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
ctor public StringNetworkSpecifier(@NonNull String);
method public int describeContents();
+ method public boolean satisfiedBy(android.net.NetworkSpecifier);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.StringNetworkSpecifier> CREATOR;
field @NonNull public final String specifier;
}
+ public final class TelephonyNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ method public boolean satisfiedBy(android.net.NetworkSpecifier);
+ }
+
public class TrafficStats {
method public static void setThreadStatsTagApp();
method public static void setThreadStatsTagBackup();
@@ -4616,9 +4846,11 @@
}
public abstract class ChildSessionParams {
+ method public long getHardLifetime();
method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getLocalTrafficSelectors();
method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getRemoteTrafficSelectors();
method @NonNull public java.util.List<android.net.ipsec.ike.ChildSaProposal> getSaProposals();
+ method public long getSoftLifetime();
}
public class IkeFqdnIdentification extends android.net.ipsec.ike.IkeIdentification {
@@ -4687,12 +4919,14 @@
}
public final class IkeSessionParams {
+ method public long getHardLifetime();
method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getLocalAuthConfig();
method @NonNull public android.net.ipsec.ike.IkeIdentification getLocalIdentification();
method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getRemoteAuthConfig();
method @NonNull public android.net.ipsec.ike.IkeIdentification getRemoteIdentification();
method @NonNull public java.util.List<android.net.ipsec.ike.IkeSaProposal> getSaProposals();
method @NonNull public java.net.InetAddress getServerAddress();
+ method public long getSoftLifetime();
method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket getUdpEncapsulationSocket();
}
@@ -4704,6 +4938,7 @@
method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@Nullable java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.util.List<java.security.cert.X509Certificate>, @NonNull java.security.PrivateKey);
method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthEap(@Nullable java.security.cert.X509Certificate, @NonNull android.net.eap.EapSessionConfig);
method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthPsk(@NonNull byte[]);
+ method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setLifetime(long, long);
method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setLocalIdentification(@NonNull android.net.ipsec.ike.IkeIdentification);
method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setRemoteIdentification(@NonNull android.net.ipsec.ike.IkeIdentification);
method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setServerAddress(@NonNull java.net.InetAddress);
@@ -4774,6 +5009,7 @@
method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal);
method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams build();
+ method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder setLifetime(long, long);
}
public final class TunnelModeChildSessionParams extends android.net.ipsec.ike.ChildSessionParams {
@@ -4791,6 +5027,7 @@
method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal);
method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams build();
+ method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder setLifetime(long, long);
}
public static interface TunnelModeChildSessionParams.ConfigRequest {
@@ -5010,6 +5247,25 @@
}
+package android.net.netstats.provider {
+
+ public abstract class AbstractNetworkStatsProvider {
+ ctor public AbstractNetworkStatsProvider();
+ method public abstract void requestStatsUpdate(int);
+ method public abstract void setAlert(long);
+ method public abstract void setLimit(@NonNull String, long);
+ field public static final int QUOTA_UNLIMITED = -1; // 0xffffffff
+ }
+
+ public class NetworkStatsProviderCallback {
+ method public void onAlertReached();
+ method public void onLimitReached();
+ method public void onStatsUpdated(int, @NonNull android.net.NetworkStats, @NonNull android.net.NetworkStats);
+ method public void unregister();
+ }
+
+}
+
package android.net.util {
public final class SocketUtils {
@@ -5359,6 +5615,10 @@
field public int numUsage;
}
+ public final class WifiNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ method public boolean satisfiedBy(android.net.NetworkSpecifier);
+ }
+
public class WifiScanner {
method @Deprecated public void configureWifiChange(int, int, int, int, int, android.net.wifi.WifiScanner.BssidInfo[]);
method @Deprecated public void configureWifiChange(android.net.wifi.WifiScanner.WifiChangeSettings);
@@ -5523,6 +5783,10 @@
method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
}
+ public final class WifiAwareNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ method public boolean satisfiedBy(android.net.NetworkSpecifier);
+ }
+
public static final class WifiAwareNetworkSpecifier.Builder {
method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPmk(@NonNull byte[]);
}
@@ -6099,11 +6363,13 @@
public class UpdateEngine {
ctor public UpdateEngine();
+ method @NonNull public android.os.UpdateEngine.AllocateSpaceResult allocateSpace(@NonNull String, @NonNull String[]);
method public void applyPayload(String, long, long, String[]);
- method public void applyPayload(@NonNull android.os.ParcelFileDescriptor, long, long, @NonNull String[]);
+ method public void applyPayload(@NonNull android.content.res.AssetFileDescriptor, @NonNull String[]);
method public boolean bind(android.os.UpdateEngineCallback, android.os.Handler);
method public boolean bind(android.os.UpdateEngineCallback);
method public void cancel();
+ method public int cleanupAppliedPayload();
method public void resetStatus();
method public void resume();
method public void suspend();
@@ -6111,14 +6377,21 @@
method public boolean verifyPayloadMetadata(String);
}
+ public static final class UpdateEngine.AllocateSpaceResult {
+ method public int errorCode();
+ method public long freeSpaceRequired();
+ }
+
public static final class UpdateEngine.ErrorCodeConstants {
ctor public UpdateEngine.ErrorCodeConstants();
+ field public static final int DEVICE_CORRUPTED = 61; // 0x3d
field public static final int DOWNLOAD_PAYLOAD_VERIFICATION_ERROR = 12; // 0xc
field public static final int DOWNLOAD_TRANSFER_ERROR = 9; // 0x9
field public static final int ERROR = 1; // 0x1
field public static final int FILESYSTEM_COPIER_ERROR = 4; // 0x4
field public static final int INSTALL_DEVICE_OPEN_ERROR = 7; // 0x7
field public static final int KERNEL_DEVICE_OPEN_ERROR = 8; // 0x8
+ field public static final int NOT_ENOUGH_SPACE = 60; // 0x3c
field public static final int PAYLOAD_HASH_MISMATCH_ERROR = 10; // 0xa
field public static final int PAYLOAD_MISMATCHED_TYPE_ERROR = 6; // 0x6
field public static final int PAYLOAD_SIZE_MISMATCH_ERROR = 11; // 0xb
@@ -6638,6 +6911,7 @@
}
public final class Settings {
+ method public static boolean checkAndNoteWriteSettingsOperation(@NonNull android.content.Context, int, @NonNull String, boolean);
field public static final String ACTION_ACCESSIBILITY_DETAILS_SETTINGS = "android.settings.ACCESSIBILITY_DETAILS_SETTINGS";
field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
field public static final String ACTION_LOCATION_CONTROLLER_EXTRA_PACKAGE_SETTINGS = "android.settings.LOCATION_CONTROLLER_EXTRA_PACKAGE_SETTINGS";
@@ -6646,6 +6920,7 @@
field public static final String ACTION_NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS = "android.settings.NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS";
field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
field public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
+ field public static final String ACTION_TETHER_PROVISIONING_UI = "android.settings.TETHER_PROVISIONING_UI";
}
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
@@ -6663,6 +6938,7 @@
field public static final String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS = "install_carrier_app_notification_sleep_millis";
field public static final String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
field public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt";
+ field public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
field public static final String TETHER_SUPPORTED = "tether_supported";
field public static final String THEATER_MODE_ON = "theater_mode_on";
field public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
@@ -6735,7 +7011,9 @@
public static final class Telephony.Carriers implements android.provider.BaseColumns {
field public static final String APN_SET_ID = "apn_set_id";
field public static final int CARRIER_EDITED = 4; // 0x4
+ field @NonNull public static final android.net.Uri DPC_URI;
field public static final String EDITED_STATUS = "edited";
+ field public static final int INVALID_APN_ID = -1; // 0xffffffff
field public static final String MAX_CONNECTIONS = "max_conns";
field public static final String MODEM_PERSIST = "modem_cognitive";
field public static final String MTU = "mtu";
@@ -6750,6 +7028,9 @@
}
public static final class Telephony.CellBroadcasts implements android.provider.BaseColumns {
+ field @NonNull public static final String AUTHORITY_LEGACY = "cellbroadcast-legacy";
+ field @NonNull public static final android.net.Uri AUTHORITY_LEGACY_URI;
+ field @NonNull public static final String CALL_METHOD_GET_PREFERENCE = "get_preference";
field public static final String CID = "cid";
field public static final String CMAS_CATEGORY = "cmas_category";
field public static final String CMAS_CERTAINTY = "cmas_certainty";
@@ -6780,6 +7061,20 @@
field public static final String SUB_ID = "sub_id";
}
+ public static final class Telephony.CellBroadcasts.Preference {
+ field @NonNull public static final String ENABLE_ALERT_VIBRATION_PREF = "enable_alert_vibrate";
+ field @NonNull public static final String ENABLE_AREA_UPDATE_INFO_PREF = "enable_area_update_info_alerts";
+ field @NonNull public static final String ENABLE_CMAS_AMBER_PREF = "enable_cmas_amber_alerts";
+ field @NonNull public static final String ENABLE_CMAS_EXTREME_THREAT_PREF = "enable_cmas_extreme_threat_alerts";
+ field @NonNull public static final String ENABLE_CMAS_IN_SECOND_LANGUAGE_PREF = "receive_cmas_in_second_language";
+ field @NonNull public static final String ENABLE_CMAS_PRESIDENTIAL_PREF = "enable_cmas_presidential_alerts";
+ field @NonNull public static final String ENABLE_CMAS_SEVERE_THREAT_PREF = "enable_cmas_severe_threat_alerts";
+ field @NonNull public static final String ENABLE_EMERGENCY_PERF = "enable_emergency_alerts";
+ field @NonNull public static final String ENABLE_PUBLIC_SAFETY_PREF = "enable_public_safety_messages";
+ field @NonNull public static final String ENABLE_STATE_LOCAL_TEST_PREF = "enable_state_local_test_alerts";
+ field @NonNull public static final String ENABLE_TEST_ALERT_PREF = "enable_test_alerts";
+ }
+
public static final class Telephony.SimInfo {
field @NonNull public static final android.net.Uri CONTENT_URI;
}
@@ -7894,8 +8189,6 @@
public final class AccessNetworkConstants {
field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff
- field public static final int TRANSPORT_TYPE_WLAN = 2; // 0x2
- field public static final int TRANSPORT_TYPE_WWAN = 1; // 0x1
}
public final class CallAttributes implements android.os.Parcelable {
@@ -8007,6 +8300,41 @@
field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService";
}
+ public abstract class CellIdentity implements android.os.Parcelable {
+ method @NonNull public abstract android.telephony.CellLocation asCellLocation();
+ method @NonNull public abstract android.telephony.CellIdentity sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityCdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.cdma.CdmaCellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityCdma sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityGsm extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityGsm sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityLte extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityLte sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityNr extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.CellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityNr sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityTdscdma sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityWcdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityWcdma sanitizeLocationInfo();
+ }
+
public final class DataFailCause {
field public static final int ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 2219; // 0x8ab
field public static final int ACCESS_BLOCK = 2087; // 0x827
@@ -8488,35 +8816,18 @@
}
public final class NetworkRegistrationInfo implements android.os.Parcelable {
- method public int describeContents();
- method public int getAccessNetworkTechnology();
- method @NonNull public java.util.List<java.lang.Integer> getAvailableServices();
- method @Nullable public android.telephony.CellIdentity getCellIdentity();
method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
- method public int getDomain();
- method public int getNrState();
method public int getRegistrationState();
method public int getRejectCause();
method public int getRoamingType();
- method public int getTransportType();
method public boolean isEmergencyEnabled();
- method public boolean isRoaming();
method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationInfo> CREATOR;
- field public static final int DOMAIN_CS = 1; // 0x1
- field public static final int DOMAIN_PS = 2; // 0x2
field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3
field public static final int REGISTRATION_STATE_HOME = 1; // 0x1
field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0
field public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2; // 0x2
field public static final int REGISTRATION_STATE_ROAMING = 5; // 0x5
field public static final int REGISTRATION_STATE_UNKNOWN = 4; // 0x4
- field public static final int SERVICE_TYPE_DATA = 2; // 0x2
- field public static final int SERVICE_TYPE_EMERGENCY = 5; // 0x5
- field public static final int SERVICE_TYPE_SMS = 3; // 0x3
- field public static final int SERVICE_TYPE_UNKNOWN = 0; // 0x0
- field public static final int SERVICE_TYPE_VIDEO = 4; // 0x4
- field public static final int SERVICE_TYPE_VOICE = 1; // 0x1
}
public static final class NetworkRegistrationInfo.Builder {
@@ -8591,7 +8902,7 @@
method public void onRadioPowerStateChanged(int);
method public void onSrvccStateChanged(int);
method public void onVoiceActivationStateChanged(int);
- field public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
@@ -8621,6 +8932,7 @@
}
public final class PreciseDataConnectionState implements android.os.Parcelable {
+ ctor public PreciseDataConnectionState(int, int, int, @NonNull String, @Nullable android.net.LinkProperties, int, @Nullable android.telephony.data.ApnSetting);
method @Deprecated @NonNull public String getDataConnectionApn();
method @Deprecated public int getDataConnectionApnTypeBitMask();
method @Deprecated public int getDataConnectionFailCause();
@@ -8727,19 +9039,27 @@
}
public class ServiceState implements android.os.Parcelable {
+ method @NonNull public android.telephony.ServiceState createLocationInfoSanitizedCopy(boolean);
+ method public void fillInNotifierBundle(@NonNull android.os.Bundle);
+ method public int getDataNetworkType();
+ method public int getDataRegistrationState();
method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int);
- method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int);
method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForTransportType(int);
method public int getNrFrequencyRange();
method @Nullable public String getOperatorAlphaLongRaw();
method @Nullable public String getOperatorAlphaShortRaw();
+ method @NonNull public static android.telephony.ServiceState newFromBundle(@NonNull android.os.Bundle);
field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2
field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3
field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0
field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1
}
+ public class SignalStrength implements android.os.Parcelable {
+ ctor public SignalStrength(@NonNull android.telephony.SignalStrength);
+ }
+
public final class SmsCbCmasInfo implements android.os.Parcelable {
ctor public SmsCbCmasInfo(int, int, int, int, int, int);
method public int describeContents();
@@ -8863,13 +9183,22 @@
}
public final class SmsManager {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean copyMessageToIcc(@Nullable byte[], @NonNull byte[], int);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean deleteMessageFromIcc(int);
method public boolean disableCellBroadcastRange(int, int, int);
method public boolean enableCellBroadcastRange(int, int, int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public java.util.List<android.telephony.SmsMessage> getMessagesFromIcc();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSmsCapacityOnIcc();
method public void sendMultipartTextMessage(@NonNull String, @NonNull String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
}
+ public class SmsMessage {
+ method @Nullable public static android.telephony.SmsMessage createFromNativeSmsSubmitPdu(@NonNull byte[], boolean);
+ method @Nullable public static android.telephony.SmsMessage.SubmitPdu getSmsPdu(int, int, @Nullable String, @NonNull String, @NonNull String, long);
+ method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static byte[] getSubmitPduEncodedMessage(boolean, @NonNull String, @NonNull String, int, int, int, int, int, int);
+ }
+
public class SubscriptionInfo implements android.os.Parcelable {
method public boolean areUiccApplicationsEnabled();
method @Nullable public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
@@ -8879,6 +9208,8 @@
public class SubscriptionManager {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean canDisablePhysicalSubscription();
+ method public boolean canManageSubscription(@Nullable android.telephony.SubscriptionInfo, @Nullable String);
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String);
method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int);
method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int);
@@ -8890,6 +9221,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUiccApplicationsEnabled(boolean, int);
field @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED";
field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
@@ -8931,6 +9263,7 @@
}
public class TelephonyManager {
+ method public int addDevicePolicyOverrideApn(@NonNull android.content.Context, @NonNull android.telephony.data.ApnSetting);
method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
method public int checkCarrierPrivilegesForPackage(String);
method public int checkCarrierPrivilegesForPackageAnyPhone(String);
@@ -8944,6 +9277,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
@@ -8957,10 +9291,12 @@
method @Deprecated public boolean getDataEnabled();
method @Deprecated public boolean getDataEnabled(int);
method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
+ method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
method public int getEmergencyNumberDbVersion();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getIsimImpu();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
method public int getMaxNumberOfSimultaneouslyActiveSims();
@@ -8980,26 +9316,29 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmi(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmiForSubscriber(int, String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int);
method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int);
- method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
- method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
+ method public boolean isCurrentSimOperator(@NonNull String, int, @Nullable String);
method public boolean isDataConnectivityPossible();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isInEmergencySmsMode();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isManualNetworkSelectionAllowed();
method public boolean isModemEnabledForSlot(int);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTetheringApnRequired();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isTetheringApnRequired();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled();
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
+ method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
method public boolean needsOtaServiceProvisioning();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
@@ -9037,10 +9376,12 @@
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
field public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
- field public static final String ACTION_NETWORK_SET_TIME = "android.telephony.action.NETWORK_SET_TIME";
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
+ field public static final int CARD_POWER_DOWN = 0; // 0x0
+ field public static final int CARD_POWER_UP = 1; // 0x1
+ field public static final int CARD_POWER_UP_PASS_THROUGH = 2; // 0x2
field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
@@ -9073,6 +9414,7 @@
field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L
field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L
field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L
+ field public static final int PHONE_TYPE_THIRD_PARTY = 4; // 0x4
field public static final int RADIO_POWER_OFF = 0; // 0x0
field public static final int RADIO_POWER_ON = 1; // 0x1
field public static final int RADIO_POWER_UNAVAILABLE = 2; // 0x2
@@ -9098,6 +9440,7 @@
method public void addOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyCallStateChangedForAllSubscriptions(int, @Nullable String);
method public void notifyCarrierNetworkChange(boolean);
+ method public void notifyRegistrationFailed(int, int, @NonNull android.telephony.CellIdentity, @NonNull String, int, int, int);
method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
method public void removeOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
}
@@ -9473,6 +9816,7 @@
method public int getEmergencyServiceCategories();
method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
+ method @Nullable public android.os.Bundle getProprietaryCallExtras();
method public int getRestrictCause();
method public int getServiceType();
method public static int getVideoStateFromCallType(int);
@@ -9516,7 +9860,8 @@
field public static final int DIALSTRING_USSD = 2; // 0x2
field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
- field public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
+ field public static final String EXTRA_CALL_NETWORK_TYPE = "android.telephony.ims.extra.CALL_NETWORK_TYPE";
+ field @Deprecated public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
field public static final String EXTRA_CHILD_NUMBER = "ChildNum";
field public static final String EXTRA_CNA = "cna";
field public static final String EXTRA_CNAP = "cnap";
@@ -9548,8 +9893,8 @@
method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState);
- method public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
- method public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
+ method @Deprecated public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
+ method @Deprecated public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
method public void callSessionHeld(android.telephony.ims.ImsCallProfile);
method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo);
method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile);
@@ -9557,7 +9902,7 @@
method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo);
method public void callSessionInviteParticipantsRequestDelivered();
method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionMayHandover(int, int);
+ method @Deprecated public void callSessionMayHandover(int, int);
method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
@@ -9579,6 +9924,9 @@
method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile);
method public void callSessionUpdated(android.telephony.ims.ImsCallProfile);
method public void callSessionUssdMessageReceived(int, String);
+ method public void onHandover(int, int, @Nullable android.telephony.ims.ImsReasonInfo);
+ method public void onHandoverFailed(int, int, @NonNull android.telephony.ims.ImsReasonInfo);
+ method public void onMayHandover(int, int);
}
public final class ImsConferenceState implements android.os.Parcelable {
@@ -9610,10 +9958,6 @@
ctor public ImsException(@Nullable String);
ctor public ImsException(@Nullable String, int);
ctor public ImsException(@Nullable String, int, @Nullable Throwable);
- method public int getCode();
- field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1
- field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0
- field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2
}
public final class ImsExternalCallState implements android.os.Parcelable {
@@ -9635,26 +9979,20 @@
public class ImsManager {
method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
+ field public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
+ field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
+ field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
+ field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
}
public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
- method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTtyOverVolteEnabled();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled();
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
@@ -9664,16 +10002,6 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback);
- field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1
- field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0
- field public static final int WIFI_MODE_WIFI_PREFERRED = 2; // 0x2
- }
-
- public static class ImsMmTelManager.CapabilityCallback {
- ctor public ImsMmTelManager.CapabilityCallback();
- method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
}
@Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback {
@@ -9929,17 +10257,90 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
+ field public static final int KEY_1X_EPDG_TIMER_SEC = 64; // 0x40
+ field public static final int KEY_1X_THRESHOLD = 59; // 0x3b
+ field public static final int KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 50; // 0x32
+ field public static final int KEY_AMR_CODEC_MODE_SET_VALUES = 0; // 0x0
+ field public static final int KEY_AMR_DEFAULT_ENCODING_MODE = 53; // 0x35
+ field public static final int KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE = 49; // 0x31
+ field public static final int KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 48; // 0x30
+ field public static final int KEY_AMR_WB_CODEC_MODE_SET_VALUES = 1; // 0x1
+ field public static final int KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE = 47; // 0x2f
+ field public static final int KEY_DTMF_NB_PAYLOAD_TYPE = 52; // 0x34
+ field public static final int KEY_DTMF_WB_PAYLOAD_TYPE = 51; // 0x33
+ field public static final int KEY_EAB_PROVISIONING_STATUS = 25; // 0x19
+ field public static final int KEY_ENABLE_SILENT_REDIAL = 6; // 0x6
+ field public static final int KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS = 31; // 0x1f
+ field public static final int KEY_LTE_EPDG_TIMER_SEC = 62; // 0x3e
+ field public static final int KEY_LTE_THRESHOLD_1 = 56; // 0x38
+ field public static final int KEY_LTE_THRESHOLD_2 = 57; // 0x39
+ field public static final int KEY_LTE_THRESHOLD_3 = 58; // 0x3a
+ field public static final int KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC = 3; // 0x3
+ field public static final int KEY_MOBILE_DATA_ENABLED = 29; // 0x1d
+ field public static final int KEY_MULTIENDPOINT_ENABLED = 65; // 0x41
+ field public static final int KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC = 19; // 0x13
+ field public static final int KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC = 18; // 0x12
+ field public static final int KEY_RCS_CAPABILITIES_POLL_INTERVAL_SEC = 20; // 0x14
+ field public static final int KEY_RCS_CAPABILITY_DISCOVERY_ENABLED = 17; // 0x11
+ field public static final int KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC = 23; // 0x17
+ field public static final int KEY_RCS_MAX_NUM_ENTRIES_IN_RCL = 22; // 0x16
+ field public static final int KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS = 21; // 0x15
+ field public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16; // 0x10
+ field public static final int KEY_RCS_PUBLISH_TIMER_SEC = 15; // 0xf
+ field public static final int KEY_REGISTRATION_DOMAIN_NAME = 12; // 0xc
+ field public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33; // 0x21
+ field public static final int KEY_REGISTRATION_RETRY_MAX_TIME_SEC = 34; // 0x22
+ field public static final int KEY_RTP_SPEECH_END_PORT = 36; // 0x24
+ field public static final int KEY_RTP_SPEECH_START_PORT = 35; // 0x23
+ field public static final int KEY_RTT_ENABLED = 66; // 0x42
+ field public static final int KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS = 43; // 0x2b
+ field public static final int KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS = 44; // 0x2c
+ field public static final int KEY_SIP_INVITE_ACK_WAIT_TIME_MS = 38; // 0x26
+ field public static final int KEY_SIP_INVITE_CANCELLATION_TIMER_MS = 4; // 0x4
+ field public static final int KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS = 37; // 0x25
+ field public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS = 42; // 0x2a
+ field public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS = 39; // 0x27
+ field public static final int KEY_SIP_KEEP_ALIVE_ENABLED = 32; // 0x20
+ field public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS = 45; // 0x2d
+ field public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMIT_INTERVAL_MS = 40; // 0x28
+ field public static final int KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS = 46; // 0x2e
+ field public static final int KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS = 41; // 0x29
+ field public static final int KEY_SIP_SESSION_TIMER_SEC = 2; // 0x2
+ field public static final int KEY_SMS_FORMAT = 13; // 0xd
+ field public static final int KEY_SMS_OVER_IP_ENABLED = 14; // 0xe
+ field public static final int KEY_SMS_PUBLIC_SERVICE_IDENTITY = 54; // 0x36
+ field public static final int KEY_T1_TIMER_VALUE_MS = 7; // 0x7
+ field public static final int KEY_T2_TIMER_VALUE_MS = 8; // 0x8
+ field public static final int KEY_TF_TIMER_VALUE_MS = 9; // 0x9
+ field public static final int KEY_TRANSITION_TO_LTE_DELAY_MS = 5; // 0x5
+ field public static final int KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION = 24; // 0x18
+ field public static final int KEY_VIDEO_QUALITY = 55; // 0x37
+ field public static final int KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE = 28; // 0x1c
field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
+ field public static final int KEY_VOLTE_PROVISIONING_STATUS = 10; // 0xa
+ field public static final int KEY_VOLTE_USER_OPT_IN_STATUS = 30; // 0x1e
+ field public static final int KEY_VT_PROVISIONING_STATUS = 11; // 0xb
+ field public static final int KEY_WIFI_EPDG_TIMER_SEC = 63; // 0x3f
+ field public static final int KEY_WIFI_THRESHOLD_A = 60; // 0x3c
+ field public static final int KEY_WIFI_THRESHOLD_B = 61; // 0x3d
+ field public static final int PROVISIONING_RESULT_UNKNOWN = -1; // 0xffffffff
field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
+ field public static final int SMS_FORMAT_3GPP = 1; // 0x1
+ field public static final int SMS_FORMAT_3GPP2 = 0; // 0x0
field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
+ field public static final int VIDEO_QUALITY_HIGH = 1; // 0x1
+ field public static final int VIDEO_QUALITY_LOW = 0; // 0x0
}
public static class ProvisioningManager.Callback {
@@ -9948,22 +10349,52 @@
method public void onProvisioningStringChanged(int, @NonNull String);
}
- public interface RegistrationManager {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
- field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0
- field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2
- field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1
+ public final class RcsContactUceCapability implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getCapableExtensionTags();
+ method @NonNull public android.net.Uri getContactUri();
+ method @Nullable public android.net.Uri getServiceUri(int);
+ method public boolean isCapable(int);
+ method public boolean isCapable(@NonNull String);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CAPABILITY_CALL_COMPOSER = 4194304; // 0x400000
+ field public static final int CAPABILITY_CHAT_BOT = 67108864; // 0x4000000
+ field public static final int CAPABILITY_CHAT_BOT_ROLE = 134217728; // 0x8000000
+ field public static final int CAPABILITY_CHAT_SESSION = 2; // 0x2
+ field public static final int CAPABILITY_CHAT_SESSION_STORE_FORWARD = 4; // 0x4
+ field public static final int CAPABILITY_CHAT_STANDALONE = 1; // 0x1
+ field public static final int CAPABILITY_DISCOVERY_VIA_PRESENCE = 4096; // 0x1000
+ field public static final int CAPABILITY_FILE_TRANSFER = 8; // 0x8
+ field public static final int CAPABILITY_FILE_TRANSFER_HTTP = 64; // 0x40
+ field public static final int CAPABILITY_FILE_TRANSFER_SMS = 128; // 0x80
+ field public static final int CAPABILITY_FILE_TRANSFER_STORE_FORWARD = 32; // 0x20
+ field public static final int CAPABILITY_FILE_TRANSFER_THUMBNAIL = 16; // 0x10
+ field public static final int CAPABILITY_GEOLOCATION_PULL = 131072; // 0x20000
+ field public static final int CAPABILITY_GEOLOCATION_PULL_FILE_TRANSFER = 262144; // 0x40000
+ field public static final int CAPABILITY_GEOLOCATION_PUSH = 32768; // 0x8000
+ field public static final int CAPABILITY_GEOLOCATION_PUSH_SMS = 65536; // 0x10000
+ field public static final int CAPABILITY_IMAGE_SHARE = 256; // 0x100
+ field public static final int CAPABILITY_IP_VIDEO_CALL = 16384; // 0x4000
+ field public static final int CAPABILITY_IP_VOICE_CALL = 8192; // 0x2000
+ field public static final int CAPABILITY_PLUG_IN = 268435456; // 0x10000000
+ field public static final int CAPABILITY_POST_CALL = 8388608; // 0x800000
+ field public static final int CAPABILITY_RCS_VIDEO_CALL = 1048576; // 0x100000
+ field public static final int CAPABILITY_RCS_VIDEO_ONLY_CALL = 2097152; // 0x200000
+ field public static final int CAPABILITY_RCS_VOICE_CALL = 524288; // 0x80000
+ field public static final int CAPABILITY_SHARED_MAP = 16777216; // 0x1000000
+ field public static final int CAPABILITY_SHARED_SKETCH = 33554432; // 0x2000000
+ field public static final int CAPABILITY_SOCIAL_PRESENCE = 2048; // 0x800
+ field public static final int CAPABILITY_VIDEO_SHARE = 1024; // 0x400
+ field public static final int CAPABILITY_VIDEO_SHARE_DURING_CS_CALL = 512; // 0x200
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsContactUceCapability> CREATOR;
}
- public static class RegistrationManager.RegistrationCallback {
- ctor public RegistrationManager.RegistrationCallback();
- method public void onRegistered(int);
- method public void onRegistering(int);
- method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo);
- method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo);
+ public static class RcsContactUceCapability.Builder {
+ ctor public RcsContactUceCapability.Builder(@NonNull android.net.Uri);
+ method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(int, @NonNull android.net.Uri);
+ method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(int);
+ method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(@NonNull String);
+ method @NonNull public android.telephony.ims.RcsContactUceCapability build();
}
}
@@ -9989,6 +10420,7 @@
public abstract class ImsFeature {
ctor public ImsFeature();
method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public int getFeatureState();
method public final int getSlotIndex();
method public abstract void onFeatureReady();
method public abstract void onFeatureRemoved();
@@ -10027,7 +10459,7 @@
method public void onFeatureReady();
method public void onFeatureRemoved();
method public boolean queryCapabilityConfiguration(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
- method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
+ method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
method public void setUiTtyMode(int, @Nullable android.os.Message);
method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]);
field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
@@ -10043,10 +10475,6 @@
method public final void addCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
method public final boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
method public final void removeCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
- field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8
- field public static final int CAPABILITY_TYPE_UT = 4; // 0x4
- field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2
- field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1
}
@IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.MmTelCapabilities.MmTelCapability {
@@ -10137,6 +10565,7 @@
method public String getConfigString(int);
method public final void notifyProvisionedValueChanged(int, int);
method public final void notifyProvisionedValueChanged(int, String);
+ method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
method public int setConfig(int, int);
method public int setConfig(int, String);
field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
@@ -10235,6 +10664,17 @@
method public int updateClir(int);
method public int updateColp(boolean);
method public int updateColr(int);
+ field public static final int CALL_BARRING_ALL = 7; // 0x7
+ field public static final int CALL_BARRING_ALL_INCOMING = 1; // 0x1
+ field public static final int CALL_BARRING_ALL_OUTGOING = 2; // 0x2
+ field public static final int CALL_BARRING_ANONYMOUS_INCOMING = 6; // 0x6
+ field public static final int CALL_BARRING_INCOMING_ALL_SERVICES = 9; // 0x9
+ field public static final int CALL_BARRING_OUTGOING_ALL_SERVICES = 8; // 0x8
+ field public static final int CALL_BARRING_OUTGOING_INTL = 3; // 0x3
+ field public static final int CALL_BARRING_OUTGOING_INTL_EXCL_HOME = 4; // 0x4
+ field public static final int CALL_BARRING_SPECIFIC_INCOMING_CALLS = 10; // 0xa
+ field public static final int CALL_BLOCKING_INCOMING_WHEN_ROAMING = 5; // 0x5
+ field public static final int INVALID_RESULT = -1; // 0xffffffff
}
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 68da72f..b5915d5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -320,8 +320,10 @@
}
public final class NotificationChannel implements android.os.Parcelable {
+ method public boolean isBlockableSystem();
method public boolean isImportanceLockedByCriticalDeviceFunction();
method public boolean isImportanceLockedByOEM();
+ method public void setBlockableSystem(boolean);
method public void setImportanceLockedByCriticalDeviceFunction(boolean);
method public void setImportanceLockedByOEM(boolean);
}
@@ -352,6 +354,7 @@
public class StatusBarManager {
method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo();
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSetup(boolean);
+ method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSimNetworkLock(boolean);
}
public static final class StatusBarManager.DisableInfo {
@@ -650,6 +653,7 @@
method public void setContentCaptureOptions(@Nullable android.content.ContentCaptureOptions);
field public static final String BUGREPORT_SERVICE = "bugreport";
field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
+ field public static final String NETWORK_STACK_SERVICE = "network_stack";
field public static final String PERMISSION_SERVICE = "permission";
field public static final String ROLLBACK_SERVICE = "rollback";
field public static final String STATUS_BAR_SERVICE = "statusbar";
@@ -1349,12 +1353,40 @@
public class CaptivePortal implements android.os.Parcelable {
method public void logEvent(int, @NonNull String);
+ method public void reevaluateNetwork();
method public void useNetwork();
+ field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64
field public static final int APP_RETURN_DISMISSED = 0; // 0x0
field public static final int APP_RETURN_UNWANTED = 1; // 0x1
field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
}
+ public final class CaptivePortalData implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getByteLimit();
+ method public long getExpiryTimeMillis();
+ method public long getRefreshTimeMillis();
+ method @Nullable public android.net.Uri getUserPortalUrl();
+ method @Nullable public android.net.Uri getVenueInfoUrl();
+ method public boolean isCaptive();
+ method public boolean isSessionExtendable();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
+ }
+
+ public static class CaptivePortalData.Builder {
+ ctor public CaptivePortalData.Builder();
+ ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
+ method @NonNull public android.net.CaptivePortalData build();
+ method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
+ method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
+ method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
+ method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
+ method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
+ method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
+ method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
+ }
+
public class ConnectivityManager {
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
@@ -1385,6 +1417,8 @@
ctor public LinkProperties(@Nullable android.net.LinkProperties);
method public boolean addDnsServer(@NonNull java.net.InetAddress);
method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
+ method @Nullable public android.net.Uri getCaptivePortalApiUrl();
+ method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
method @Nullable public String getTcpBufferSizes();
method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
@@ -1395,9 +1429,12 @@
method public boolean isIpv6Provisioned();
method public boolean isProvisioned();
method public boolean isReachable(@NonNull java.net.InetAddress);
+ method @NonNull public android.net.LinkProperties makeSensitiveFieldsParcelingCopy();
method public boolean removeDnsServer(@NonNull java.net.InetAddress);
method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
method public boolean removeRoute(@NonNull android.net.RouteInfo);
+ method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
+ method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
method public void setPrivateDnsServerName(@Nullable String);
method public void setTcpBufferSizes(@Nullable String);
@@ -2355,6 +2392,7 @@
public final class Settings {
field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
+ field public static final String ACTION_TETHER_PROVISIONING_UI = "android.settings.TETHER_PROVISIONING_UI";
field public static final int RESET_MODE_PACKAGE_DEFAULTS = 1; // 0x1
}
@@ -2371,6 +2409,7 @@
field public static final String LOW_POWER_MODE_STICKY = "low_power_sticky";
field public static final String NOTIFICATION_BUBBLES = "notification_bubbles";
field public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
+ field public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
}
@@ -2884,8 +2923,6 @@
public final class AccessNetworkConstants {
field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff
- field public static final int TRANSPORT_TYPE_WLAN = 2; // 0x2
- field public static final int TRANSPORT_TYPE_WWAN = 1; // 0x1
}
public final class CallQuality implements android.os.Parcelable {
@@ -2948,34 +2985,18 @@
}
public final class NetworkRegistrationInfo implements android.os.Parcelable {
- method public int describeContents();
- method public int getAccessNetworkTechnology();
- method @NonNull public java.util.List<java.lang.Integer> getAvailableServices();
- method @Nullable public android.telephony.CellIdentity getCellIdentity();
method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
- method public int getDomain();
method public int getRegistrationState();
method public int getRejectCause();
method public int getRoamingType();
- method public int getTransportType();
method public boolean isEmergencyEnabled();
- method public boolean isRoaming();
method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationInfo> CREATOR;
- field public static final int DOMAIN_CS = 1; // 0x1
- field public static final int DOMAIN_PS = 2; // 0x2
field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3
field public static final int REGISTRATION_STATE_HOME = 1; // 0x1
field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0
field public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2; // 0x2
field public static final int REGISTRATION_STATE_ROAMING = 5; // 0x5
field public static final int REGISTRATION_STATE_UNKNOWN = 4; // 0x4
- field public static final int SERVICE_TYPE_DATA = 2; // 0x2
- field public static final int SERVICE_TYPE_EMERGENCY = 5; // 0x5
- field public static final int SERVICE_TYPE_SMS = 3; // 0x3
- field public static final int SERVICE_TYPE_UNKNOWN = 0; // 0x0
- field public static final int SERVICE_TYPE_VIDEO = 4; // 0x4
- field public static final int SERVICE_TYPE_VOICE = 1; // 0x1
}
public static final class NetworkRegistrationInfo.Builder {
@@ -3012,6 +3033,7 @@
public class ServiceState implements android.os.Parcelable {
method public void addNetworkRegistrationInfo(android.telephony.NetworkRegistrationInfo);
+ method public int getDataNetworkType();
method public void setCdmaSystemAndNetworkId(int, int);
method public void setCellBandwidths(int[]);
method public void setChannelNumber(int);
@@ -3042,14 +3064,17 @@
}
public class TelephonyManager {
+ method public int addDevicePolicyOverrideApn(@NonNull android.content.Context, @NonNull android.telephony.data.ApnSetting);
method public int checkCarrierPrivilegesForPackage(String);
method public int getCarrierIdListVersion();
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
+ method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
method public int getEmergencyNumberDbVersion();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNetworkCountryIso(int);
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
+ method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
@@ -3117,6 +3142,7 @@
method public int getEmergencyServiceCategories();
method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
+ method @Nullable public android.os.Bundle getProprietaryCallExtras();
method public int getRestrictCause();
method public int getServiceType();
method public static int getVideoStateFromCallType(int);
@@ -3160,7 +3186,8 @@
field public static final int DIALSTRING_USSD = 2; // 0x2
field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
- field public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
+ field public static final String EXTRA_CALL_NETWORK_TYPE = "android.telephony.ims.extra.CALL_NETWORK_TYPE";
+ field @Deprecated public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
field public static final String EXTRA_CHILD_NUMBER = "ChildNum";
field public static final String EXTRA_CNA = "cna";
field public static final String EXTRA_CNAP = "cnap";
@@ -3169,6 +3196,7 @@
field public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
field public static final String EXTRA_EMERGENCY_CALL = "e_call";
field public static final String EXTRA_IS_CALL_PULL = "CallPull";
+ field public static final String EXTRA_OEM_EXTRAS = "android.telephony.ims.extra.OEM_EXTRAS";
field public static final String EXTRA_OI = "oi";
field public static final String EXTRA_OIR = "oir";
field public static final String EXTRA_REMOTE_URI = "remote_uri";
@@ -3192,8 +3220,8 @@
method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState);
- method public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
- method public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
+ method @Deprecated public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
+ method @Deprecated public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
method public void callSessionHeld(android.telephony.ims.ImsCallProfile);
method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo);
method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile);
@@ -3201,7 +3229,7 @@
method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo);
method public void callSessionInviteParticipantsRequestDelivered();
method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionMayHandover(int, int);
+ method @Deprecated public void callSessionMayHandover(int, int);
method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
@@ -3223,6 +3251,9 @@
method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile);
method public void callSessionUpdated(android.telephony.ims.ImsCallProfile);
method public void callSessionUssdMessageReceived(int, String);
+ method public void onHandover(int, int, @Nullable android.telephony.ims.ImsReasonInfo);
+ method public void onHandoverFailed(int, int, @NonNull android.telephony.ims.ImsReasonInfo);
+ method public void onMayHandover(int, int);
}
public final class ImsConferenceState implements android.os.Parcelable {
@@ -3254,10 +3285,6 @@
ctor public ImsException(@Nullable String);
ctor public ImsException(@Nullable String, int);
ctor public ImsException(@Nullable String, int, @Nullable Throwable);
- method public int getCode();
- field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1
- field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0
- field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2
}
public final class ImsExternalCallState implements android.os.Parcelable {
@@ -3279,26 +3306,20 @@
public class ImsManager {
method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
+ field public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
+ field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
+ field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
+ field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
}
public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
- method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiModeSetting();
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiRoamingModeSetting();
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAdvancedCallingSettingEnabled();
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isTtyOverVolteEnabled();
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVoWiFiRoamingSettingEnabled();
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVoWiFiSettingEnabled();
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVtSettingEnabled();
method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
@@ -3308,16 +3329,6 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback);
- field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1
- field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0
- field public static final int WIFI_MODE_WIFI_PREFERRED = 2; // 0x2
- }
-
- public static class ImsMmTelManager.CapabilityCallback {
- ctor public ImsMmTelManager.CapabilityCallback();
- method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
}
@Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback {
@@ -3569,17 +3580,90 @@
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public int getProvisioningIntValue(int);
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public String getProvisioningStringValue(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
+ field public static final int KEY_1X_EPDG_TIMER_SEC = 64; // 0x40
+ field public static final int KEY_1X_THRESHOLD = 59; // 0x3b
+ field public static final int KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 50; // 0x32
+ field public static final int KEY_AMR_CODEC_MODE_SET_VALUES = 0; // 0x0
+ field public static final int KEY_AMR_DEFAULT_ENCODING_MODE = 53; // 0x35
+ field public static final int KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE = 49; // 0x31
+ field public static final int KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 48; // 0x30
+ field public static final int KEY_AMR_WB_CODEC_MODE_SET_VALUES = 1; // 0x1
+ field public static final int KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE = 47; // 0x2f
+ field public static final int KEY_DTMF_NB_PAYLOAD_TYPE = 52; // 0x34
+ field public static final int KEY_DTMF_WB_PAYLOAD_TYPE = 51; // 0x33
+ field public static final int KEY_EAB_PROVISIONING_STATUS = 25; // 0x19
+ field public static final int KEY_ENABLE_SILENT_REDIAL = 6; // 0x6
+ field public static final int KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS = 31; // 0x1f
+ field public static final int KEY_LTE_EPDG_TIMER_SEC = 62; // 0x3e
+ field public static final int KEY_LTE_THRESHOLD_1 = 56; // 0x38
+ field public static final int KEY_LTE_THRESHOLD_2 = 57; // 0x39
+ field public static final int KEY_LTE_THRESHOLD_3 = 58; // 0x3a
+ field public static final int KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC = 3; // 0x3
+ field public static final int KEY_MOBILE_DATA_ENABLED = 29; // 0x1d
+ field public static final int KEY_MULTIENDPOINT_ENABLED = 65; // 0x41
+ field public static final int KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC = 19; // 0x13
+ field public static final int KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC = 18; // 0x12
+ field public static final int KEY_RCS_CAPABILITIES_POLL_INTERVAL_SEC = 20; // 0x14
+ field public static final int KEY_RCS_CAPABILITY_DISCOVERY_ENABLED = 17; // 0x11
+ field public static final int KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC = 23; // 0x17
+ field public static final int KEY_RCS_MAX_NUM_ENTRIES_IN_RCL = 22; // 0x16
+ field public static final int KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS = 21; // 0x15
+ field public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16; // 0x10
+ field public static final int KEY_RCS_PUBLISH_TIMER_SEC = 15; // 0xf
+ field public static final int KEY_REGISTRATION_DOMAIN_NAME = 12; // 0xc
+ field public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33; // 0x21
+ field public static final int KEY_REGISTRATION_RETRY_MAX_TIME_SEC = 34; // 0x22
+ field public static final int KEY_RTP_SPEECH_END_PORT = 36; // 0x24
+ field public static final int KEY_RTP_SPEECH_START_PORT = 35; // 0x23
+ field public static final int KEY_RTT_ENABLED = 66; // 0x42
+ field public static final int KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS = 43; // 0x2b
+ field public static final int KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS = 44; // 0x2c
+ field public static final int KEY_SIP_INVITE_ACK_WAIT_TIME_MS = 38; // 0x26
+ field public static final int KEY_SIP_INVITE_CANCELLATION_TIMER_MS = 4; // 0x4
+ field public static final int KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS = 37; // 0x25
+ field public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS = 42; // 0x2a
+ field public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS = 39; // 0x27
+ field public static final int KEY_SIP_KEEP_ALIVE_ENABLED = 32; // 0x20
+ field public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS = 45; // 0x2d
+ field public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMIT_INTERVAL_MS = 40; // 0x28
+ field public static final int KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS = 46; // 0x2e
+ field public static final int KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS = 41; // 0x29
+ field public static final int KEY_SIP_SESSION_TIMER_SEC = 2; // 0x2
+ field public static final int KEY_SMS_FORMAT = 13; // 0xd
+ field public static final int KEY_SMS_OVER_IP_ENABLED = 14; // 0xe
+ field public static final int KEY_SMS_PUBLIC_SERVICE_IDENTITY = 54; // 0x36
+ field public static final int KEY_T1_TIMER_VALUE_MS = 7; // 0x7
+ field public static final int KEY_T2_TIMER_VALUE_MS = 8; // 0x8
+ field public static final int KEY_TF_TIMER_VALUE_MS = 9; // 0x9
+ field public static final int KEY_TRANSITION_TO_LTE_DELAY_MS = 5; // 0x5
+ field public static final int KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION = 24; // 0x18
+ field public static final int KEY_VIDEO_QUALITY = 55; // 0x37
+ field public static final int KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE = 28; // 0x1c
field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
+ field public static final int KEY_VOLTE_PROVISIONING_STATUS = 10; // 0xa
+ field public static final int KEY_VOLTE_USER_OPT_IN_STATUS = 30; // 0x1e
+ field public static final int KEY_VT_PROVISIONING_STATUS = 11; // 0xb
+ field public static final int KEY_WIFI_EPDG_TIMER_SEC = 63; // 0x3f
+ field public static final int KEY_WIFI_THRESHOLD_A = 60; // 0x3c
+ field public static final int KEY_WIFI_THRESHOLD_B = 61; // 0x3d
+ field public static final int PROVISIONING_RESULT_UNKNOWN = -1; // 0xffffffff
field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
+ field public static final int SMS_FORMAT_3GPP = 1; // 0x1
+ field public static final int SMS_FORMAT_3GPP2 = 0; // 0x0
field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
+ field public static final int VIDEO_QUALITY_HIGH = 1; // 0x1
+ field public static final int VIDEO_QUALITY_LOW = 0; // 0x0
}
public static class ProvisioningManager.Callback {
@@ -3588,24 +3672,6 @@
method public void onProvisioningStringChanged(int, @NonNull String);
}
- public interface RegistrationManager {
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
- field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0
- field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2
- field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1
- }
-
- public static class RegistrationManager.RegistrationCallback {
- ctor public RegistrationManager.RegistrationCallback();
- method public void onRegistered(int);
- method public void onRegistering(int);
- method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo);
- method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo);
- }
-
}
package android.telephony.ims.feature {
@@ -3629,6 +3695,7 @@
public abstract class ImsFeature {
ctor public ImsFeature();
method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public int getFeatureState();
method public final int getSlotIndex();
method public abstract void onFeatureReady();
method public abstract void onFeatureRemoved();
@@ -3667,7 +3734,7 @@
method public void onFeatureReady();
method public void onFeatureRemoved();
method public boolean queryCapabilityConfiguration(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
- method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
+ method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
method public void setUiTtyMode(int, @Nullable android.os.Message);
method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]);
field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
@@ -3683,10 +3750,6 @@
method public final void addCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
method public final boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
method public final void removeCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
- field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8
- field public static final int CAPABILITY_TYPE_UT = 4; // 0x4
- field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2
- field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1
}
@IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.MmTelCapabilities.MmTelCapability {
@@ -3777,6 +3840,7 @@
method public String getConfigString(int);
method public final void notifyProvisionedValueChanged(int, int);
method public final void notifyProvisionedValueChanged(int, String);
+ method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
method public int setConfig(int, int);
method public int setConfig(int, String);
field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
@@ -3875,6 +3939,17 @@
method public int updateClir(int);
method public int updateColp(boolean);
method public int updateColr(int);
+ field public static final int CALL_BARRING_ALL = 7; // 0x7
+ field public static final int CALL_BARRING_ALL_INCOMING = 1; // 0x1
+ field public static final int CALL_BARRING_ALL_OUTGOING = 2; // 0x2
+ field public static final int CALL_BARRING_ANONYMOUS_INCOMING = 6; // 0x6
+ field public static final int CALL_BARRING_INCOMING_ALL_SERVICES = 9; // 0x9
+ field public static final int CALL_BARRING_OUTGOING_ALL_SERVICES = 8; // 0x8
+ field public static final int CALL_BARRING_OUTGOING_INTL = 3; // 0x3
+ field public static final int CALL_BARRING_OUTGOING_INTL_EXCL_HOME = 4; // 0x4
+ field public static final int CALL_BARRING_SPECIFIC_INCOMING_CALLS = 10; // 0xa
+ field public static final int CALL_BLOCKING_INCOMING_WHEN_ROAMING = 5; // 0x5
+ field public static final int INVALID_RESULT = -1; // 0xffffffff
}
}
@@ -4059,138 +4134,10 @@
method public void writeRawZigZag64(long);
}
- public final class ProtoOutputStream extends android.util.proto.ProtoStream {
- ctor public ProtoOutputStream();
- ctor public ProtoOutputStream(int);
- ctor public ProtoOutputStream(java.io.OutputStream);
- ctor public ProtoOutputStream(java.io.FileDescriptor);
- method public static int checkFieldId(long, long);
- method public void dump(String);
- method public void end(long);
- method @Deprecated public void endObject(long);
- method @Deprecated public void endRepeatedObject(long);
- method public void flush();
- method public byte[] getBytes();
- method public int getRawSize();
- method public static long makeFieldId(int, long);
- method public long start(long);
- method @Deprecated public long startObject(long);
- method @Deprecated public long startRepeatedObject(long);
- method public void write(long, double);
- method public void write(long, float);
- method public void write(long, int);
- method public void write(long, long);
- method public void write(long, boolean);
- method public void write(long, String);
- method public void write(long, byte[]);
- method @Deprecated public void writeBool(long, boolean);
- method @Deprecated public void writeBytes(long, byte[]);
- method @Deprecated public void writeDouble(long, double);
- method @Deprecated public void writeEnum(long, int);
- method @Deprecated public void writeFixed32(long, int);
- method @Deprecated public void writeFixed64(long, long);
- method @Deprecated public void writeFloat(long, float);
- method @Deprecated public void writeInt32(long, int);
- method @Deprecated public void writeInt64(long, long);
- method @Deprecated public void writeObject(long, byte[]);
- method @Deprecated public void writePackedBool(long, boolean[]);
- method @Deprecated public void writePackedDouble(long, double[]);
- method @Deprecated public void writePackedEnum(long, int[]);
- method @Deprecated public void writePackedFixed32(long, int[]);
- method @Deprecated public void writePackedFixed64(long, long[]);
- method @Deprecated public void writePackedFloat(long, float[]);
- method @Deprecated public void writePackedInt32(long, int[]);
- method @Deprecated public void writePackedInt64(long, long[]);
- method @Deprecated public void writePackedSFixed32(long, int[]);
- method @Deprecated public void writePackedSFixed64(long, long[]);
- method @Deprecated public void writePackedSInt32(long, int[]);
- method @Deprecated public void writePackedSInt64(long, long[]);
- method @Deprecated public void writePackedUInt32(long, int[]);
- method @Deprecated public void writePackedUInt64(long, long[]);
- method @Deprecated public void writeRepeatedBool(long, boolean);
- method @Deprecated public void writeRepeatedBytes(long, byte[]);
- method @Deprecated public void writeRepeatedDouble(long, double);
- method @Deprecated public void writeRepeatedEnum(long, int);
- method @Deprecated public void writeRepeatedFixed32(long, int);
- method @Deprecated public void writeRepeatedFixed64(long, long);
- method @Deprecated public void writeRepeatedFloat(long, float);
- method @Deprecated public void writeRepeatedInt32(long, int);
- method @Deprecated public void writeRepeatedInt64(long, long);
- method @Deprecated public void writeRepeatedObject(long, byte[]);
- method @Deprecated public void writeRepeatedSFixed32(long, int);
- method @Deprecated public void writeRepeatedSFixed64(long, long);
- method @Deprecated public void writeRepeatedSInt32(long, int);
- method @Deprecated public void writeRepeatedSInt64(long, long);
- method @Deprecated public void writeRepeatedString(long, String);
- method @Deprecated public void writeRepeatedUInt32(long, int);
- method @Deprecated public void writeRepeatedUInt64(long, long);
- method @Deprecated public void writeSFixed32(long, int);
- method @Deprecated public void writeSFixed64(long, long);
- method @Deprecated public void writeSInt32(long, int);
- method @Deprecated public void writeSInt64(long, long);
- method @Deprecated public void writeString(long, String);
- method public void writeTag(int, int);
- method @Deprecated public void writeUInt32(long, int);
- method @Deprecated public void writeUInt64(long, long);
- }
-
public class ProtoParseException extends java.lang.RuntimeException {
ctor public ProtoParseException(String);
}
- public abstract class ProtoStream {
- ctor public ProtoStream();
- method public static int convertObjectIdToOrdinal(int);
- method public static int getDepthFromToken(long);
- method public static String getFieldCountString(long);
- method public static String getFieldIdString(long);
- method public static String getFieldTypeString(long);
- method public static int getObjectIdFromToken(long);
- method public static int getOffsetFromToken(long);
- method public static boolean getRepeatedFromToken(long);
- method public static int getTagSizeFromToken(long);
- method public static String getWireTypeString(int);
- method public static long makeFieldId(int, long);
- method public static long makeToken(int, boolean, int, int, int);
- method public static String token2String(long);
- field public static final long FIELD_COUNT_MASK = 16492674416640L; // 0xf0000000000L
- field public static final long FIELD_COUNT_PACKED = 5497558138880L; // 0x50000000000L
- field public static final long FIELD_COUNT_REPEATED = 2199023255552L; // 0x20000000000L
- field public static final int FIELD_COUNT_SHIFT = 40; // 0x28
- field public static final long FIELD_COUNT_SINGLE = 1099511627776L; // 0x10000000000L
- field public static final long FIELD_COUNT_UNKNOWN = 0L; // 0x0L
- field public static final int FIELD_ID_MASK = -8; // 0xfffffff8
- field public static final int FIELD_ID_SHIFT = 3; // 0x3
- field public static final long FIELD_TYPE_BOOL = 34359738368L; // 0x800000000L
- field public static final long FIELD_TYPE_BYTES = 51539607552L; // 0xc00000000L
- field public static final long FIELD_TYPE_DOUBLE = 4294967296L; // 0x100000000L
- field public static final long FIELD_TYPE_ENUM = 60129542144L; // 0xe00000000L
- field public static final long FIELD_TYPE_FIXED32 = 30064771072L; // 0x700000000L
- field public static final long FIELD_TYPE_FIXED64 = 25769803776L; // 0x600000000L
- field public static final long FIELD_TYPE_FLOAT = 8589934592L; // 0x200000000L
- field public static final long FIELD_TYPE_INT32 = 21474836480L; // 0x500000000L
- field public static final long FIELD_TYPE_INT64 = 12884901888L; // 0x300000000L
- field public static final long FIELD_TYPE_MASK = 1095216660480L; // 0xff00000000L
- field public static final long FIELD_TYPE_MESSAGE = 47244640256L; // 0xb00000000L
- field protected static final String[] FIELD_TYPE_NAMES;
- field public static final long FIELD_TYPE_SFIXED32 = 64424509440L; // 0xf00000000L
- field public static final long FIELD_TYPE_SFIXED64 = 68719476736L; // 0x1000000000L
- field public static final int FIELD_TYPE_SHIFT = 32; // 0x20
- field public static final long FIELD_TYPE_SINT32 = 73014444032L; // 0x1100000000L
- field public static final long FIELD_TYPE_SINT64 = 77309411328L; // 0x1200000000L
- field public static final long FIELD_TYPE_STRING = 38654705664L; // 0x900000000L
- field public static final long FIELD_TYPE_UINT32 = 55834574848L; // 0xd00000000L
- field public static final long FIELD_TYPE_UINT64 = 17179869184L; // 0x400000000L
- field public static final long FIELD_TYPE_UNKNOWN = 0L; // 0x0L
- field public static final int WIRE_TYPE_END_GROUP = 4; // 0x4
- field public static final int WIRE_TYPE_FIXED32 = 5; // 0x5
- field public static final int WIRE_TYPE_FIXED64 = 1; // 0x1
- field public static final int WIRE_TYPE_LENGTH_DELIMITED = 2; // 0x2
- field public static final int WIRE_TYPE_MASK = 7; // 0x7
- field public static final int WIRE_TYPE_START_GROUP = 3; // 0x3
- field public static final int WIRE_TYPE_VARINT = 0; // 0x0
- }
-
public class WireTypeMismatchException extends android.util.proto.ProtoParseException {
ctor public WireTypeMismatchException(String);
}
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index 6033655..c2ee6dc 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -103,6 +103,10 @@
runSetVirtualDisk();
} else if ("set-isolated-storage".equals(op)) {
runIsolatedStorage();
+ } else if ("start-checkpoint".equals(op)) {
+ runStartCheckpoint();
+ } else if ("supports-checkpoint".equals(op)) {
+ runSupportsCheckpoint();
} else {
throw new IllegalArgumentException();
}
@@ -313,6 +317,27 @@
}
}
+ private void runStartCheckpoint() throws RemoteException {
+ final String numRetriesString = nextArg();
+ if (numRetriesString == null) {
+ throw new IllegalArgumentException("Expected <num-retries>");
+ }
+ int numRetries;
+ try {
+ numRetries = Integer.parseInt(numRetriesString);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("<num-retries> must be a positive integer");
+ }
+ if (numRetries <= 0) {
+ throw new IllegalArgumentException("<num-retries> must be a positive integer");
+ }
+ mSm.startCheckpoint(numRetries);
+ }
+
+ private void runSupportsCheckpoint() throws RemoteException {
+ System.out.println(mSm.supportsCheckpoint());
+ }
+
private String nextArg() {
if (mNextArg >= mArgs.length) {
return null;
@@ -344,6 +369,10 @@
System.err.println("");
System.err.println(" sm set-isolated-storage [on|off|default]");
System.err.println("");
+ System.err.println(" sm start-checkpoint <num-retries>");
+ System.err.println("");
+ System.err.println(" sm supports-checkpoint");
+ System.err.println("");
return 1;
}
}
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 8944ded..da1a76f 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -138,11 +138,57 @@
"android.hardware.power@1.1",
"android.hardware.power.stats@1.0",
"libpackagelistparser",
+ "libstatsmetadata",
"libsysutils",
"libcutils",
],
}
+// ================
+// libstatsmetadata
+// ================
+
+genrule {
+ name: "atoms_info.h",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --atomsInfoHeader $(genDir)/atoms_info.h",
+ out: [
+ "atoms_info.h",
+ ],
+}
+
+genrule {
+ name: "atoms_info.cpp",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --atomsInfoCpp $(genDir)/atoms_info.cpp",
+ out: [
+ "atoms_info.cpp",
+ ],
+}
+
+cc_library_shared {
+ name: "libstatsmetadata",
+ host_supported: true,
+ generated_sources: [
+ "atoms_info.cpp",
+ ],
+ generated_headers: [
+ "atoms_info.h",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ export_generated_headers: [
+ "atoms_info.h",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libstatslog",
+ ],
+}
+
+
// =========
// statsd
// =========
diff --git a/cmds/statsd/OWNERS b/cmds/statsd/OWNERS
index 380e499..a61babf 100644
--- a/cmds/statsd/OWNERS
+++ b/cmds/statsd/OWNERS
@@ -1,7 +1,9 @@
-jianjin@google.com
+jeffreyhuang@google.com
joeo@google.com
jtnguyen@google.com
muhammadq@google.com
+ruchirr@google.com
singhtejinder@google.com
+tsaichristine@google.com
yaochen@google.com
yro@google.com
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index 13f5c8a..320a32a 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -18,8 +18,8 @@
#include "Log.h"
#include "FieldValue.h"
#include "HashableDimensionKey.h"
+#include "atoms_info.h"
#include "math.h"
-#include "statslog.h"
namespace android {
namespace os {
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index ff7416c..c9e026b 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -23,6 +23,7 @@
#include <frameworks/base/cmds/statsd/src/active_config_list.pb.h>
#include "StatsLogProcessor.h"
#include "android-base/stringprintf.h"
+#include "atoms_info.h"
#include "external/StatsPullerManager.h"
#include "guardrail/StatsdStats.h"
#include "metrics/CountMetricProducer.h"
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index c923156..d908388 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -50,6 +50,7 @@
import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
import "frameworks/base/core/proto/android/stats/location/location_enums.proto";
import "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.proto";
+import "frameworks/base/core/proto/android/stats/otaupdate/updateengine_enums.proto";
import "frameworks/base/core/proto/android/stats/storage/storage_enums.proto";
import "frameworks/base/core/proto/android/stats/style/style_enums.proto";
import "frameworks/base/core/proto/android/telecomm/enums.proto";
@@ -123,10 +124,10 @@
AppStartOccurred app_start_occurred = 48;
AppStartCanceled app_start_canceled = 49;
AppStartFullyDrawn app_start_fully_drawn = 50;
- LmkKillOccurred lmk_kill_occurred = 51;
+ LmkKillOccurred lmk_kill_occurred = 51 [(log_from_module) = "lmkd"];
PictureInPictureStateChanged picture_in_picture_state_changed = 52;
WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53;
- LmkStateChanged lmk_state_changed = 54;
+ LmkStateChanged lmk_state_changed = 54 [(log_from_module) = "lmkd"];
AppStartMemoryStateCaptured app_start_memory_state_captured = 55;
ShutdownSequenceReported shutdown_sequence_reported = 56;
BootSequenceReported boot_sequence_reported = 57;
@@ -322,6 +323,8 @@
ExclusionRectStateChanged exclusion_rect_state_changed = 223;
BackGesture back_gesture_reported_reported = 224;
+ UpdateEngineUpdateAttemptReported update_engine_update_attempt_reported = 225;
+ UpdateEngineSuccessfulUpdateReported update_engine_successful_update_reported = 226;
AppCompatibilityChangeReported app_compatibility_change_reported =
228 [(allow_from_any_uid) = true];
PerfettoUploaded perfetto_uploaded =
@@ -6894,3 +6897,70 @@
optional int64 trace_uuid_lsb = 2;
optional int64 trace_uuid_msb = 3;
}
+
+/**
+ * Information about an OTA update attempt by update_engine.
+ * Logged from platform/system/update_engine/metrics_reporter_android.cc
+ */
+message UpdateEngineUpdateAttemptReported {
+ // The number of attempts for the update engine to apply a given payload.
+ optional int32 attempt_number = 1;
+
+ optional android.stats.otaupdate.PayloadType payload_type = 2;
+
+ // The total time in minutes for the update engine to apply a given payload.
+ // The time is calculated by calling clock_gettime() / CLOCK_BOOTTIME; and
+ // it's increased when the system is sleeping.
+ optional int32 duration_boottime_in_minutes = 3;
+
+ // The total time in minutes for the update engine to apply a given payload.
+ // The time is calculated by calling clock_gettime() / CLOCK_MONOTONIC_RAW;
+ // and it's not increased when the system is sleeping.
+ optional int32 duration_monotonic_in_minutes = 4;
+
+ // The size of the payload in MiBs.
+ optional int32 payload_size_mib = 5;
+
+ // The attempt result reported by the update engine for an OTA update.
+ optional android.stats.otaupdate.AttemptResult attempt_result = 6;
+
+ // The error code reported by the update engine after an OTA update attempt
+ // on A/B devices.
+ optional android.stats.otaupdate.ErrorCode error_code = 7;
+
+ // The build fingerprint of the source system. The value is read from a
+ // system property when the device takes the update. e.g.
+ // Android/aosp_sailfish/sailfish:10/QP1A.190425.004/5507117:userdebug/test-keys
+ optional string source_fingerprint = 8;
+}
+
+/**
+ * Information about all the attempts the device make before finishing the
+ * successful update.
+ * Logged from platform/system/update_engine/metrics_reporter_android.cc
+ */
+message UpdateEngineSuccessfulUpdateReported {
+ // The number of attempts for the update engine to apply the payload for a
+ // successful update.
+ optional int32 attempt_count = 1;
+
+ optional android.stats.otaupdate.PayloadType payload_type = 2;
+
+ optional int32 payload_size_mib = 3;
+
+ // The total number of bytes downloaded by update_engine since the last
+ // successful update.
+ optional int32 total_bytes_downloaded_mib = 4;
+
+ // The ratio in percentage of the over-downloaded bytes compared to the
+ // total bytes needed to successfully install the update. e.g. 200 if we
+ // download 200MiB in total for a 100MiB package.
+ optional int32 download_overhead_percentage = 5;
+
+ // The total time in minutes for the update engine to apply the payload for a
+ // successful update.
+ optional int32 total_duration_minutes = 6;
+
+ // The number of reboot of the device during a successful update.
+ optional int32 reboot_count = 7;
+}
diff --git a/cmds/statsd/src/external/PowerStatsPuller.cpp b/cmds/statsd/src/external/PowerStatsPuller.cpp
index b142cac..dc69b78 100644
--- a/cmds/statsd/src/external/PowerStatsPuller.cpp
+++ b/cmds/statsd/src/external/PowerStatsPuller.cpp
@@ -22,6 +22,7 @@
#include <vector>
#include "PowerStatsPuller.h"
+#include "statslog.h"
#include "stats_log_util.h"
using android::hardware::hidl_vec;
diff --git a/cmds/statsd/src/external/puller_util.cpp b/cmds/statsd/src/external/puller_util.cpp
index 0b9b6ab..ccfd666 100644
--- a/cmds/statsd/src/external/puller_util.cpp
+++ b/cmds/statsd/src/external/puller_util.cpp
@@ -18,8 +18,8 @@
#include "Log.h"
#include "StatsPullerManager.h"
+#include "atoms_info.h"
#include "puller_util.h"
-#include "statslog.h"
namespace android {
namespace os {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 23d2ace..564b9ee 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -16,7 +16,7 @@
#pragma once
#include "config/ConfigKey.h"
-#include "statslog.h"
+#include "atoms_info.h"
#include <gtest/gtest_prod.h>
#include <log/log_time.h>
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 963205e..7b7d0ca 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -19,6 +19,7 @@
#include "statslog.h"
#include "CountMetricProducer.h"
+#include "atoms_info.h"
#include "condition/CombinationConditionTracker.h"
#include "condition/SimpleConditionTracker.h"
#include "guardrail/StatsdStats.h"
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 5cfb123..46442b5 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -32,8 +32,8 @@
#include "../metrics/GaugeMetricProducer.h"
#include "../metrics/ValueMetricProducer.h"
+#include "atoms_info.h"
#include "stats_util.h"
-#include "statslog.h"
#include <inttypes.h>
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index bfb84cf..a28165d 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -19,9 +19,9 @@
#include <android/util/ProtoOutputStream.h>
#include "FieldValue.h"
#include "HashableDimensionKey.h"
+#include "atoms_info.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "guardrail/StatsdStats.h"
-#include "statslog.h"
namespace android {
namespace os {
diff --git a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
index bdc52b0..3240918 100644
--- a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
+++ b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
@@ -24,6 +24,7 @@
#include <log/log.h>
#include "src/external/GpuStatsPuller.h"
+#include "statslog.h"
#ifdef __ANDROID__
diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp
index 266ea35..6730828 100644
--- a/cmds/statsd/tests/external/puller_util_test.cpp
+++ b/cmds/statsd/tests/external/puller_util_test.cpp
@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <stdio.h>
#include <vector>
+#include "statslog.h"
#include "../metrics/metrics_test_helper.h"
#ifdef __ANDROID__
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 2ac8409..773942c 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -14142,7 +14142,6 @@
HSPLandroid/telephony/ServiceState;->copyFrom(Landroid/telephony/ServiceState;)V
HSPLandroid/telephony/ServiceState;->describeContents()I
HSPLandroid/telephony/ServiceState;->equals(Ljava/lang/Object;)Z
-HSPLandroid/telephony/ServiceState;->fillInNotifierBundle(Landroid/os/Bundle;)V
HSPLandroid/telephony/ServiceState;->getCdmaDefaultRoamingIndicator()I
HSPLandroid/telephony/ServiceState;->getCdmaEriIconIndex()I
HSPLandroid/telephony/ServiceState;->getCdmaEriIconMode()I
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 90b80e7..842c3ef 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -21,8 +21,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
-import android.annotation.UnsupportedAppUsage;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index cf24b8e..8e1ac76 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -20,7 +20,7 @@
import android.annotation.IntDef;
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index c822d20..9a18880 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/accounts/AccountAndUser.java b/core/java/android/accounts/AccountAndUser.java
index b0d5343..fd67394 100644
--- a/core/java/android/accounts/AccountAndUser.java
+++ b/core/java/android/accounts/AccountAndUser.java
@@ -16,7 +16,7 @@
package android.accounts;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Used to store the Account and the UserId this account is associated with.
diff --git a/core/java/android/accounts/AccountAuthenticatorResponse.java b/core/java/android/accounts/AccountAuthenticatorResponse.java
index bb2e327..a2a5799 100644
--- a/core/java/android/accounts/AccountAuthenticatorResponse.java
+++ b/core/java/android/accounts/AccountAuthenticatorResponse.java
@@ -16,10 +16,10 @@
package android.accounts;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index c80be8e..7ecaaca 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -25,8 +25,8 @@
import android.annotation.Size;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
diff --git a/core/java/android/accounts/AuthenticatorDescription.java b/core/java/android/accounts/AuthenticatorDescription.java
index 5556394..b7bf11d 100644
--- a/core/java/android/accounts/AuthenticatorDescription.java
+++ b/core/java/android/accounts/AuthenticatorDescription.java
@@ -16,10 +16,10 @@
package android.accounts;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
/**
* A {@link Parcelable} value type that contains information about an account authenticator.
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 17d54d2..3cdd691 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -17,7 +17,7 @@
package android.animation;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ConstantState;
diff --git a/core/java/android/animation/ArgbEvaluator.java b/core/java/android/animation/ArgbEvaluator.java
index 5b69d18..9519ddd 100644
--- a/core/java/android/animation/ArgbEvaluator.java
+++ b/core/java/android/animation/ArgbEvaluator.java
@@ -16,7 +16,7 @@
package android.animation;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* This evaluator can be used to perform type interpolation between integer
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index c753710..21f0b6b 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -16,7 +16,7 @@
package android.animation;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 764e599..ca37e9b 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -19,7 +19,7 @@
import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Looper;
import android.os.Trace;
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index e573279..504364c 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -22,7 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index bf7b2f8..b6f61a2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -33,10 +33,10 @@
import android.annotation.StyleRes;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.VoiceInteractor.Request;
import android.app.admin.DevicePolicyManager;
import android.app.assist.AssistContent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.ContentResolver;
diff --git a/core/java/android/app/ActivityGroup.java b/core/java/android/app/ActivityGroup.java
index d4aa01b..cb06eea 100644
--- a/core/java/android/app/ActivityGroup.java
+++ b/core/java/android/app/ActivityGroup.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Bundle;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index e8e4085..726a619 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -27,7 +27,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 607ef18..b9eb957 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -15,7 +15,7 @@
*/
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.IBinder;
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 926044b..10bee40 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -25,7 +25,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 4ef554d..28d4c7f 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -19,7 +19,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4e8bee2..c4281f0 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -32,7 +32,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.backup.BackupAgent;
@@ -46,6 +45,7 @@
import android.app.servertransaction.PendingTransactionActions.StopInfo;
import android.app.servertransaction.TransactionExecutor;
import android.app.servertransaction.TransactionExecutorHelper;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 3a34b79..a0040ff 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -21,7 +21,7 @@
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index bfc216a..4c34737 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -21,7 +21,7 @@
import android.annotation.DrawableRes;
import android.annotation.StringRes;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.ResourceId;
diff --git a/core/java/android/app/AppGlobals.java b/core/java/android/app/AppGlobals.java
index 1f737b6..552d6e9 100644
--- a/core/java/android/app/AppGlobals.java
+++ b/core/java/android/app/AppGlobals.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.IPackageManager;
/**
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 33d83f9..6ff48ea 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -25,8 +25,8 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.usage.UsageStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
@@ -720,7 +720,18 @@
/** @hide Capture the device's display contents and/or audio */
@UnsupportedAppUsage
public static final int OP_PROJECT_MEDIA = 46;
- /** @hide Activate a VPN connection without user intervention. */
+
+ /**
+ * Start (without additional user intervention) a VPN connection, as used by {@link
+ * android.net.VpnService} along with as Platform VPN connections, as used by {@link
+ * android.net.VpnManager}
+ *
+ * <p>This appop is granted to apps that have already been given user consent to start
+ * VpnService based VPN connections. As this is a superset of OP_ACTIVATE_PLATFORM_VPN, this
+ * appop also allows the starting of Platform VPNs.
+ *
+ * @hide
+ */
@UnsupportedAppUsage
public static final int OP_ACTIVATE_VPN = 47;
/** @hide Access the WallpaperManagerAPI to write wallpapers. */
@@ -840,10 +851,21 @@
public static final int OP_READ_DEVICE_IDENTIFIERS = 89;
/** @hide Read location metadata from media */
public static final int OP_ACCESS_MEDIA_LOCATION = 90;
+ /**
+ * Start (without additional user intervention) a Platform VPN connection, as used by {@link
+ * android.net.VpnManager}
+ *
+ * <p>This appop is granted to apps that have already been given user consent to start Platform
+ * VPN connections. This appop is insufficient to start VpnService based VPNs (but the opposite
+ * is true).
+ *
+ * @hide
+ */
+ public static final int OP_ACTIVATE_PLATFORM_VPN = 91;
/** @hide */
@UnsupportedAppUsage
- public static final int _NUM_OP = 91;
+ public static final int _NUM_OP = 92;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1122,6 +1144,8 @@
public static final String OPSTR_ACCESS_ACCESSIBILITY = "android:access_accessibility";
/** @hide Read device identifiers */
public static final String OPSTR_READ_DEVICE_IDENTIFIERS = "android:read_device_identifiers";
+ /** @hide Start Platform VPN without user intervention */
+ public static final String OPSTR_ACTIVATE_PLATFORM_VPN = "android:activate_platform_vpn";
// Warning: If an permission is added here it also has to be added to
// com.android.packageinstaller.permission.utils.EventLogger
@@ -1285,6 +1309,7 @@
OP_ACCESS_ACCESSIBILITY, // ACCESS_ACCESSIBILITY
OP_READ_DEVICE_IDENTIFIERS, // READ_DEVICE_IDENTIFIERS
OP_ACCESS_MEDIA_LOCATION, // ACCESS_MEDIA_LOCATION
+ OP_ACTIVATE_PLATFORM_VPN, // ACTIVATE_PLATFORM_VPN
};
/**
@@ -1382,6 +1407,7 @@
OPSTR_ACCESS_ACCESSIBILITY,
OPSTR_READ_DEVICE_IDENTIFIERS,
OPSTR_ACCESS_MEDIA_LOCATION,
+ OPSTR_ACTIVATE_PLATFORM_VPN,
};
/**
@@ -1480,6 +1506,7 @@
"ACCESS_ACCESSIBILITY",
"READ_DEVICE_IDENTIFIERS",
"ACCESS_MEDIA_LOCATION",
+ "ACTIVATE_PLATFORM_VPN"
};
/**
@@ -1579,6 +1606,7 @@
null, // no permission for OP_ACCESS_ACCESSIBILITY
null, // no direct permission for OP_READ_DEVICE_IDENTIFIERS
Manifest.permission.ACCESS_MEDIA_LOCATION,
+ null, // no permission for OP_ACTIVATE_PLATFORM_VPN
};
/**
@@ -1678,6 +1706,7 @@
null, // ACCESS_ACCESSIBILITY
null, // READ_DEVICE_IDENTIFIERS
null, // ACCESS_MEDIA_LOCATION
+ null, // ACTIVATE_PLATFORM_VPN
};
/**
@@ -1776,6 +1805,7 @@
false, // ACCESS_ACCESSIBILITY
false, // READ_DEVICE_IDENTIFIERS
false, // ACCESS_MEDIA_LOCATION
+ false, // ACTIVATE_PLATFORM_VPN
};
/**
@@ -1873,6 +1903,7 @@
AppOpsManager.MODE_ALLOWED, // ACCESS_ACCESSIBILITY
AppOpsManager.MODE_ERRORED, // READ_DEVICE_IDENTIFIERS
AppOpsManager.MODE_ALLOWED, // ALLOW_MEDIA_LOCATION
+ AppOpsManager.MODE_IGNORED, // ACTIVATE_PLATFORM_VPN
};
/**
@@ -1974,6 +2005,7 @@
false, // ACCESS_ACCESSIBILITY
false, // READ_DEVICE_IDENTIFIERS
false, // ACCESS_MEDIA_LOCATION
+ false, // ACTIVATE_PLATFORM_VPN
};
/**
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 08cad04..996939e 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -16,7 +16,6 @@
package android.app;
-import android.annotation.NonNull;
import android.util.SparseIntArray;
import com.android.internal.util.function.QuadFunction;
@@ -77,38 +76,10 @@
public abstract void setDeviceAndProfileOwners(SparseIntArray owners);
/**
- * Sets the app-ops mode for a certain app-op and uid.
- *
- * <p>Similar as {@link AppOpsManager#setUidMode} but does not require the package manager to be
- * working. Hence this can be used very early during boot.
- *
- * <p>Only for internal callers. Does <u>not</u> verify that package name belongs to uid.
- *
- * @param code The op code to set.
- * @param uid The UID for which to set.
- * @param mode The new mode to set.
- */
- public abstract void setUidMode(int code, int uid, int mode);
-
- /**
* Set all {@link #setMode (package) modes} for this uid to the default value.
*
* @param code The app-op
* @param uid The uid
*/
public abstract void setAllPkgModesToDefault(int code, int uid);
-
- /**
- * Get the (raw) mode of an app-op.
- *
- * <p>Does <u>not</u> verify that package belongs to uid. The caller needs to do that.
- *
- * @param code The code of the op
- * @param uid The uid of the package the op belongs to
- * @param packageName The package the op belongs to
- *
- * @return The mode of the op
- */
- public abstract @AppOpsManager.Mode int checkOperationUnchecked(int code, int uid,
- @NonNull String packageName);
}
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index e12942f..941467f 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -19,7 +19,7 @@
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
import android.content.Context;
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 2e59b90..bac432e 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.SharedLibraryInfo;
import android.os.Build;
import android.os.GraphicsEnvironment;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 835769f..1158c44 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -20,9 +20,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.XmlRes;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/app/ContentProviderHolder.java b/core/java/android/app/ContentProviderHolder.java
index 004dca1a..3d74583 100644
--- a/core/java/android/app/ContentProviderHolder.java
+++ b/core/java/android/app/ContentProviderHolder.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProviderNative;
import android.content.IContentProvider;
import android.content.pm.ProviderInfo;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d317c34..ce4d312 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 9d82ffa..195c3e1 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 088c245..10525f7 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -24,7 +24,7 @@
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index bfc15c2..e4c84d7 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 77a7770..bcc08e9 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -22,7 +22,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentUris;
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 4f121aa..c6a0de4 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -21,7 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/app/FragmentController.java b/core/java/android/app/FragmentController.java
index 9316be7..f021f76 100644
--- a/core/java/android/app/FragmentController.java
+++ b/core/java/android/app/FragmentController.java
@@ -17,7 +17,7 @@
package android.app;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java
index 26b4a11..9e887b8 100644
--- a/core/java/android/app/FragmentHostCallback.java
+++ b/core/java/android/app/FragmentHostCallback.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 68daf44..904c473 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -22,7 +22,7 @@
import android.animation.AnimatorSet;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 9720e9f..cff6411 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 74fb99a..71b28fb 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -16,9 +16,9 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
-import android.annotation.WorkerThread;
import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 6677587..376acfa 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -23,8 +23,8 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.trust.ITrustManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 4efaaad..2a72d43 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 19575b2..1d27f8f 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -16,9 +16,9 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.servertransaction.PendingTransactionActions;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Binder;
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 25eb958..74bc9e2 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 412ef04c..cefec44 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -33,7 +33,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.LocusId;
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 69ec831..8ad2b36 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -15,13 +15,13 @@
*/
package android.app;
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.annotation.SystemApi.Client.MODULE_APPS;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.NotificationManager.Importance;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -319,9 +319,14 @@
}
/**
+ * Allows users to block notifications sent through this channel, if this channel belongs to
+ * a package that is signed with the system signature. If the channel does not belong to a
+ * package that is signed with the system signature, this method does nothing.
+ * @param blockableSystem if {@code true}, allows users to block notifications on this channel.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi(client = MODULE_APPS)
+ @TestApi
public void setBlockableSystem(boolean blockableSystem) {
mBlockableSystem = blockableSystem;
}
@@ -641,6 +646,7 @@
/**
* @hide
*/
+ @TestApi
public boolean isBlockableSystem() {
return mBlockableSystem;
}
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index a8ee414..afbd0b5 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -17,7 +17,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index c6aa4fd..e25558f 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -23,8 +23,8 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Notification.Builder;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/app/PackageDeleteObserver.java b/core/java/android/app/PackageDeleteObserver.java
index b7b0b19..d8803aa 100644
--- a/core/java/android/app/PackageDeleteObserver.java
+++ b/core/java/android/app/PackageDeleteObserver.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.IPackageDeleteObserver2;
diff --git a/core/java/android/app/PackageInstallObserver.java b/core/java/android/app/PackageInstallObserver.java
index 50031e0..0820367 100644
--- a/core/java/android/app/PackageInstallObserver.java
+++ b/core/java/android/app/PackageInstallObserver.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.IPackageInstallObserver2;
import android.os.Bundle;
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 6f7a060..6acbf21 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java
index 3ee5173..9d49d10 100644
--- a/core/java/android/app/PictureInPictureArgs.java
+++ b/core/java/android/app/PictureInPictureArgs.java
@@ -17,7 +17,7 @@
package android.app;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
index cb72d4d..f864fb5 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -20,24 +20,24 @@
import static android.content.Context.WINDOW_SERVICE;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Binder;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
-import android.os.Handler;
-import android.os.Message;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.TypedValue;
/**
* Base class for presentations.
diff --git a/core/java/android/app/ProgressDialog.java b/core/java/android/app/ProgressDialog.java
index 3193eb8..432fae5 100644
--- a/core/java/android/app/ProgressDialog.java
+++ b/core/java/android/app/ProgressDialog.java
@@ -16,9 +16,7 @@
package android.app;
-import com.android.internal.R;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
@@ -34,6 +32,8 @@
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.android.internal.R;
+
import java.text.NumberFormat;
/**
diff --git a/core/java/android/app/QueuedWork.java b/core/java/android/app/QueuedWork.java
index 7626539..82cc2c4 100644
--- a/core/java/android/app/QueuedWork.java
+++ b/core/java/android/app/QueuedWork.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index e9ae60f..7d742f7 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.ApkAssets;
diff --git a/core/java/android/app/ResultInfo.java b/core/java/android/app/ResultInfo.java
index 9ee0f31..979d3db 100644
--- a/core/java/android/app/ResultInfo.java
+++ b/core/java/android/app/ResultInfo.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 8493fb2..9fe894b 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -17,7 +17,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index acca6fc..93107ad 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -17,7 +17,7 @@
package android.app;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java
index a01cec7..83eb2ee 100644
--- a/core/java/android/app/SearchableInfo.java
+++ b/core/java/android/app/SearchableInfo.java
@@ -16,17 +16,14 @@
package android.app;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ProviderInfo;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.os.Parcel;
@@ -38,6 +35,9 @@
import android.util.Xml;
import android.view.inputmethod.EditorInfo;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.util.HashMap;
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 9b62e3b..dc8269f 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -21,7 +21,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.Context;
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 0f8976f..3783d1c 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -17,7 +17,7 @@
package android.app;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.SharedPreferences;
import android.os.FileUtils;
import android.os.Looper;
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 28413be..078e453 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -23,7 +23,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -153,6 +153,11 @@
*/
public static final int DEFAULT_SETUP_DISABLE2_FLAGS = DISABLE2_ROTATE_SUGGESTIONS;
+ /**
+ * disable flags to be applied when the device is sim-locked.
+ */
+ private static final int DEFAULT_SIM_LOCKED_DISABLED_FLAGS = DISABLE_EXPAND;
+
/** @hide */
public static final int NAVIGATION_HINT_BACK_ALT = 1 << 0;
/** @hide */
@@ -385,6 +390,30 @@
}
/**
+ * Enable or disable expansion of the status bar. When the device is SIM-locked, the status
+ * bar should not be expandable.
+ *
+ * @param disabled If {@code true}, the status bar will be set to non-expandable. If
+ * {@code false}, re-enables expansion of the status bar.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.STATUS_BAR)
+ public void setDisabledForSimNetworkLock(boolean disabled) {
+ try {
+ final int userId = Binder.getCallingUserHandle().getIdentifier();
+ final IStatusBarService svc = getService();
+ if (svc != null) {
+ svc.disableForUser(disabled ? DEFAULT_SIM_LOCKED_DISABLED_FLAGS : DISABLE_NONE,
+ mToken, mContext.getPackageName(), userId);
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Get this app's currently requested disabled components
*
* @return a new DisableInfo
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 82df702..88976e1 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -341,6 +341,14 @@
}
});
+ registerService(Context.NETWORK_STACK_SERVICE, IBinder.class,
+ new StaticServiceFetcher<IBinder>() {
+ @Override
+ public IBinder createService() {
+ return ServiceManager.getService(Context.NETWORK_STACK_SERVICE);
+ }
+ });
+
registerService(Context.TETHERING_SERVICE, TetheringManager.class,
new CachedServiceFetcher<TetheringManager>() {
@Override
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index de64db9..fe9c640 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Configuration;
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 5013040..6247187 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -16,8 +16,8 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager.TaskSnapshot;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Binder;
import android.os.IBinder;
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index 1b281d5..c529297 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -17,7 +17,7 @@
package android.app;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 3935628..20e31ca 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -24,7 +24,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index f251b3e..5f89e5c 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -19,6 +19,7 @@
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.graphics.Bitmap;
@@ -40,8 +41,6 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.IAccessibilityManager;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import libcore.io.IoUtils;
import java.io.FileInputStream;
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 8324787..6582d24 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -23,7 +23,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.os.RemoteException;
diff --git a/core/java/android/app/UserSwitchObserver.java b/core/java/android/app/UserSwitchObserver.java
index 2f8ee744b..6abc4f0 100644
--- a/core/java/android/app/UserSwitchObserver.java
+++ b/core/java/android/app/UserSwitchObserver.java
@@ -16,7 +16,7 @@
package android.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IRemoteCallback;
import android.os.RemoteException;
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index c74f8c3..08a210b 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -6,7 +6,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.os.RemoteException;
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 325a54b..102de95 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -26,7 +26,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 74237b4..f4240b1 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -26,6 +26,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Parcel;
@@ -35,8 +36,6 @@
import android.util.proto.WireTypeMismatchException;
import android.view.DisplayInfo;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.IOException;
/**
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 00903c4..3cc7f1e 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -17,7 +17,7 @@
package android.app.admin;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a17b2dd..79a2c90 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -33,13 +33,13 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.IServiceConnection;
import android.app.KeyguardManager;
import android.app.admin.SecurityLog.SecurityEvent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -6993,7 +6993,9 @@
* @param userHandle The user for whom to check the caller-id permission
* @hide
*/
- public boolean getBluetoothContactSharingDisabled(UserHandle userHandle) {
+ @SystemApi
+ @RequiresPermission(permission.INTERACT_ACROSS_USERS)
+ public boolean getBluetoothContactSharingDisabled(@NonNull UserHandle userHandle) {
if (mService != null) {
try {
return mService.getBluetoothContactSharingDisabledForUser(userHandle
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 9727621..f0b87a8 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/app/assist/AssistContent.java b/core/java/android/app/assist/AssistContent.java
index db6ae4f..e5316bc0 100644
--- a/core/java/android/app/assist/AssistContent.java
+++ b/core/java/android/app/assist/AssistContent.java
@@ -1,6 +1,6 @@
package android.app.assist;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
diff --git a/core/java/android/app/backup/BackupDataInput.java b/core/java/android/app/backup/BackupDataInput.java
index 2a98ca7..d1383c8 100644
--- a/core/java/android/app/backup/BackupDataInput.java
+++ b/core/java/android/app/backup/BackupDataInput.java
@@ -17,7 +17,7 @@
package android.app.backup;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.FileDescriptor;
import java.io.IOException;
diff --git a/core/java/android/app/backup/BackupDataInputStream.java b/core/java/android/app/backup/BackupDataInputStream.java
index 0888066..11a3d0c 100644
--- a/core/java/android/app/backup/BackupDataInputStream.java
+++ b/core/java/android/app/backup/BackupDataInputStream.java
@@ -16,9 +16,10 @@
package android.app.backup;
-import android.annotation.UnsupportedAppUsage;
-import java.io.InputStream;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.IOException;
+import java.io.InputStream;
/**
* Provides an {@link java.io.InputStream}-like interface for accessing an
diff --git a/core/java/android/app/backup/BackupDataOutput.java b/core/java/android/app/backup/BackupDataOutput.java
index 01961e7..fb161d4 100644
--- a/core/java/android/app/backup/BackupDataOutput.java
+++ b/core/java/android/app/backup/BackupDataOutput.java
@@ -17,7 +17,7 @@
package android.app.backup;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelFileDescriptor;
import java.io.FileDescriptor;
diff --git a/core/java/android/app/backup/BackupHelperDispatcher.java b/core/java/android/app/backup/BackupHelperDispatcher.java
index e9acdbf..6faa887 100644
--- a/core/java/android/app/backup/BackupHelperDispatcher.java
+++ b/core/java/android/app/backup/BackupHelperDispatcher.java
@@ -16,7 +16,7 @@
package android.app.backup;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelFileDescriptor;
import android.util.Log;
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 25caaaa..dc815b6 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -21,7 +21,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/app/backup/FileBackupHelperBase.java b/core/java/android/app/backup/FileBackupHelperBase.java
index 0caab98..5ad5d08 100644
--- a/core/java/android/app/backup/FileBackupHelperBase.java
+++ b/core/java/android/app/backup/FileBackupHelperBase.java
@@ -16,7 +16,7 @@
package android.app.backup;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.util.Log;
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 9a595b2..587e883 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -16,7 +16,7 @@
package android.app.backup;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.XmlResourceParser;
diff --git a/core/java/android/app/backup/FullBackupDataOutput.java b/core/java/android/app/backup/FullBackupDataOutput.java
index 0ce8653..d8fa0f5 100644
--- a/core/java/android/app/backup/FullBackupDataOutput.java
+++ b/core/java/android/app/backup/FullBackupDataOutput.java
@@ -1,6 +1,6 @@
package android.app.backup;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelFileDescriptor;
/**
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index a8f89df..72eea84 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -29,7 +29,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ComponentName;
import android.net.NetworkRequest;
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index dadfe3d..7635202 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -18,8 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
-import android.app.job.IJobCallback;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.net.Network;
import android.net.Uri;
diff --git a/core/java/android/app/job/JobWorkItem.java b/core/java/android/app/job/JobWorkItem.java
index a055ab4..237c507 100644
--- a/core/java/android/app/job/JobWorkItem.java
+++ b/core/java/android/app/job/JobWorkItem.java
@@ -19,7 +19,7 @@
import static android.app.job.JobInfo.NETWORK_BYTES_UNKNOWN;
import android.annotation.BytesLong;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index bb04a2e..b9cda6c 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -629,9 +629,12 @@
* {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}, as required by
* {@link android.provider.Telephony.Sms#getDefaultSmsPackage(Context)}
*
+ * @param userId The user ID to get the default SMS package for.
+ * @return the package name of the default SMS app, or {@code null} if not configured.
* @hide
*/
@Nullable
+ @SystemApi
public String getDefaultSmsPackage(@UserIdInt int userId) {
try {
return mService.getDefaultSmsPackage(userId);
diff --git a/core/java/android/app/servertransaction/ActivityResultItem.java b/core/java/android/app/servertransaction/ActivityResultItem.java
index 52ec3e6..4e743ca 100644
--- a/core/java/android/app/servertransaction/ActivityResultItem.java
+++ b/core/java/android/app/servertransaction/ActivityResultItem.java
@@ -18,9 +18,9 @@
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import android.annotation.UnsupportedAppUsage;
import android.app.ClientTransactionHandler;
import android.app.ResultInfo;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index b08e5973..4d2e9a5 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -17,9 +17,9 @@
package android.app.servertransaction;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ClientTransactionHandler;
import android.app.IApplicationThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 1236e0a..6d674ae 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -18,11 +18,11 @@
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.app.ProfilerInfo;
import android.app.ResultInfo;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo;
diff --git a/core/java/android/app/servertransaction/NewIntentItem.java b/core/java/android/app/servertransaction/NewIntentItem.java
index bb775fc..6a4996d 100644
--- a/core/java/android/app/servertransaction/NewIntentItem.java
+++ b/core/java/android/app/servertransaction/NewIntentItem.java
@@ -19,8 +19,8 @@
import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED;
-import android.annotation.UnsupportedAppUsage;
import android.app.ClientTransactionHandler;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/app/timedetector/ITimeDetectorService.aidl b/core/java/android/app/timedetector/ITimeDetectorService.aidl
index 9877fc7..de8f470 100644
--- a/core/java/android/app/timedetector/ITimeDetectorService.aidl
+++ b/core/java/android/app/timedetector/ITimeDetectorService.aidl
@@ -17,6 +17,7 @@
package android.app.timedetector;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
/**
@@ -35,4 +36,5 @@
interface ITimeDetectorService {
void suggestPhoneTime(in PhoneTimeSuggestion timeSuggestion);
void suggestManualTime(in ManualTimeSuggestion timeSuggestion);
+ void suggestNetworkTime(in NetworkTimeSuggestion timeSuggestion);
}
diff --git a/core/java/android/app/timedetector/ManualTimeSuggestion.java b/core/java/android/app/timedetector/ManualTimeSuggestion.java
index 55f92be..50de7385 100644
--- a/core/java/android/app/timedetector/ManualTimeSuggestion.java
+++ b/core/java/android/app/timedetector/ManualTimeSuggestion.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.TimestampedValue;
+import android.os.TimestampedValue;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/core/java/android/net/NetworkMisc.aidl b/core/java/android/app/timedetector/NetworkTimeSuggestion.aidl
similarity index 81%
copy from core/java/android/net/NetworkMisc.aidl
copy to core/java/android/app/timedetector/NetworkTimeSuggestion.aidl
index c65583f..731c907 100644
--- a/core/java/android/net/NetworkMisc.aidl
+++ b/core/java/android/app/timedetector/NetworkTimeSuggestion.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.net;
+package android.app.timedetector;
-parcelable NetworkMisc;
+parcelable NetworkTimeSuggestion;
diff --git a/core/java/android/app/timedetector/NetworkTimeSuggestion.java b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
new file mode 100644
index 0000000..17e9c5a
--- /dev/null
+++ b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timedetector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.TimestampedValue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A time signal from a network time source like NTP. The value consists of the number of
+ * milliseconds elapsed since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime
+ * clock when that number was established. The elapsed realtime clock is considered accurate but
+ * volatile, so time signals must not be persisted across device resets.
+ *
+ * @hide
+ */
+public final class NetworkTimeSuggestion implements Parcelable {
+
+ public static final @NonNull Creator<NetworkTimeSuggestion> CREATOR =
+ new Creator<NetworkTimeSuggestion>() {
+ public NetworkTimeSuggestion createFromParcel(Parcel in) {
+ return NetworkTimeSuggestion.createFromParcel(in);
+ }
+
+ public NetworkTimeSuggestion[] newArray(int size) {
+ return new NetworkTimeSuggestion[size];
+ }
+ };
+
+ @NonNull
+ private final TimestampedValue<Long> mUtcTime;
+ @Nullable
+ private ArrayList<String> mDebugInfo;
+
+ public NetworkTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
+ mUtcTime = Objects.requireNonNull(utcTime);
+ Objects.requireNonNull(utcTime.getValue());
+ }
+
+ private static NetworkTimeSuggestion createFromParcel(Parcel in) {
+ TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
+ NetworkTimeSuggestion suggestion = new NetworkTimeSuggestion(utcTime);
+ @SuppressWarnings("unchecked")
+ ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
+ suggestion.mDebugInfo = debugInfo;
+ return suggestion;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeParcelable(mUtcTime, 0);
+ dest.writeList(mDebugInfo);
+ }
+
+ @NonNull
+ public TimestampedValue<Long> getUtcTime() {
+ return mUtcTime;
+ }
+
+ @NonNull
+ public List<String> getDebugInfo() {
+ return mDebugInfo == null
+ ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+ }
+
+ /**
+ * Associates information with the instance that can be useful for debugging / logging. The
+ * information is present in {@link #toString()} but is not considered for
+ * {@link #equals(Object)} and {@link #hashCode()}.
+ */
+ public void addDebugInfo(String... debugInfos) {
+ if (mDebugInfo == null) {
+ mDebugInfo = new ArrayList<>();
+ }
+ mDebugInfo.addAll(Arrays.asList(debugInfos));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ NetworkTimeSuggestion that = (NetworkTimeSuggestion) o;
+ return Objects.equals(mUtcTime, that.mUtcTime);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mUtcTime);
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkTimeSuggestion{"
+ + "mUtcTime=" + mUtcTime
+ + ", mDebugInfo=" + mDebugInfo
+ + '}';
+ }
+}
diff --git a/core/java/android/app/timedetector/PhoneTimeSuggestion.java b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
index 4a89a12..bd649f8 100644
--- a/core/java/android/app/timedetector/PhoneTimeSuggestion.java
+++ b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
@@ -18,9 +18,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.TimestampedValue;
+import android.os.TimestampedValue;
import java.util.ArrayList;
import java.util.Collections;
@@ -28,17 +29,23 @@
import java.util.Objects;
/**
- * A time signal from a telephony source. The value can be {@code null} to indicate that the
- * telephony source has entered an "un-opinionated" state and any previously sent suggestions are
- * being withdrawn. When not {@code null}, the value consists of the number of milliseconds elapsed
- * since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime clock when that number
- * was established. The elapsed realtime clock is considered accurate but volatile, so time signals
- * must not be persisted across device resets.
+ * A time suggestion from an identified telephony source. e.g. from NITZ information from a specific
+ * radio.
+ *
+ * <p>The time value can be {@code null} to indicate that the telephony source has entered an
+ * "un-opinionated" state and any previous suggestions from the source are being withdrawn. When not
+ * {@code null}, the value consists of the number of milliseconds elapsed since 1/1/1970 00:00:00
+ * UTC and the time according to the elapsed realtime clock when that number was established. The
+ * elapsed realtime clock is considered accurate but volatile, so time suggestions must not be
+ * persisted across device resets.
*
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class PhoneTimeSuggestion implements Parcelable {
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final @NonNull Parcelable.Creator<PhoneTimeSuggestion> CREATOR =
new Parcelable.Creator<PhoneTimeSuggestion>() {
public PhoneTimeSuggestion createFromParcel(Parcel in) {
@@ -85,15 +92,27 @@
dest.writeList(mDebugInfo);
}
+ /**
+ * Returns an identifier for the source of this suggestion. When a device has several "phones",
+ * i.e. sim slots or equivalent, it is used to identify which one.
+ */
public int getPhoneId() {
return mPhoneId;
}
+ /**
+ * Returns the suggestion. {@code null} means that the caller is no longer sure what time it
+ * is.
+ */
@Nullable
public TimestampedValue<Long> getUtcTime() {
return mUtcTime;
}
+ /**
+ * Returns debug metadata for the suggestion. The information is present in {@link #toString()}
+ * but is not considered for {@link #equals(Object)} and {@link #hashCode()}.
+ */
@NonNull
public List<String> getDebugInfo() {
return mDebugInfo == null
@@ -105,7 +124,7 @@
* information is present in {@link #toString()} but is not considered for
* {@link #equals(Object)} and {@link #hashCode()}.
*/
- public void addDebugInfo(String debugInfo) {
+ public void addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
mDebugInfo = new ArrayList<>();
}
@@ -156,16 +175,19 @@
*
* @hide
*/
- public static class Builder {
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static final class Builder {
private final int mPhoneId;
- private TimestampedValue<Long> mUtcTime;
- private List<String> mDebugInfo;
+ @Nullable private TimestampedValue<Long> mUtcTime;
+ @Nullable private List<String> mDebugInfo;
+ /** Creates a builder with the specified {@code phoneId}. */
public Builder(int phoneId) {
mPhoneId = phoneId;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder setUtcTime(@Nullable TimestampedValue<Long> utcTime) {
if (utcTime != null) {
// utcTime can be null, but the value it holds cannot.
@@ -177,6 +199,7 @@
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
mDebugInfo = new ArrayList<>();
@@ -186,6 +209,7 @@
}
/** Returns the {@link PhoneTimeSuggestion}. */
+ @NonNull
public PhoneTimeSuggestion build() {
return new PhoneTimeSuggestion(this);
}
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 48d5cd2..7c29f01 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -18,19 +18,23 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.SystemClock;
+import android.os.TimestampedValue;
import android.util.Log;
-import android.util.TimestampedValue;
/**
* The interface through which system components can send signals to the TimeDetectorService.
+ *
+ * <p>This class is marked non-final for mockito.
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@SystemService(Context.TIME_DETECTOR_SERVICE)
public class TimeDetector {
private static final String TAG = "timedetector.TimeDetector";
@@ -38,6 +42,7 @@
private final ITimeDetectorService mITimeDetectorService;
+ /** @hide */
public TimeDetector() throws ServiceNotFoundException {
mITimeDetectorService = ITimeDetectorService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TIME_DETECTOR_SERVICE));
@@ -48,7 +53,7 @@
* signal if better signals are available such as those that come from more reliable sources or
* were determined more recently.
*/
- @RequiresPermission(android.Manifest.permission.SET_TIME)
+ @RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE)
public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
if (DEBUG) {
Log.d(TAG, "suggestPhoneTime called: " + timeSuggestion);
@@ -62,8 +67,10 @@
/**
* Suggests the user's manually entered current time to the detector.
+ *
+ * @hide
*/
- @RequiresPermission(android.Manifest.permission.SET_TIME)
+ @RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE)
public void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion) {
if (DEBUG) {
Log.d(TAG, "suggestManualTime called: " + timeSuggestion);
@@ -77,6 +84,8 @@
/**
* A shared utility method to create a {@link ManualTimeSuggestion}.
+ *
+ * @hide
*/
public static ManualTimeSuggestion createManualTimeSuggestion(long when, String why) {
TimestampedValue<Long> utcTime =
@@ -85,4 +94,21 @@
manualTimeSuggestion.addDebugInfo(why);
return manualTimeSuggestion;
}
+
+ /**
+ * Suggests the time according to a network time source like NTP.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.SET_TIME)
+ public void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion) {
+ if (DEBUG) {
+ Log.d(TAG, "suggestNetworkTime called: " + timeSuggestion);
+ }
+ try {
+ mITimeDetectorService.suggestNetworkTime(timeSuggestion);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
index e8162488..d71ffcb 100644
--- a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
+++ b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,12 +31,27 @@
import java.util.Objects;
/**
- * A suggested time zone from a Phone-based signal, e.g. from MCC and NITZ information.
+ * A time zone suggestion from an identified telephony source, e.g. from MCC and NITZ information
+ * associated with a specific radio.
+ *
+ * <p>The time zone ID can be {@code null} to indicate that the telephony source has entered an
+ * "un-opinionated" state and any previous suggestions from that source are being withdrawn.
+ * When not {@code null}, the value consists of a suggested time zone ID and metadata that can be
+ * used to judge quality / certainty of the suggestion.
+ *
+ * <p>{@code matchType} must be set to {@link #MATCH_TYPE_NA} when {@code zoneId} is {@code null},
+ * and one of the other {@code MATCH_TYPE_} values when it is not {@code null}.
+ *
+ * <p>{@code quality} must be set to {@link #QUALITY_NA} when {@code zoneId} is {@code null},
+ * and one of the other {@code QUALITY_} values when it is not {@code null}.
*
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class PhoneTimeZoneSuggestion implements Parcelable {
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
public static final Creator<PhoneTimeZoneSuggestion> CREATOR =
new Creator<PhoneTimeZoneSuggestion>() {
@@ -58,6 +74,7 @@
return new Builder(phoneId).addDebugInfo(debugInfo).build();
}
+ /** @hide */
@IntDef({ MATCH_TYPE_NA, MATCH_TYPE_NETWORK_COUNTRY_ONLY, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET,
MATCH_TYPE_EMULATOR_ZONE_ID, MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY })
@Retention(RetentionPolicy.SOURCE)
@@ -90,6 +107,7 @@
*/
public static final int MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY = 5;
+ /** @hide */
@IntDef({ QUALITY_NA, QUALITY_SINGLE_ZONE, QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET,
QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS })
@Retention(RetentionPolicy.SOURCE)
@@ -115,7 +133,7 @@
/**
* The ID of the phone this suggestion is associated with. For multiple-sim devices this
- * helps to establish origin so filtering / stickiness can be implemented.
+ * helps to establish source so filtering / stickiness can be implemented.
*/
private final int mPhoneId;
@@ -123,6 +141,7 @@
* The suggestion. {@code null} means there is no current suggestion and any previous suggestion
* should be forgotten.
*/
+ @Nullable
private final String mZoneId;
/**
@@ -139,9 +158,10 @@
private final int mQuality;
/**
- * Free-form debug information about how the signal was derived. Used for debug only,
+ * Free-form debug information about how the suggestion was derived. Used for debug only,
* intentionally not used in equals(), etc.
*/
+ @Nullable
private List<String> mDebugInfo;
private PhoneTimeZoneSuggestion(Builder builder) {
@@ -182,25 +202,47 @@
return 0;
}
+ /**
+ * Returns an identifier for the source of this suggestion. When a device has several "phones",
+ * i.e. sim slots or equivalent, it is used to identify which one.
+ */
public int getPhoneId() {
return mPhoneId;
}
+ /**
+ * Returns the suggested time zone Olson ID, e.g. "America/Los_Angeles". {@code null} means that
+ * the caller is no longer sure what the current time zone is. See
+ * {@link PhoneTimeZoneSuggestion} for the associated {@code matchType} / {@code quality} rules.
+ */
@Nullable
public String getZoneId() {
return mZoneId;
}
+ /**
+ * Returns information about how the suggestion was determined which could be used to rank
+ * suggestions when several are available from different sources. See
+ * {@link PhoneTimeZoneSuggestion} for the associated rules.
+ */
@MatchType
public int getMatchType() {
return mMatchType;
}
+ /**
+ * Returns information about the likelihood of the suggested zone being correct. See
+ * {@link PhoneTimeZoneSuggestion} for the associated rules.
+ */
@Quality
public int getQuality() {
return mQuality;
}
+ /**
+ * Returns debug metadata for the suggestion. The information is present in {@link #toString()}
+ * but is not considered for {@link #equals(Object)} and {@link #hashCode()}.
+ */
@NonNull
public List<String> getDebugInfo() {
return mDebugInfo == null
@@ -267,36 +309,43 @@
*
* @hide
*/
- public static class Builder {
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static final class Builder {
private final int mPhoneId;
- private String mZoneId;
+ @Nullable private String mZoneId;
@MatchType private int mMatchType;
@Quality private int mQuality;
- private List<String> mDebugInfo;
+ @Nullable private List<String> mDebugInfo;
public Builder(int phoneId) {
mPhoneId = phoneId;
}
- /** Returns the builder for call chaining. */
- public Builder setZoneId(String zoneId) {
+ /**
+ * Returns the builder for call chaining.
+ */
+ @NonNull
+ public Builder setZoneId(@Nullable String zoneId) {
mZoneId = zoneId;
return this;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder setMatchType(@MatchType int matchType) {
mMatchType = matchType;
return this;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder setQuality(@Quality int quality) {
mQuality = quality;
return this;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
mDebugInfo = new ArrayList<>();
@@ -333,6 +382,7 @@
}
/** Returns the {@link PhoneTimeZoneSuggestion}. */
+ @NonNull
public PhoneTimeZoneSuggestion build() {
validate();
return new PhoneTimeZoneSuggestion(this);
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java
index 387a36b..5b5f311 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetector.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
@@ -28,8 +29,10 @@
/**
* The interface through which system components can send signals to the TimeZoneDetectorService.
*
+ * <p>This class is non-final for mockito.
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@SystemService(Context.TIME_ZONE_DETECTOR_SERVICE)
public class TimeZoneDetector {
private static final String TAG = "timezonedetector.TimeZoneDetector";
@@ -37,6 +40,7 @@
private final ITimeZoneDetectorService mITimeZoneDetectorService;
+ /** @hide */
public TimeZoneDetector() throws ServiceNotFoundException {
mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE));
@@ -46,8 +50,11 @@
* Suggests the current time zone, determined using telephony signals, to the detector. The
* detector may ignore the signal based on system settings, whether better information is
* available, and so on.
+ *
+ * @hide
*/
- @RequiresPermission(android.Manifest.permission.SET_TIME_ZONE)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE)
public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) {
if (DEBUG) {
Log.d(TAG, "suggestPhoneTimeZone called: " + timeZoneSuggestion);
@@ -62,8 +69,10 @@
/**
* Suggests the current time zone, determined for the user's manually information, to the
* detector. The detector may ignore the signal based on system settings.
+ *
+ * @hide
*/
- @RequiresPermission(android.Manifest.permission.SET_TIME_ZONE)
+ @RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE)
public void suggestManualTimeZone(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion) {
if (DEBUG) {
Log.d(TAG, "suggestManualTimeZone called: " + timeZoneSuggestion);
@@ -77,6 +86,8 @@
/**
* A shared utility method to create a {@link ManualTimeZoneSuggestion}.
+ *
+ * @hide
*/
public static ManualTimeZoneSuggestion createManualTimeZoneSuggestion(String tzId, String why) {
ManualTimeZoneSuggestion suggestion = new ManualTimeZoneSuggestion(tzId);
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 27abdcf..65b2775 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -19,7 +19,7 @@
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Handler;
diff --git a/core/java/android/app/usage/ConfigurationStats.java b/core/java/android/app/usage/ConfigurationStats.java
index da3b769..8a7107d 100644
--- a/core/java/android/app/usage/ConfigurationStats.java
+++ b/core/java/android/app/usage/ConfigurationStats.java
@@ -15,7 +15,7 @@
*/
package android.app.usage;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 6bade90..9c4a8f4 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -16,19 +16,23 @@
package android.app.usage;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.usage.NetworkStats.Bucket;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DataUsageRequest;
import android.net.INetworkStatsService;
import android.net.NetworkIdentity;
import android.net.NetworkTemplate;
+import android.net.netstats.provider.AbstractNetworkStatsProvider;
+import android.net.netstats.provider.NetworkStatsProviderCallback;
+import android.net.netstats.provider.NetworkStatsProviderWrapper;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
@@ -42,6 +46,8 @@
import com.android.internal.annotations.VisibleForTesting;
+import java.util.Objects;
+
/**
* Provides access to network usage history and statistics. Usage data is collected in
* discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
@@ -418,7 +424,7 @@
/** @hide */
public void registerUsageCallback(NetworkTemplate template, int networkType,
long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
- checkNotNull(callback, "UsageCallback cannot be null");
+ Objects.requireNonNull(callback, "UsageCallback cannot be null");
final Looper looper;
if (handler == null) {
@@ -519,6 +525,34 @@
private DataUsageRequest request;
}
+ /**
+ * Registers a custom provider of {@link android.net.NetworkStats} to combine the network
+ * statistics that cannot be seen by the kernel to system. To unregister, invoke
+ * {@link NetworkStatsProviderCallback#unregister()}.
+ *
+ * @param tag a human readable identifier of the custom network stats provider.
+ * @param provider a custom implementation of {@link AbstractNetworkStatsProvider} that needs to
+ * be registered to the system.
+ * @return a {@link NetworkStatsProviderCallback}, which can be used to report events to the
+ * system.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
+ @NonNull public NetworkStatsProviderCallback registerNetworkStatsProvider(
+ @NonNull String tag,
+ @NonNull AbstractNetworkStatsProvider provider) {
+ try {
+ final NetworkStatsProviderWrapper wrapper = new NetworkStatsProviderWrapper(provider);
+ return new NetworkStatsProviderCallback(
+ mService.registerNetworkStatsProvider(tag, wrapper));
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ // Unreachable code, but compiler doesn't know about it.
+ return null;
+ }
+
private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
final NetworkTemplate template;
switch (networkType) {
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 84c6855..c646fc6 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 2c021cc..3550ebd 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -29,7 +29,7 @@
import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 92e1b30..102a08d17 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -23,9 +23,9 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.Build;
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index f003d4b..f61d35b 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.IntentSender;
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 85f0e23..09d56ec 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -16,9 +16,9 @@
package android.appwidget;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.ActivityOptions;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index dbc1c19..6dea1c6 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -23,9 +23,9 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.IServiceConnection;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 2faa900..130a20d 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -18,8 +18,8 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 64df0e8..d8c653c6 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -24,7 +24,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.Build;
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index c6957e1..8993de0 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -21,7 +21,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 291d1d9..bd0a39c 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -25,7 +25,6 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.bluetooth.BluetoothProfile.ConnectionPolicy;
import android.bluetooth.le.BluetoothLeAdvertiser;
@@ -36,6 +35,7 @@
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.BatteryStats;
import android.os.Binder;
@@ -1222,6 +1222,7 @@
if (mService != null) {
return mService.factoryReset();
}
+ Log.e(TAG, "factoryReset(): IBluetooth Service is null");
SystemProperties.set("persist.bluetooth.factoryreset", "true");
} catch (RemoteException e) {
Log.e(TAG, "", e);
@@ -1239,7 +1240,7 @@
*/
@UnsupportedAppUsage
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public @NonNull ParcelUuid[] getUuids() {
+ public @Nullable ParcelUuid[] getUuids() {
if (getState() != STATE_ON) {
return null;
}
@@ -2670,6 +2671,9 @@
} else if (profile == BluetoothProfile.PAN) {
BluetoothPan pan = new BluetoothPan(context, listener);
return true;
+ } else if (profile == BluetoothProfile.PBAP) {
+ BluetoothPbap pbap = new BluetoothPbap(context, listener);
+ return true;
} else if (profile == BluetoothProfile.HEALTH) {
Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated");
return false;
@@ -2742,6 +2746,10 @@
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();
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index 260e2fb..905b0cee 100755
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -17,7 +17,7 @@
package android.bluetooth;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index 08d0797..93e76fa 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 323c7d1..9fe4dd6 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -24,7 +24,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Handler;
import android.os.Parcel;
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index d616b8f..f877f04 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,7 +16,7 @@
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Handler;
import android.os.ParcelUuid;
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index edacf3e..7066f47 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -15,7 +15,7 @@
*/
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index 0783cd2..7cc2d6b 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -16,7 +16,7 @@
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index c20faf9..13d6d70 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -15,7 +15,7 @@
*/
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 0955b10..1ba2bb5 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -23,7 +23,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.os.Binder;
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 7ee29ff..6de1ffb 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -19,7 +19,7 @@
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
index 7165dd5..d1a096e 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
@@ -16,7 +16,7 @@
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index a65162a..38498bc 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -23,7 +23,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
index e9b0be2..a923be6 100644
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -16,8 +16,12 @@
package android.bluetooth;
+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.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -36,6 +40,7 @@
*/
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.
@@ -682,4 +687,62 @@
return result;
}
+
+ /**
+ * 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
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+ @ConnectionPolicy int connectionPolicy) {
+ log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
+ try {
+ final IBluetoothHidDevice 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);
+ }
+ 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;
+ }
+ }
+
+ 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/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index 8f5cdf0..c1233b8 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -17,9 +17,12 @@
package android.bluetooth;
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.SuppressLint;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Binder;
@@ -43,6 +46,7 @@
*
* @hide
*/
+@SystemApi
public final class BluetoothHidHost implements BluetoothProfile {
private static final String TAG = "BluetoothHidHost";
private static final boolean DBG = true;
@@ -66,6 +70,7 @@
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
* receive.
*/
+ @SuppressLint("ActionValue")
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
@@ -325,7 +330,7 @@
* {@inheritDoc}
*/
@Override
- public List<BluetoothDevice> getConnectedDevices() {
+ public @NonNull List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothHidHost service = getService();
if (service != null && isEnabled()) {
@@ -342,6 +347,8 @@
/**
* {@inheritDoc}
+ *
+ * @hide
*/
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
@@ -363,7 +370,7 @@
* {@inheritDoc}
*/
@Override
- public int getConnectionState(BluetoothDevice device) {
+ public int getConnectionState(@Nullable BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -409,7 +416,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
- public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+ public boolean setConnectionPolicy(@Nullable BluetoothDevice device, int connectionPolicy) {
if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -457,7 +464,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public int getConnectionPolicy(BluetoothDevice device) {
+ public int getConnectionPolicy(@Nullable BluetoothDevice device) {
if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 979dfd4..4674706 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -17,9 +17,12 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -35,21 +38,35 @@
*
* @hide
*/
+@SystemApi
public final class BluetoothMap implements BluetoothProfile {
private static final String TAG = "BluetoothMap";
private static final boolean DBG = true;
private static final boolean VDBG = false;
+ /** @hide */
+ @SuppressLint("ActionValue")
+ @SystemApi
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 */
+ /**
+ * 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. */
+ /**
+ * Connection canceled before completion.
+ *
+ * @hide
+ */
public static final int RESULT_CANCELED = 2;
private BluetoothAdapter mAdapter;
@@ -71,6 +88,7 @@
mProfileConnector.connect(context, listener);
}
+ @SuppressLint("GenericException")
protected void finalize() throws Throwable {
try {
close();
@@ -84,6 +102,8 @@
* Other public functions of BluetoothMap will return default error
* results once close() has been called. Multiple invocations of close()
* are ok.
+ *
+ * @hide
*/
public synchronized void close() {
mProfileConnector.disconnect();
@@ -98,6 +118,8 @@
*
* @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not
* connected to the Map service.
+ *
+ * @hide
*/
public int getState() {
if (VDBG) log("getState()");
@@ -120,6 +142,8 @@
*
* @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
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
@@ -141,6 +165,8 @@
* 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
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
@@ -161,6 +187,8 @@
/**
* Initiate connection. Initiation of outgoing connections is not
* supported for MAP server.
+ *
+ * @hide
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")" + "not supported for MAPS");
@@ -172,6 +200,8 @@
*
* @param device Remote Bluetooth Device
* @return false on error, true otherwise
+ *
+ * @hide
*/
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
@@ -196,6 +226,8 @@
* 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
@@ -214,8 +246,11 @@
* Get the list of connected devices. Currently at most one.
*
* @return list of connected devices
+ *
+ * @hide
*/
- public List<BluetoothDevice> getConnectedDevices() {
+ @SystemApi
+ public @NonNull List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
final IBluetoothMap service = getService();
if (service != null && isEnabled()) {
@@ -234,6 +269,8 @@
* Get the list of devices matching specified states. Currently at most one.
*
* @return list of matching devices
+ *
+ * @hide
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
@@ -254,6 +291,8 @@
* Get connection state of device
*
* @return device connection state
+ *
+ * @hide
*/
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
@@ -301,7 +340,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
- public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+ public boolean setConnectionPolicy(@Nullable BluetoothDevice device, int connectionPolicy) {
if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -349,7 +388,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public int getConnectionPolicy(BluetoothDevice device) {
+ public int getConnectionPolicy(@Nullable BluetoothDevice device) {
if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 0ec473c..0aa5aac 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -19,8 +19,8 @@
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.Uri;
import android.os.Binder;
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 4e97627..ec63fd0 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -16,18 +16,21 @@
package android.bluetooth;
+import android.Manifest;
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.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.CloseGuard;
import android.util.Log;
import java.lang.annotation.Retention;
@@ -48,10 +51,11 @@
* @hide
*/
@SystemApi
-public final class BluetoothPan implements BluetoothProfile {
+public final class BluetoothPan implements BluetoothProfile, AutoCloseable {
private static final String TAG = "BluetoothPan";
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 Pan
@@ -164,10 +168,15 @@
mAdapter = BluetoothAdapter.getDefaultAdapter();
mContext = context;
mProfileConnector.connect(context, listener);
+ mCloseGuard = new CloseGuard();
+ mCloseGuard.open("close");
}
- @UnsupportedAppUsage
- /*package*/ void close() {
+ /**
+ * Closes the connection to the service and unregisters callbacks
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public void close() {
if (VDBG) log("close()");
mProfileConnector.disconnect();
}
@@ -176,8 +185,11 @@
return mProfileConnector.getService();
}
-
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
protected void finalize() {
+ if (mCloseGuard != null) {
+ mCloseGuard.warnIfOpen();
+ }
close();
}
@@ -256,6 +268,41 @@
}
/**
+ * 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_ADMIN)
+ public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+ @ConnectionPolicy int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
+ try {
+ final IBluetoothPan 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);
+ }
+ 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;
+ }
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
@@ -279,6 +326,7 @@
* @hide
*/
@Override
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothPan service = getService();
@@ -298,6 +346,7 @@
* {@inheritDoc}
*/
@Override
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getConnectionState(@Nullable BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
final IBluetoothPan service = getService();
@@ -318,6 +367,7 @@
*
* @param value is whether to enable or disable bluetooth tethering
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void setBluetoothTethering(boolean value) {
String pkgName = mContext.getOpPackageName();
if (DBG) log("setBluetoothTethering(" + value + "), calling package:" + pkgName);
@@ -336,6 +386,7 @@
*
* @return true if tethering is on, false if not or some error occurred
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public boolean isTetheringOn() {
if (VDBG) log("isTetheringOn()");
final IBluetoothPan service = getService();
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index df02896..e07ca52 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -16,11 +16,14 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -271,6 +274,42 @@
}
/**
+ * Pbap does not store connection policy, so this function only disconnects pbap if
+ * connectionPolicy is {@link #CONNECTION_POLICY_FORBIDDEN}.
+ *
+ * <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 determines whether to disconnect the device
+ * @return true if pbap is successfully disconnected, false otherwise
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+ @ConnectionPolicy int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
+ try {
+ final IBluetoothPbap service = mService;
+ if (service != null && isEnabled()
+ && isValidDevice(device)) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ return false;
+ }
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+ 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.
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 097a367..7538df8 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -22,7 +22,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -146,7 +146,7 @@
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
int A2DP_SINK = 11;
/**
@@ -154,7 +154,7 @@
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
int AVRCP_CONTROLLER = 12;
/**
@@ -169,6 +169,7 @@
*
* @hide
*/
+ @SystemApi
int HEADSET_CLIENT = 16;
/**
@@ -176,6 +177,7 @@
*
* @hide
*/
+ @SystemApi
int PBAP_CLIENT = 17;
/**
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index 9b4dabc..8bf1b58 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -19,7 +19,7 @@
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 3a23808..88c186c 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -16,7 +16,7 @@
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.ParcelUuid;
import android.util.Log;
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 760166b..f774369 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -16,7 +16,7 @@
package android.bluetooth;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.LocalSocket;
import android.os.ParcelFileDescriptor;
import android.os.ParcelUuid;
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 7e96c23..e274af1 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelUuid;
import java.nio.ByteBuffer;
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 97e3f52..c0c1aa1 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothUuid;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelUuid;
import android.util.ArrayMap;
import android.util.Log;
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
index e4114c6..489d125 100644
--- a/core/java/android/companion/AssociationRequest.java
+++ b/core/java/android/companion/AssociationRequest.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.OneTimeUseBuilder;
diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java
index fe0123c..2649fbe 100644
--- a/core/java/android/companion/BluetoothDeviceFilter.java
+++ b/core/java/android/companion/BluetoothDeviceFilter.java
@@ -25,8 +25,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.provider.OneTimeUseBuilder;
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
index 0f67f6b..24be45c 100644
--- a/core/java/android/companion/BluetoothDeviceFilterUtils.java
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -21,9 +21,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.wifi.ScanResult;
import android.os.ParcelUuid;
import android.os.Parcelable;
diff --git a/core/java/android/companion/BluetoothLeDeviceFilter.java b/core/java/android/companion/BluetoothLeDeviceFilter.java
index 2701619..730bc60 100644
--- a/core/java/android/companion/BluetoothLeDeviceFilter.java
+++ b/core/java/android/companion/BluetoothLeDeviceFilter.java
@@ -25,11 +25,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.provider.OneTimeUseBuilder;
import android.text.TextUtils;
diff --git a/core/java/android/companion/DeviceFilter.java b/core/java/android/companion/DeviceFilter.java
index dc7cf82..c9cb072 100644
--- a/core/java/android/companion/DeviceFilter.java
+++ b/core/java/android/companion/DeviceFilter.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcelable;
import java.lang.annotation.Retention;
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index bb7d5e4..14c3387 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.OperationCanceledException;
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index f73a376..1d4d30d 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -18,11 +18,11 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.IActivityManager;
import android.app.QueuedWork;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 88e2c22..5c67283 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -21,7 +21,7 @@
import static android.content.ContentResolver.SCHEME_CONTENT;
import static android.content.ContentResolver.SCHEME_FILE;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.net.Uri;
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index dc1c700..dec9589 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
diff --git a/core/java/android/content/ComponentName.java b/core/java/android/content/ComponentName.java
index 18147b5..e955c2d 100644
--- a/core/java/android/content/ComponentName.java
+++ b/core/java/android/content/ComponentName.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 7cdd268..137faea 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -26,8 +26,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppOpsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 93bf518..db8aa40 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -22,7 +22,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.database.CrossProcessCursorWrapper;
import android.database.Cursor;
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 9948338..234f567 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -17,7 +17,7 @@
package android.content;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.database.BulkCursorDescriptor;
import android.database.BulkCursorToCursorAdaptor;
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index c201e4d..e401f2a 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 0a1bc85..a50831f 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -25,12 +25,12 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.UriGrantsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java
index eafeed2..76d37fc 100644
--- a/core/java/android/content/ContentValues.java
+++ b/core/java/android/content/ContentValues.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 902c6b9d..cd4af96 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -30,14 +30,15 @@
import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.annotation.StyleableRes;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
import android.app.VrManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
@@ -3827,6 +3828,7 @@
*/
@SystemApi
@TestApi
+ @SuppressLint("ServiceName")
public static final String STATUS_BAR_SERVICE = "statusbar";
/**
@@ -3851,10 +3853,12 @@
/**
* Use with {@link android.os.ServiceManager.getService()} to retrieve a
- * {@link NetworkStackClient} IBinder for communicating with the network stack
+ * {@link INetworkStackConnector} IBinder for communicating with the network stack
* @hide
* @see NetworkStackClient
*/
+ @SystemApi
+ @TestApi
public static final String NETWORK_STACK_SERVICE = "network_stack";
/**
@@ -3918,6 +3922,8 @@
*/
public static final String NETWORK_STATS_SERVICE = "netstats";
/** {@hide} */
+ @SystemApi
+ @SuppressLint("ServiceName")
public static final String NETWORK_POLICY_SERVICE = "netpolicy";
/** {@hide} */
public static final String NETWORK_WATCHLIST_SERVICE = "network_watchlist";
@@ -4227,6 +4233,7 @@
* @see #getSystemService(String)
*/
@TestApi
+ @SuppressLint("ServiceName") // TODO: This should be renamed to CONTENT_CAPTURE_SERVICE
public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
/**
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 877557f..72cc021 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -21,9 +21,9 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
diff --git a/core/java/android/content/CursorEntityIterator.java b/core/java/android/content/CursorEntityIterator.java
index 2c630d2..952366d 100644
--- a/core/java/android/content/CursorEntityIterator.java
+++ b/core/java/android/content/CursorEntityIterator.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.Cursor;
import android.os.RemoteException;
diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java
index 4ccafab..4ff5cca 100644
--- a/core/java/android/content/CursorLoader.java
+++ b/core/java/android/content/CursorLoader.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.Cursor;
import android.net.Uri;
import android.os.CancellationSignal;
diff --git a/core/java/android/content/Entity.java b/core/java/android/content/Entity.java
index ff4f150..13137c4 100644
--- a/core/java/android/content/Entity.java
+++ b/core/java/android/content/Entity.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 0427c2f..92df7ee 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -17,7 +17,7 @@
package android.content;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a6867ff..9cba7aa 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -28,8 +28,8 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
@@ -4011,6 +4011,7 @@
* <p>
* @see #EXTRA_SIM_STATE
* @see #EXTRA_SIM_LOCKED_REASON
+ * @see #EXTRA_REBROADCAST_ON_UNLOCK
*
* @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED} or
* {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
@@ -4187,6 +4188,18 @@
public static final String SIM_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED";
/**
+ * The extra used with {@link #ACTION_SIM_STATE_CHANGED} for indicating whether this broadcast
+ * is a rebroadcast on unlock. Defaults to {@code false} if not specified.
+ *
+ * @hide
+ * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED} or
+ * {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+ */
+ @Deprecated
+ @SystemApi
+ public static final String EXTRA_REBROADCAST_ON_UNLOCK = "rebroadcastOnUnlock";
+
+ /**
* Broadcast Action: indicate that the phone service state has changed.
* The intent will have the following extra values:</p>
* <p>
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 099dea2..4d0ecff 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index ec0bac4..f40dc29 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -16,14 +16,14 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.util.AndroidException;
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index bbdab04..885eb70 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -17,9 +17,9 @@
package android.content;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
diff --git a/core/java/android/content/SearchRecentSuggestionsProvider.java b/core/java/android/content/SearchRecentSuggestionsProvider.java
index 8ee7b9e..fc3ddf6 100644
--- a/core/java/android/content/SearchRecentSuggestionsProvider.java
+++ b/core/java/android/content/SearchRecentSuggestionsProvider.java
@@ -16,8 +16,8 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
import android.app.SearchManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index 8c8fe5a..7bcdbfd 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -17,11 +17,11 @@
package android.content;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
-import android.text.TextUtils;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
/**
* Value type that represents a SyncAdapterType. This object overrides {@link #equals} and
diff --git a/core/java/android/content/SyncAdaptersCache.java b/core/java/android/content/SyncAdaptersCache.java
index d4e5217..58445a7 100644
--- a/core/java/android/content/SyncAdaptersCache.java
+++ b/core/java/android/content/SyncAdaptersCache.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.RegisteredServicesCache;
import android.content.pm.XmlSerializerAndParser;
import android.content.res.Resources;
@@ -29,8 +29,8 @@
import com.android.internal.annotations.GuardedBy;
import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.util.ArrayList;
diff --git a/core/java/android/content/SyncContext.java b/core/java/android/content/SyncContext.java
index 50d1dc9..4a9f66c 100644
--- a/core/java/android/content/SyncContext.java
+++ b/core/java/android/content/SyncContext.java
@@ -16,10 +16,10 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.IBinder;
public class SyncContext {
private ISyncContext mSyncContext;
diff --git a/core/java/android/content/SyncInfo.java b/core/java/android/content/SyncInfo.java
index d3f2eed..017a92b 100644
--- a/core/java/android/content/SyncInfo.java
+++ b/core/java/android/content/SyncInfo.java
@@ -17,7 +17,7 @@
package android.content;
import android.accounts.Account;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index 5f1f180..9e568a4 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -17,7 +17,7 @@
package android.content;
import android.accounts.Account;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index 3f64515..620fdb7 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
diff --git a/core/java/android/content/UndoManager.java b/core/java/android/content/UndoManager.java
index f9c58d6..ed9cd86 100644
--- a/core/java/android/content/UndoManager.java
+++ b/core/java/android/content/UndoManager.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.text.TextUtils;
import android.util.ArrayMap;
diff --git a/core/java/android/content/UndoOperation.java b/core/java/android/content/UndoOperation.java
index a425486..235d721 100644
--- a/core/java/android/content/UndoOperation.java
+++ b/core/java/android/content/UndoOperation.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java
index 208bc01..7fa48f0 100644
--- a/core/java/android/content/UriMatcher.java
+++ b/core/java/android/content/UriMatcher.java
@@ -16,7 +16,7 @@
package android.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import java.util.ArrayList;
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index 1a78f79..a3487be 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -20,8 +20,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 95e5f6b..43dd1f45 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Configuration;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 0ea1845..49d2201 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -22,7 +22,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
diff --git a/core/java/android/content/pm/BaseParceledListSlice.java b/core/java/android/content/pm/BaseParceledListSlice.java
index 4178309..5d1a08c 100644
--- a/core/java/android/content/pm/BaseParceledListSlice.java
+++ b/core/java/android/content/pm/BaseParceledListSlice.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 29612c2..988b280 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 1451431..67deb82 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 3933e81..ac8eab7 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -25,10 +25,10 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index d6fb28f..f4d4a8d 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -17,7 +17,7 @@
package android.content.pm;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java
index f5442ec..6743a3f 100644
--- a/core/java/android/content/pm/PackageInfoLite.java
+++ b/core/java/android/content/pm/PackageInfoLite.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 1099d8b..78db3d8 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -26,9 +26,9 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager.DeleteFlags;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 81670cd..0ae00fb 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -29,7 +29,6 @@
import android.annotation.StringRes;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.XmlRes;
import android.app.ActivityManager;
@@ -38,6 +37,7 @@
import android.app.PackageInstallObserver;
import android.app.admin.DevicePolicyManager;
import android.app.usage.StorageStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 812ae93..0e61016 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -47,11 +47,11 @@
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.apex.ApexInfo;
import android.app.ActivityTaskManager;
import android.app.ActivityThread;
import android.app.ResourcesManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index b0fecfa..7c12527 100644
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -16,8 +16,8 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
import android.app.usage.StorageStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 249b691..d1e1132 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -27,7 +27,7 @@
import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.BaseBundle;
import android.os.Debug;
import android.os.PersistableBundle;
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
index dccc524..73119e0 100644
--- a/core/java/android/content/pm/ParceledListSlice.java
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index c77c53f..89a1c6a 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -22,7 +22,7 @@
import android.annotation.StringRes;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 23fbefb..bd909c7 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -17,7 +17,7 @@
package android.content.pm;
import android.Manifest;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -43,11 +43,11 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
+import libcore.io.IoUtils;
+
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
-import libcore.io.IoUtils;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 1734182..7755fe3 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -17,7 +17,7 @@
package android.content.pm;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 58aacc2..e14bcf6 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -20,11 +20,11 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.Notification;
import android.app.Person;
import android.app.TaskStackBuilder;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index f851799..dde8865 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -22,9 +22,9 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.usage.UsageStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index 25a4dca..3b84ae7 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 2b1b32e..caf0958 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -16,10 +16,9 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
diff --git a/core/java/android/content/pm/VerifierInfo.java b/core/java/android/content/pm/VerifierInfo.java
index 224ca62..5f88555 100644
--- a/core/java/android/content/pm/VerifierInfo.java
+++ b/core/java/android/content/pm/VerifierInfo.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/XmlSerializerAndParser.java b/core/java/android/content/pm/XmlSerializerAndParser.java
index 6d24800..5dce839 100644
--- a/core/java/android/content/pm/XmlSerializerAndParser.java
+++ b/core/java/android/content/pm/XmlSerializerAndParser.java
@@ -16,11 +16,12 @@
package android.content.pm;
-import org.xmlpull.v1.XmlSerializer;
+import android.compat.annotation.UnsupportedAppUsage;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
-import android.annotation.UnsupportedAppUsage;
import java.io.IOException;
/** @hide */
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index 69462ab..baa3e84 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -16,7 +16,7 @@
package android.content.res;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java
index 2ba5579..e93ec00 100644
--- a/core/java/android/content/res/AssetFileDescriptor.java
+++ b/core/java/android/content/res/AssetFileDescriptor.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index e5ef67b..a70eff9 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -24,7 +24,7 @@
import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration.NativeConfig;
import android.os.ParcelFileDescriptor;
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index b5b097b..f23c802 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -19,9 +19,18 @@
import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.Resources.Theme;
import android.graphics.Color;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.MathUtils;
+import android.util.SparseArray;
+import android.util.StateSet;
+import android.util.Xml;
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
@@ -30,16 +39,6 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import android.annotation.UnsupportedAppUsage;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.MathUtils;
-import android.util.SparseArray;
-import android.util.StateSet;
-import android.util.Xml;
-import android.os.Parcel;
-import android.os.Parcelable;
-
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Arrays;
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index f3b7553..c66c70a2 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.graphics.Canvas;
import android.graphics.PointF;
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index e40e566..cec6382 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -45,8 +45,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.WindowConfiguration;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.LocaleProto;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index 848790f..5e10a57 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
/**
diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java
index 90604b8..5497e61 100644
--- a/core/java/android/content/res/DrawableCache.java
+++ b/core/java/android/content/res/DrawableCache.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.drawable.Drawable;
/**
diff --git a/core/java/android/content/res/ObbInfo.java b/core/java/android/content/res/ObbInfo.java
index 8af27ca..c477abc 100644
--- a/core/java/android/content/res/ObbInfo.java
+++ b/core/java/android/content/res/ObbInfo.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index d7e4e14..4f6449e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -39,8 +39,8 @@
import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.annotation.StyleableRes;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
import android.graphics.Movie;
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 794be9e..86ba0b6 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -27,7 +27,7 @@
import android.annotation.RawRes;
import android.annotation.StyleRes;
import android.annotation.StyleableRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
import android.content.res.AssetManager.AssetInputStream;
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 1db2dd8..a29fea0 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.TextUtils;
import java.util.Arrays;
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
index b7bc822..6258892 100644
--- a/core/java/android/content/res/StringBlock.java
+++ b/core/java/android/content/res/StringBlock.java
@@ -16,7 +16,7 @@
package android.content.res;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java
index 06cafdb..f24e6f2 100644
--- a/core/java/android/content/res/ThemedResourceCache.java
+++ b/core/java/android/content/res/ThemedResourceCache.java
@@ -18,12 +18,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.Resources.Theme;
import android.content.res.Resources.ThemeKey;
-import android.util.LongSparseArray;
import android.util.ArrayMap;
+import android.util.LongSparseArray;
import java.lang.ref.WeakReference;
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index b79cf65..90affdf 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -20,7 +20,7 @@
import android.annotation.ColorInt;
import android.annotation.Nullable;
import android.annotation.StyleableRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
import android.graphics.Typeface;
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index 626bf77..cb93cbf 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -20,7 +20,7 @@
import android.annotation.AnyRes;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.TypedValue;
import com.android.internal.util.XmlUtils;
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index cc5d3b1..3e10a6c 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -17,7 +17,7 @@
package android.database;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.Build;
diff --git a/core/java/android/database/AbstractWindowedCursor.java b/core/java/android/database/AbstractWindowedCursor.java
index a988f068..daf7d2b 100644
--- a/core/java/android/database/AbstractWindowedCursor.java
+++ b/core/java/android/database/AbstractWindowedCursor.java
@@ -16,7 +16,7 @@
package android.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* A base class for Cursors that store their data in {@link CursorWindow}s.
diff --git a/core/java/android/database/BulkCursorNative.java b/core/java/android/database/BulkCursorNative.java
index 77a13cf..8ea450c 100644
--- a/core/java/android/database/BulkCursorNative.java
+++ b/core/java/android/database/BulkCursorNative.java
@@ -16,7 +16,7 @@
package android.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
diff --git a/core/java/android/database/ContentObserver.java b/core/java/android/database/ContentObserver.java
index 798b783..69ca581 100644
--- a/core/java/android/database/ContentObserver.java
+++ b/core/java/android/database/ContentObserver.java
@@ -16,7 +16,7 @@
package android.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index 6873577..063a2d0 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -17,7 +17,7 @@
package android.database;
import android.annotation.BytesLong;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.database.sqlite.SQLiteClosable;
import android.database.sqlite.SQLiteException;
diff --git a/core/java/android/database/CursorWrapper.java b/core/java/android/database/CursorWrapper.java
index c9cafaf..4496f80 100644
--- a/core/java/android/database/CursorWrapper.java
+++ b/core/java/android/database/CursorWrapper.java
@@ -16,7 +16,7 @@
package android.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.Bundle;
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 992da31..4246b84 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -17,7 +17,7 @@
package android.database;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java
index b0d399c..050a49a 100644
--- a/core/java/android/database/MatrixCursor.java
+++ b/core/java/android/database/MatrixCursor.java
@@ -16,7 +16,7 @@
package android.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import java.util.ArrayList;
diff --git a/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java b/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
index 2af06e1..ba546f3 100644
--- a/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
+++ b/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An exception that indicates that garbage-collector is finalizing a database object
diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java
index d6a71da..2fca729 100644
--- a/core/java/android/database/sqlite/SQLiteClosable.java
+++ b/core/java/android/database/sqlite/SQLiteClosable.java
@@ -16,7 +16,8 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.Closeable;
/**
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index e3c4098..4559e91 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.AbstractWindowedCursor;
import android.database.CursorWindow;
import android.database.DatabaseUtils;
diff --git a/core/java/android/database/sqlite/SQLiteCustomFunction.java b/core/java/android/database/sqlite/SQLiteCustomFunction.java
index 41b78d3..1ace40d 100644
--- a/core/java/android/database/sqlite/SQLiteCustomFunction.java
+++ b/core/java/android/database/sqlite/SQLiteCustomFunction.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
/**
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index caf3e93..7a0e183 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -20,9 +20,9 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index fcdaf0a..6a52b72 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.ArrayList;
import java.util.Locale;
diff --git a/core/java/android/database/sqlite/SQLiteDebug.java b/core/java/android/database/sqlite/SQLiteDebug.java
index 3d0ac61..165f863 100644
--- a/core/java/android/database/sqlite/SQLiteDebug.java
+++ b/core/java/android/database/sqlite/SQLiteDebug.java
@@ -17,14 +17,13 @@
package android.database.sqlite;
import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Process;
import android.os.SystemProperties;
import android.util.Log;
import android.util.Printer;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.util.ArrayList;
/**
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 62cec0e..943afc7 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -19,7 +19,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.SQLException;
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 8304133..de1c543 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.DatabaseUtils;
import android.os.CancellationSignal;
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 5890179..02c8a97 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.DatabaseUtils;
diff --git a/core/java/android/database/sqlite/SQLiteSession.java b/core/java/android/database/sqlite/SQLiteSession.java
index a9ac9e7..24b62b8 100644
--- a/core/java/android/database/sqlite/SQLiteSession.java
+++ b/core/java/android/database/sqlite/SQLiteSession.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.CursorWindow;
import android.database.DatabaseUtils;
import android.os.CancellationSignal;
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 42e7ac7..9fda8b0 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelFileDescriptor;
/**
diff --git a/core/java/android/database/sqlite/SqliteWrapper.java b/core/java/android/database/sqlite/SqliteWrapper.java
index e317164..f335fbd 100644
--- a/core/java/android/database/sqlite/SqliteWrapper.java
+++ b/core/java/android/database/sqlite/SqliteWrapper.java
@@ -17,12 +17,11 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
-import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;
diff --git a/core/java/android/ddm/DdmHandleAppName.java b/core/java/android/ddm/DdmHandleAppName.java
index 9560787..e6fb4ec 100644
--- a/core/java/android/ddm/DdmHandleAppName.java
+++ b/core/java/android/ddm/DdmHandleAppName.java
@@ -16,11 +16,13 @@
package android.ddm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.util.Log;
+
import org.apache.harmony.dalvik.ddmc.Chunk;
import org.apache.harmony.dalvik.ddmc.ChunkHandler;
import org.apache.harmony.dalvik.ddmc.DdmServer;
-import android.util.Log;
+
import java.nio.ByteBuffer;
diff --git a/core/java/android/debug/AdbManager.java b/core/java/android/debug/AdbManager.java
index ae3d794..0a76bed 100644
--- a/core/java/android/debug/AdbManager.java
+++ b/core/java/android/debug/AdbManager.java
@@ -16,15 +16,17 @@
package android.debug;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
+import android.os.RemoteException;
/**
- * This class allows the control of ADB-related functions. Currently only ADB over USB is
- * supported, and none of the API is public.
- *
+ * This class allows the control of ADB-related functions.
* @hide
*/
+@SystemApi
@SystemService(Context.ADB_SERVICE)
public class AdbManager {
private static final String TAG = "AdbManager";
@@ -39,4 +41,33 @@
mContext = context;
mService = service;
}
+
+ /**
+ * @return true if the device supports secure ADB over Wi-Fi.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
+ public boolean isAdbWifiSupported() {
+ try {
+ return mService.isAdbWifiSupported();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @return true if the device supports secure ADB over Wi-Fi and device pairing by
+ * QR code.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
+ public boolean isAdbWifiQrSupported() {
+ try {
+ return mService.isAdbWifiQrSupported();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/debug/IAdbManager.aidl b/core/java/android/debug/IAdbManager.aidl
index 79e0794..c48fc07 100644
--- a/core/java/android/debug/IAdbManager.aidl
+++ b/core/java/android/debug/IAdbManager.aidl
@@ -41,4 +41,15 @@
* Clear all public keys installed for secure ADB debugging.
*/
void clearDebuggingKeys();
+
+ /**
+ * Returns true if device supports secure Adb over Wi-Fi.
+ */
+ boolean isAdbWifiSupported();
+
+ /**
+ * Returns true if device supports secure Adb over Wi-Fi and device pairing by
+ * QR code.
+ */
+ boolean isAdbWifiQrSupported();
}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 33e51c9..c847f86 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -16,14 +16,20 @@
package android.hardware;
-import static android.system.OsConstants.*;
+import static android.system.OsConstants.EACCES;
+import static android.system.OsConstants.EBUSY;
+import static android.system.OsConstants.EINVAL;
+import static android.system.OsConstants.ENODEV;
+import static android.system.OsConstants.ENOSYS;
+import static android.system.OsConstants.EOPNOTSUPP;
+import static android.system.OsConstants.EUSERS;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.AppOpsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Point;
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index c569e05..6779751 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -20,7 +20,7 @@
import android.annotation.IntRange;
import android.annotation.LongDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.GraphicBuffer;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index e78fb7f..a71a7b6 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -18,7 +18,7 @@
package android.hardware;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
/**
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 8c910b2..64c45bf 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -16,7 +16,7 @@
package android.hardware;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* This class represents a {@link android.hardware.Sensor Sensor} event and
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 3250428..6036d79 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -18,7 +18,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/hardware/SerialManager.java b/core/java/android/hardware/SerialManager.java
index 571c3cc..b51382e 100644
--- a/core/java/android/hardware/SerialManager.java
+++ b/core/java/android/hardware/SerialManager.java
@@ -17,7 +17,7 @@
package android.hardware;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
diff --git a/core/java/android/hardware/SerialPort.java b/core/java/android/hardware/SerialPort.java
index 78ac3c0..0fcaa49 100644
--- a/core/java/android/hardware/SerialPort.java
+++ b/core/java/android/hardware/SerialPort.java
@@ -16,12 +16,11 @@
package android.hardware;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelFileDescriptor;
import java.io.FileDescriptor;
import java.io.IOException;
-
import java.nio.ByteBuffer;
/**
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 7abfabf..974913b 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -16,7 +16,7 @@
package android.hardware;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 27c04b4..2333251 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -16,8 +16,8 @@
package android.hardware.biometrics;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index b025508..5c74456 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -16,8 +16,8 @@
package android.hardware.biometrics;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.fingerprint.FingerprintManager;
/**
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 1142a07..2497ea9 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -32,6 +32,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.security.identity.IdentityCredential;
import android.text.TextUtils;
import android.util.Log;
@@ -401,6 +402,10 @@
super(mac);
}
+ public CryptoObject(@NonNull IdentityCredential credential) {
+ super(credential);
+ }
+
/**
* Get {@link Signature} object.
* @return {@link Signature} object or null if this doesn't contain one.
@@ -424,6 +429,14 @@
public Mac getMac() {
return super.getMac();
}
+
+ /**
+ * Get {@link IdentityCredential} object.
+ * @return {@link IdentityCredential} object or null if this doesn't contain one.
+ */
+ public @Nullable IdentityCredential getIdentityCredential() {
+ return super.getIdentityCredential();
+ }
}
/**
diff --git a/core/java/android/hardware/biometrics/CryptoObject.java b/core/java/android/hardware/biometrics/CryptoObject.java
index 787dc66..0af18df 100644
--- a/core/java/android/hardware/biometrics/CryptoObject.java
+++ b/core/java/android/hardware/biometrics/CryptoObject.java
@@ -17,6 +17,7 @@
package android.hardware.biometrics;
import android.annotation.NonNull;
+import android.security.identity.IdentityCredential;
import android.security.keystore.AndroidKeyStoreProvider;
import java.security.Signature;
@@ -26,7 +27,8 @@
/**
* A wrapper class for the crypto objects supported by BiometricPrompt and FingerprintManager.
- * Currently the framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
+ * Currently the framework supports {@link Signature}, {@link Cipher}, {@link Mac} and
+ * {@link IdentityCredential} objects.
* @hide
*/
public class CryptoObject {
@@ -44,6 +46,10 @@
mCrypto = mac;
}
+ public CryptoObject(@NonNull IdentityCredential credential) {
+ mCrypto = credential;
+ }
+
/**
* Get {@link Signature} object.
* @return {@link Signature} object or null if this doesn't contain one.
@@ -69,11 +75,23 @@
}
/**
+ * Get {@link IdentityCredential} object.
+ * @return {@link IdentityCredential} object or null if this doesn't contain one.
+ */
+ public IdentityCredential getIdentityCredential() {
+ return mCrypto instanceof IdentityCredential ? (IdentityCredential) mCrypto : null;
+ }
+
+ /**
* @hide
* @return the opId associated with this object or 0 if none
*/
public final long getOpId() {
- return mCrypto != null
- ? AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0;
+ if (mCrypto == null) {
+ return 0;
+ } else if (mCrypto instanceof IdentityCredential) {
+ return ((IdentityCredential) mCrypto).getCredstoreOperationHandle();
+ }
+ return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto);
}
};
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 48588e6..c697d4c 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.PublicKey;
import android.hardware.camera2.impl.SyntheticKey;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 6a2fc8a..d027de8 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.PublicKey;
import android.hardware.camera2.impl.SyntheticKey;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index ba451e5..af05b29 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.impl.PublicKey;
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index e909c00..706aa4ef 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -16,12 +16,11 @@
package android.hardware.camera2.impl;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.ImageFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.marshal.MarshalQueryable;
@@ -52,7 +51,6 @@
import android.hardware.camera2.params.HighSpeedVideoConfiguration;
import android.hardware.camera2.params.LensShadingMap;
import android.hardware.camera2.params.MandatoryStreamCombination;
-import android.hardware.camera2.params.MandatoryStreamCombination.MandatoryStreamInformation;
import android.hardware.camera2.params.OisSample;
import android.hardware.camera2.params.RecommendedStreamConfiguration;
import android.hardware.camera2.params.RecommendedStreamConfigurationMap;
diff --git a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
index 526f086..16f3f2a 100644
--- a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
+++ b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
@@ -16,7 +16,7 @@
package android.hardware.camera2.utils;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Provide hashing functions using the Modified Bernstein hash
diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
index d3c4505..abe1372 100644
--- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java
+++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
@@ -16,7 +16,7 @@
package android.hardware.camera2.utils;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.ImageFormat;
import android.hardware.camera2.legacy.LegacyCameraDevice;
import android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandonedException;
diff --git a/core/java/android/hardware/camera2/utils/TypeReference.java b/core/java/android/hardware/camera2/utils/TypeReference.java
index d9ba31b..435ed15 100644
--- a/core/java/android/hardware/camera2/utils/TypeReference.java
+++ b/core/java/android/hardware/camera2/utils/TypeReference.java
@@ -16,7 +16,10 @@
package android.hardware.camera2.utils;
-import android.annotation.UnsupportedAppUsage;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
@@ -24,8 +27,6 @@
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
-import static com.android.internal.util.Preconditions.*;
-
/**
* Super type token; allows capturing generic types at runtime by forcing them to be reified.
*
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 0b25dbd..799dff9 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -23,8 +23,8 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Point;
import android.media.projection.MediaProjection;
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index ea63776..2a58495 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
diff --git a/core/java/android/hardware/display/WifiDisplay.java b/core/java/android/hardware/display/WifiDisplay.java
index 55e6051..5bbbbf9 100644
--- a/core/java/android/hardware/display/WifiDisplay.java
+++ b/core/java/android/hardware/display/WifiDisplay.java
@@ -16,7 +16,7 @@
package android.hardware.display;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/hardware/display/WifiDisplayStatus.java b/core/java/android/hardware/display/WifiDisplayStatus.java
index 1973e51..e2a825f 100644
--- a/core/java/android/hardware/display/WifiDisplayStatus.java
+++ b/core/java/android/hardware/display/WifiDisplayStatus.java
@@ -16,7 +16,7 @@
package android.hardware.display;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index d0622c8..16f9688 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -26,8 +26,8 @@
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricAuthenticator;
@@ -44,6 +44,7 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.security.identity.IdentityCredential;
import android.util.Slog;
import java.security.Signature;
@@ -125,6 +126,10 @@
super(mac);
}
+ public CryptoObject(@NonNull IdentityCredential credential) {
+ super(credential);
+ }
+
/**
* Get {@link Signature} object.
* @return {@link Signature} object or null if this doesn't contain one.
@@ -148,6 +153,14 @@
public Mac getMac() {
return super.getMac();
}
+
+ /**
+ * Get {@link IdentityCredential} object.
+ * @return {@link IdentityCredential} object or null if this doesn't contain one.
+ */
+ public @Nullable IdentityCredential getIdentityCredential() {
+ return super.getIdentityCredential();
+ }
}
/**
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 0c0f248..8d32db0 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -20,7 +20,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.AudioAttributes;
import android.os.Binder;
diff --git a/core/java/android/hardware/location/GeofenceHardware.java b/core/java/android/hardware/location/GeofenceHardware.java
index 23d8d01..a1866af 100644
--- a/core/java/android/hardware/location/GeofenceHardware.java
+++ b/core/java/android/hardware/location/GeofenceHardware.java
@@ -16,7 +16,7 @@
package android.hardware.location;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.location.Location;
import android.os.Build;
import android.os.RemoteException;
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index f96f47d..2f0265a 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -25,8 +25,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioFormat;
import android.os.Handler;
import android.os.Parcel;
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index 9113548..694d605 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -16,7 +16,7 @@
package android.hardware.soundtrigger;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index 08c9eea..fdb4cc07 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 71297c1..215ac24 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.ParcelFileDescriptor;
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index eb148b9..67fdda3 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -26,8 +26,8 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -91,7 +91,7 @@
*
* {@hide}
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final String ACTION_USB_STATE =
"android.hardware.usb.action.USB_STATE";
@@ -164,7 +164,7 @@
*
* {@hide}
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final String USB_CONNECTED = "connected";
/**
@@ -181,6 +181,7 @@
*
* {@hide}
*/
+ @SystemApi
public static final String USB_CONFIGURED = "configured";
/**
@@ -217,6 +218,7 @@
*
* {@hide}
*/
+ @SystemApi
public static final String USB_FUNCTION_RNDIS = "rndis";
/**
@@ -319,6 +321,7 @@
* Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
* {@hide}
*/
+ @SystemApi
public static final long FUNCTION_NONE = 0;
/**
@@ -337,6 +340,7 @@
* Code for the rndis usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
* {@hide}
*/
+ @SystemApi
public static final long FUNCTION_RNDIS = GadgetFunction.RNDIS;
/**
@@ -698,6 +702,8 @@
*
* {@hide}
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MANAGE_USB)
public void setCurrentFunctions(long functions) {
try {
mService.setCurrentFunctions(functions);
@@ -737,6 +743,8 @@
*
* {@hide}
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MANAGE_USB)
public long getCurrentFunctions() {
try {
return mService.getCurrentFunctions();
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index 7abf3e9..fab2c0b 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -17,7 +17,7 @@
package android.hardware.usb;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.util.Log;
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index 7d4849f..9327b24 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -16,7 +16,7 @@
package android.inputmethodservice;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index a47f601..69b93b1 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -18,7 +18,7 @@
import android.annotation.BinderThread;
import android.annotation.MainThread;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 82d4d1d..44825a8 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -30,9 +30,9 @@
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.Dialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index 3f25113..c85fcd9 100644
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -16,8 +16,8 @@
package android.inputmethodservice;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 45f067b..b780b21 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -16,7 +16,7 @@
package android.inputmethodservice;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java
index a66fcae..fb35b4b 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -60,6 +60,18 @@
@SystemApi
@TestApi
public static final int APP_RETURN_WANTED_AS_IS = 2;
+ /** Event offset of request codes from captive portal application. */
+ private static final int APP_REQUEST_BASE = 100;
+ /**
+ * Request code from the captive portal application, indicating that the network condition may
+ * have changed and the network should be re-validated.
+ * @see ICaptivePortal#appRequest(int)
+ * @see android.net.INetworkMonitor#forceReevaluation(int)
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final int APP_REQUEST_REEVALUATION_REQUIRED = APP_REQUEST_BASE + 0;
private final IBinder mBinder;
@@ -136,6 +148,19 @@
}
/**
+ * Request that the system reevaluates the captive portal status.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public void reevaluateNetwork() {
+ try {
+ ICaptivePortal.Stub.asInterface(mBinder).appRequest(APP_REQUEST_REEVALUATION_REQUIRED);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Log a captive portal login event.
* @param eventId one of the CAPTIVE_PORTAL_LOGIN_* constants in metrics_constants.proto.
* @param packageName captive portal application package name.
diff --git a/core/java/android/net/NetworkMisc.aidl b/core/java/android/net/CaptivePortalData.aidl
similarity index 84%
copy from core/java/android/net/NetworkMisc.aidl
copy to core/java/android/net/CaptivePortalData.aidl
index c65583f..1d57ee7 100644
--- a/core/java/android/net/NetworkMisc.aidl
+++ b/core/java/android/net/CaptivePortalData.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,4 +16,4 @@
package android.net;
-parcelable NetworkMisc;
+@JavaOnlyStableParcelable parcelable CaptivePortalData;
diff --git a/core/java/android/net/CaptivePortalData.java b/core/java/android/net/CaptivePortalData.java
new file mode 100644
index 0000000..1357803
--- /dev/null
+++ b/core/java/android/net/CaptivePortalData.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Metadata sent by captive portals, see https://www.ietf.org/id/draft-ietf-capport-api-03.txt.
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class CaptivePortalData implements Parcelable {
+ private final long mRefreshTimeMillis;
+ @Nullable
+ private final Uri mUserPortalUrl;
+ @Nullable
+ private final Uri mVenueInfoUrl;
+ private final boolean mIsSessionExtendable;
+ private final long mByteLimit;
+ private final long mExpiryTimeMillis;
+ private final boolean mCaptive;
+
+ private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl,
+ boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive) {
+ mRefreshTimeMillis = refreshTimeMillis;
+ mUserPortalUrl = userPortalUrl;
+ mVenueInfoUrl = venueInfoUrl;
+ mIsSessionExtendable = isSessionExtendable;
+ mByteLimit = byteLimit;
+ mExpiryTimeMillis = expiryTimeMillis;
+ mCaptive = captive;
+ }
+
+ private CaptivePortalData(Parcel p) {
+ this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(),
+ p.readLong(), p.readLong(), p.readBoolean());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeLong(mRefreshTimeMillis);
+ dest.writeParcelable(mUserPortalUrl, 0);
+ dest.writeParcelable(mVenueInfoUrl, 0);
+ dest.writeBoolean(mIsSessionExtendable);
+ dest.writeLong(mByteLimit);
+ dest.writeLong(mExpiryTimeMillis);
+ dest.writeBoolean(mCaptive);
+ }
+
+ /**
+ * A builder to create new {@link CaptivePortalData}.
+ */
+ public static class Builder {
+ private long mRefreshTime;
+ private Uri mUserPortalUrl;
+ private Uri mVenueInfoUrl;
+ private boolean mIsSessionExtendable;
+ private long mBytesRemaining = -1;
+ private long mExpiryTime = -1;
+ private boolean mCaptive;
+
+ /**
+ * Create an empty builder.
+ */
+ public Builder() {}
+
+ /**
+ * Create a builder copying all data from existing {@link CaptivePortalData}.
+ */
+ public Builder(@Nullable CaptivePortalData data) {
+ if (data == null) return;
+ setRefreshTime(data.mRefreshTimeMillis)
+ .setUserPortalUrl(data.mUserPortalUrl)
+ .setVenueInfoUrl(data.mVenueInfoUrl)
+ .setSessionExtendable(data.mIsSessionExtendable)
+ .setBytesRemaining(data.mByteLimit)
+ .setExpiryTime(data.mExpiryTimeMillis)
+ .setCaptive(data.mCaptive);
+ }
+
+ /**
+ * Set the time at which data was last refreshed, as per {@link System#currentTimeMillis()}.
+ */
+ @NonNull
+ public Builder setRefreshTime(long refreshTime) {
+ mRefreshTime = refreshTime;
+ return this;
+ }
+
+ /**
+ * Set the URL to be used for users to login to the portal, if captive.
+ */
+ @NonNull
+ public Builder setUserPortalUrl(@Nullable Uri userPortalUrl) {
+ mUserPortalUrl = userPortalUrl;
+ return this;
+ }
+
+ /**
+ * Set the URL that can be used by users to view information about the network venue.
+ */
+ @NonNull
+ public Builder setVenueInfoUrl(@Nullable Uri venueInfoUrl) {
+ mVenueInfoUrl = venueInfoUrl;
+ return this;
+ }
+
+ /**
+ * Set whether the portal supports extending a user session on the portal URL page.
+ */
+ @NonNull
+ public Builder setSessionExtendable(boolean sessionExtendable) {
+ mIsSessionExtendable = sessionExtendable;
+ return this;
+ }
+
+ /**
+ * Set the number of bytes remaining on the network before the portal closes.
+ */
+ @NonNull
+ public Builder setBytesRemaining(long bytesRemaining) {
+ mBytesRemaining = bytesRemaining;
+ return this;
+ }
+
+ /**
+ * Set the time at the session will expire, as per {@link System#currentTimeMillis()}.
+ */
+ @NonNull
+ public Builder setExpiryTime(long expiryTime) {
+ mExpiryTime = expiryTime;
+ return this;
+ }
+
+ /**
+ * Set whether the network is captive (portal closed).
+ */
+ @NonNull
+ public Builder setCaptive(boolean captive) {
+ mCaptive = captive;
+ return this;
+ }
+
+ /**
+ * Create a new {@link CaptivePortalData}.
+ */
+ @NonNull
+ public CaptivePortalData build() {
+ return new CaptivePortalData(mRefreshTime, mUserPortalUrl, mVenueInfoUrl,
+ mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive);
+ }
+ }
+
+ /**
+ * Get the time at which data was last refreshed, as per {@link System#currentTimeMillis()}.
+ */
+ public long getRefreshTimeMillis() {
+ return mRefreshTimeMillis;
+ }
+
+ /**
+ * Get the URL to be used for users to login to the portal, or extend their session if
+ * {@link #isSessionExtendable()} is true.
+ */
+ @Nullable
+ public Uri getUserPortalUrl() {
+ return mUserPortalUrl;
+ }
+
+ /**
+ * Get the URL that can be used by users to view information about the network venue.
+ */
+ @Nullable
+ public Uri getVenueInfoUrl() {
+ return mVenueInfoUrl;
+ }
+
+ /**
+ * Indicates whether the user portal URL can be used to extend sessions, when the user is logged
+ * in and the session has a time or byte limit.
+ */
+ public boolean isSessionExtendable() {
+ return mIsSessionExtendable;
+ }
+
+ /**
+ * Get the remaining bytes on the captive portal session, at the time {@link CaptivePortalData}
+ * was refreshed. This may be different from the limit currently enforced by the portal.
+ * @return The byte limit, or -1 if not set.
+ */
+ public long getByteLimit() {
+ return mByteLimit;
+ }
+
+ /**
+ * Get the time at the session will expire, as per {@link System#currentTimeMillis()}.
+ * @return The expiry time, or -1 if unset.
+ */
+ public long getExpiryTimeMillis() {
+ return mExpiryTimeMillis;
+ }
+
+ /**
+ * Get whether the network is captive (portal closed).
+ */
+ public boolean isCaptive() {
+ return mCaptive;
+ }
+
+ @NonNull
+ public static final Creator<CaptivePortalData> CREATOR = new Creator<CaptivePortalData>() {
+ @Override
+ public CaptivePortalData createFromParcel(Parcel source) {
+ return new CaptivePortalData(source);
+ }
+
+ @Override
+ public CaptivePortalData[] newArray(int size) {
+ return new CaptivePortalData[size];
+ }
+ };
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl,
+ mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CaptivePortalData)) return false;
+ final CaptivePortalData other = (CaptivePortalData) obj;
+ return mRefreshTimeMillis == other.mRefreshTimeMillis
+ && Objects.equals(mUserPortalUrl, other.mUserPortalUrl)
+ && Objects.equals(mVenueInfoUrl, other.mVenueInfoUrl)
+ && mIsSessionExtendable == other.mIsSessionExtendable
+ && mByteLimit == other.mByteLimit
+ && mExpiryTimeMillis == other.mExpiryTimeMillis
+ && mCaptive == other.mCaptive;
+ }
+
+ @Override
+ public String toString() {
+ return "CaptivePortalData {"
+ + "refreshTime: " + mRefreshTimeMillis
+ + ", userPortalUrl: " + mUserPortalUrl
+ + ", venueInfoUrl: " + mVenueInfoUrl
+ + ", isSessionExtendable: " + mIsSessionExtendable
+ + ", byteLimit: " + mByteLimit
+ + ", expiryTime: " + mExpiryTimeMillis
+ + ", captive: " + mCaptive
+ + "}";
+ }
+}
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
new file mode 100644
index 0000000..6afdb5e
--- /dev/null
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.PersistableBundle;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * Class that provides utilities for collecting network connectivity diagnostics information.
+ * Connectivity information is made available through triggerable diagnostics tools and by listening
+ * to System validations. Some diagnostics information may be permissions-restricted.
+ *
+ * <p>ConnectivityDiagnosticsManager is intended for use by applications offering network
+ * connectivity on a user device. These tools will provide several mechanisms for these applications
+ * to be alerted to network conditions as well as diagnose potential network issues themselves.
+ *
+ * <p>The primary responsibilities of this class are to:
+ *
+ * <ul>
+ * <li>Allow permissioned applications to register and unregister callbacks for network event
+ * notifications
+ * <li>Invoke callbacks for network event notifications, including:
+ * <ul>
+ * <li>Network validations
+ * <li>Data stalls
+ * <li>Connectivity reports from applications
+ * </ul>
+ * </ul>
+ */
+public class ConnectivityDiagnosticsManager {
+ public static final int DETECTION_METHOD_DNS_EVENTS = 1;
+ public static final int DETECTION_METHOD_TCP_METRICS = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(
+ prefix = {"DETECTION_METHOD_"},
+ value = {DETECTION_METHOD_DNS_EVENTS, DETECTION_METHOD_TCP_METRICS})
+ public @interface DetectionMethod {}
+
+ /** @hide */
+ public ConnectivityDiagnosticsManager() {}
+
+ /** Class that includes connectivity information for a specific Network at a specific time. */
+ public static class ConnectivityReport {
+ /** The Network for which this ConnectivityReport applied */
+ @NonNull public final Network network;
+
+ /**
+ * The timestamp for the report. The timestamp is taken from {@link
+ * System#currentTimeMillis}.
+ */
+ public final long reportTimestamp;
+
+ /** LinkProperties available on the Network at the reported timestamp */
+ @NonNull public final LinkProperties linkProperties;
+
+ /** NetworkCapabilities available on the Network at the reported timestamp */
+ @NonNull public final NetworkCapabilities networkCapabilities;
+
+ /** PersistableBundle that may contain additional info about the report */
+ @NonNull public final PersistableBundle additionalInfo;
+
+ /**
+ * Constructor for ConnectivityReport.
+ *
+ * <p>Apps should obtain instances through {@link
+ * ConnectivityDiagnosticsCallback#onConnectivityReport} instead of instantiating their own
+ * instances (unless for testing purposes).
+ *
+ * @param network The Network for which this ConnectivityReport applies
+ * @param reportTimestamp The timestamp for the report
+ * @param linkProperties The LinkProperties available on network at reportTimestamp
+ * @param networkCapabilities The NetworkCapabilities available on network at
+ * reportTimestamp
+ * @param additionalInfo A PersistableBundle that may contain additional info about the
+ * report
+ */
+ public ConnectivityReport(
+ @NonNull Network network,
+ long reportTimestamp,
+ @NonNull LinkProperties linkProperties,
+ @NonNull NetworkCapabilities networkCapabilities,
+ @NonNull PersistableBundle additionalInfo) {
+ this.network = network;
+ this.reportTimestamp = reportTimestamp;
+ this.linkProperties = linkProperties;
+ this.networkCapabilities = networkCapabilities;
+ this.additionalInfo = additionalInfo;
+ }
+ }
+
+ /** Class that includes information for a suspected data stall on a specific Network */
+ public static class DataStallReport {
+ /** The Network for which this DataStallReport applied */
+ @NonNull public final Network network;
+
+ /**
+ * The timestamp for the report. The timestamp is taken from {@link
+ * System#currentTimeMillis}.
+ */
+ public final long reportTimestamp;
+
+ /** The detection method used to identify the suspected data stall */
+ @DetectionMethod public final int detectionMethod;
+
+ /** PersistableBundle that may contain additional information on the suspected data stall */
+ @NonNull public final PersistableBundle stallDetails;
+
+ /**
+ * Constructor for DataStallReport.
+ *
+ * <p>Apps should obtain instances through {@link
+ * ConnectivityDiagnosticsCallback#onDataStallSuspected} instead of instantiating their own
+ * instances (unless for testing purposes).
+ *
+ * @param network The Network for which this DataStallReport applies
+ * @param reportTimestamp The timestamp for the report
+ * @param detectionMethod The detection method used to identify this data stall
+ * @param stallDetails A PersistableBundle that may contain additional info about the report
+ */
+ public DataStallReport(
+ @NonNull Network network,
+ long reportTimestamp,
+ @DetectionMethod int detectionMethod,
+ @NonNull PersistableBundle stallDetails) {
+ this.network = network;
+ this.reportTimestamp = reportTimestamp;
+ this.detectionMethod = detectionMethod;
+ this.stallDetails = stallDetails;
+ }
+ }
+
+ /**
+ * Abstract base class for Connectivity Diagnostics callbacks. Used for notifications about
+ * network connectivity events. Must be extended by applications wanting notifications.
+ */
+ public abstract static class ConnectivityDiagnosticsCallback {
+ /**
+ * Called when the platform completes a data connectivity check. This will also be invoked
+ * upon registration with the latest report.
+ *
+ * <p>The Network specified in the ConnectivityReport may not be active any more when this
+ * method is invoked.
+ *
+ * @param report The ConnectivityReport containing information about a connectivity check
+ */
+ public void onConnectivityReport(@NonNull ConnectivityReport report) {}
+
+ /**
+ * Called when the platform suspects a data stall on some Network.
+ *
+ * <p>The Network specified in the DataStallReport may not be active any more when this
+ * method is invoked.
+ *
+ * @param report The DataStallReport containing information about the suspected data stall
+ */
+ public void onDataStallSuspected(@NonNull DataStallReport report) {}
+
+ /**
+ * Called when any app reports connectivity to the System.
+ *
+ * @param network The Network for which connectivity has been reported
+ * @param hasConnectivity The connectivity reported to the System
+ */
+ public void onNetworkConnectivityReported(
+ @NonNull Network network, boolean hasConnectivity) {}
+ }
+
+ /**
+ * Registers a ConnectivityDiagnosticsCallback with the System.
+ *
+ * <p>Only apps that offer network connectivity to the user are allowed to register callbacks.
+ * This includes:
+ *
+ * <ul>
+ * <li>Carrier apps with active subscriptions
+ * <li>Active VPNs
+ * <li>WiFi Suggesters
+ * </ul>
+ *
+ * <p>Callbacks will be limited to receiving notifications for networks over which apps provide
+ * connectivity.
+ *
+ * <p>If a registering app loses its relevant permissions, any callbacks it registered will
+ * silently stop receiving callbacks.
+ *
+ * <p>Each register() call <b>MUST</b> use a unique ConnectivityDiagnosticsCallback instance. If
+ * a single instance is registered with multiple NetworkRequests, an IllegalArgumentException
+ * will be thrown.
+ *
+ * @param request The NetworkRequest that will be used to match with Networks for which
+ * callbacks will be fired
+ * @param e The Executor to be used for running the callback method invocations
+ * @param callback The ConnectivityDiagnosticsCallback that the caller wants registered with the
+ * System
+ * @throws IllegalArgumentException if the same callback instance is registered with multiple
+ * NetworkRequests
+ * @throws SecurityException if the caller does not have appropriate permissions to register a
+ * callback
+ */
+ public void registerConnectivityDiagnosticsCallback(
+ @NonNull NetworkRequest request,
+ @NonNull Executor e,
+ @NonNull ConnectivityDiagnosticsCallback callback) {
+ // TODO(b/143187964): implement ConnectivityDiagnostics functionality
+ throw new UnsupportedOperationException("registerCallback() not supported yet");
+ }
+
+ /**
+ * Unregisters a ConnectivityDiagnosticsCallback with the System.
+ *
+ * <p>If the given callback is not currently registered with the System, this operation will be
+ * a no-op.
+ *
+ * @param callback The ConnectivityDiagnosticsCallback to be unregistered from the System.
+ */
+ public void unregisterConnectivityDiagnosticsCallback(
+ @NonNull ConnectivityDiagnosticsCallback callback) {
+ // TODO(b/143187964): implement ConnectivityDiagnostics functionality
+ throw new UnsupportedOperationException("registerCallback() not supported yet");
+ }
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 82cecb6..11c1a9c 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -27,8 +27,8 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.net.IpSecManager.UdpEncapsulationSocket;
@@ -363,7 +363,7 @@
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@UnsupportedAppUsage
public static final String ACTION_TETHER_STATE_CHANGED =
- "android.net.conn.TETHER_STATE_CHANGED";
+ TetheringManager.ACTION_TETHER_STATE_CHANGED;
/**
* @hide
@@ -371,14 +371,14 @@
* tethering and currently available for tethering.
*/
@UnsupportedAppUsage
- public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
+ public static final String EXTRA_AVAILABLE_TETHER = TetheringManager.EXTRA_AVAILABLE_TETHER;
/**
* @hide
* gives a String[] listing all the interfaces currently in local-only
* mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
*/
- public static final String EXTRA_ACTIVE_LOCAL_ONLY = "localOnlyArray";
+ public static final String EXTRA_ACTIVE_LOCAL_ONLY = TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
/**
* @hide
@@ -386,7 +386,7 @@
* (ie, has DHCPv4 support and packets potentially forwarded/NATed)
*/
@UnsupportedAppUsage
- public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
+ public static final String EXTRA_ACTIVE_TETHER = TetheringManager.EXTRA_ACTIVE_TETHER;
/**
* @hide
@@ -395,7 +395,7 @@
* for any interfaces listed here.
*/
@UnsupportedAppUsage
- public static final String EXTRA_ERRORED_TETHER = "erroredArray";
+ public static final String EXTRA_ERRORED_TETHER = TetheringManager.EXTRA_ERRORED_TETHER;
/**
* Broadcast Action: The captive portal tracker has finished its test.
@@ -445,7 +445,7 @@
* @see #startTethering(int, boolean, OnStartTetheringCallback)
* @hide
*/
- public static final int TETHERING_INVALID = -1;
+ public static final int TETHERING_INVALID = TetheringManager.TETHERING_INVALID;
/**
* Wifi tethering type.
@@ -453,7 +453,7 @@
* @hide
*/
@SystemApi
- public static final int TETHERING_WIFI = 0;
+ public static final int TETHERING_WIFI = TetheringManager.TETHERING_WIFI;
/**
* USB tethering type.
@@ -461,7 +461,7 @@
* @hide
*/
@SystemApi
- public static final int TETHERING_USB = 1;
+ public static final int TETHERING_USB = TetheringManager.TETHERING_USB;
/**
* Bluetooth tethering type.
@@ -469,7 +469,7 @@
* @hide
*/
@SystemApi
- public static final int TETHERING_BLUETOOTH = 2;
+ public static final int TETHERING_BLUETOOTH = TetheringManager.TETHERING_BLUETOOTH;
/**
* Wifi P2p tethering type.
@@ -477,47 +477,47 @@
* need to start from #startTethering(int, boolean, OnStartTetheringCallback).
* @hide
*/
- public static final int TETHERING_WIFI_P2P = 3;
+ public static final int TETHERING_WIFI_P2P = TetheringManager.TETHERING_WIFI_P2P;
/**
* Extra used for communicating with the TetherService. Includes the type of tethering to
* enable if any.
* @hide
*/
- public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
+ public static final String EXTRA_ADD_TETHER_TYPE = TetheringManager.EXTRA_ADD_TETHER_TYPE;
/**
* Extra used for communicating with the TetherService. Includes the type of tethering for
* which to cancel provisioning.
* @hide
*/
- public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
+ public static final String EXTRA_REM_TETHER_TYPE = TetheringManager.EXTRA_REM_TETHER_TYPE;
/**
* Extra used for communicating with the TetherService. True to schedule a recheck of tether
* provisioning.
* @hide
*/
- public static final String EXTRA_SET_ALARM = "extraSetAlarm";
+ public static final String EXTRA_SET_ALARM = TetheringManager.EXTRA_SET_ALARM;
/**
* Tells the TetherService to run a provision check now.
* @hide
*/
- public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
+ public static final String EXTRA_RUN_PROVISION = TetheringManager.EXTRA_RUN_PROVISION;
/**
* Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
* which will receive provisioning results. Can be left empty.
* @hide
*/
- public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
+ public static final String EXTRA_PROVISION_CALLBACK = TetheringManager.EXTRA_PROVISION_CALLBACK;
/**
* The absence of a connection type.
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
+ @SystemApi
public static final int TYPE_NONE = -1;
/**
@@ -662,7 +662,7 @@
* {@hide}
*/
@Deprecated
- @UnsupportedAppUsage
+ @SystemApi
public static final int TYPE_WIFI_P2P = 13;
/**
@@ -3107,6 +3107,61 @@
}
}
+ /**
+ * Registers the specified {@link NetworkProvider}.
+ * Each listener must only be registered once. The listener can be unregistered with
+ * {@link #unregisterNetworkProvider}.
+ *
+ * @param provider the provider to register
+ * @return the ID of the provider. This ID must be used by the provider when registering
+ * {@link android.net.NetworkAgent}s.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public int registerNetworkProvider(@NonNull NetworkProvider provider) {
+ if (provider.getProviderId() != NetworkProvider.ID_NONE) {
+ throw new IllegalStateException("NetworkProviders can only be registered once");
+ }
+
+ try {
+ int providerId = mService.registerNetworkProvider(provider.getMessenger(),
+ provider.getName());
+ provider.setProviderId(providerId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ return provider.getProviderId();
+ }
+
+ /**
+ * Unregisters the specified NetworkProvider.
+ *
+ * @param provider the provider to unregister
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void unregisterNetworkProvider(@NonNull NetworkProvider provider) {
+ try {
+ mService.unregisterNetworkProvider(provider.getMessenger());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ provider.setProviderId(NetworkProvider.ID_NONE);
+ }
+
+
+ /** @hide exposed via the NetworkProvider class. */
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
+ try {
+ mService.declareNetworkRequestUnfulfillable(request);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
// TODO : remove this method. It is a stopgap measure to help sheperding a number
// of dependent changes that would conflict throughout the automerger graph. Having this
// temporarily helps with the process of going through with all these dependent changes across
@@ -3114,26 +3169,25 @@
/**
* @hide
* Register a NetworkAgent with ConnectivityService.
- * @return NetID corresponding to NetworkAgent.
+ * @return Network corresponding to NetworkAgent.
*/
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
- public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
- NetworkCapabilities nc, int score, NetworkMisc misc) {
- return registerNetworkAgent(messenger, ni, lp, nc, score, misc,
- NetworkFactory.SerialNumber.NONE);
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
+ NetworkCapabilities nc, int score, NetworkAgentConfig config) {
+ return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE);
}
/**
* @hide
* Register a NetworkAgent with ConnectivityService.
- * @return NetID corresponding to NetworkAgent.
+ * @return Network corresponding to NetworkAgent.
*/
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
- public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
- NetworkCapabilities nc, int score, NetworkMisc misc, int factorySerialNumber) {
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
+ NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) {
+
try {
- return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc,
- factorySerialNumber);
+ return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3569,14 +3623,26 @@
/**
* Helper function to request a network with a particular legacy type.
*
- * This is temporarily public @hide so it can be called by system code that uses the
- * NetworkRequest API to request networks but relies on CONNECTIVITY_ACTION broadcasts for
- * instead network notifications.
+ * @deprecated This is temporarily public for tethering to backwards compatibility that uses
+ * the NetworkRequest API to request networks with legacy type and relies on
+ * CONNECTIVITY_ACTION broadcasts instead of NetworkCallbacks. New caller should use
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback, Handler)} instead.
*
* TODO: update said system code to rely on NetworkCallbacks and make this method private.
+
+ * @param request {@link NetworkRequest} describing this request.
+ * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+ * the callback must not be shared - it uniquely specifies this request.
+ * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
+ * before {@link NetworkCallback#onUnavailable()} is called. The timeout must
+ * be a positive value (i.e. >0).
+ * @param legacyType to specify the network type(#TYPE_*).
+ * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
*
* @hide
*/
+ @SystemApi
+ @Deprecated
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, int timeoutMs, int legacyType,
@NonNull Handler handler) {
diff --git a/core/java/android/net/DhcpInfo.java b/core/java/android/net/DhcpInfo.java
index 98bab44..912df67 100644
--- a/core/java/android/net/DhcpInfo.java
+++ b/core/java/android/net/DhcpInfo.java
@@ -16,8 +16,8 @@
package android.net;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
/**
* A simple object for retrieving the results of a DHCP request.
@@ -67,12 +67,12 @@
buf.append(NetworkUtils.intToInetAddress(addr).getHostAddress());
}
- /** Implement the Parcelable interface {@hide} */
+ /** Implement the Parcelable interface */
public int describeContents() {
return 0;
}
- /** Implement the Parcelable interface {@hide} */
+ /** Implement the Parcelable interface */
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(ipAddress);
dest.writeInt(gateway);
@@ -83,7 +83,7 @@
dest.writeInt(leaseDuration);
}
- /** Implement the Parcelable interface {@hide} */
+ /** Implement the Parcelable interface */
public static final @android.annotation.NonNull Creator<DhcpInfo> CREATOR =
new Creator<DhcpInfo>() {
public DhcpInfo createFromParcel(Parcel in) {
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index 97be51a..059cd94 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.shared.InetAddressUtils;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 7256502..fd015b4 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -17,7 +17,7 @@
package android.net;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
diff --git a/core/java/android/net/ICaptivePortal.aidl b/core/java/android/net/ICaptivePortal.aidl
index 707b4f6..fe21905 100644
--- a/core/java/android/net/ICaptivePortal.aidl
+++ b/core/java/android/net/ICaptivePortal.aidl
@@ -21,6 +21,7 @@
* @hide
*/
oneway interface ICaptivePortal {
+ void appRequest(int request);
void appResponse(int response);
void logEvent(int eventId, String packageName);
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 09c02ef..186196bd 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -20,9 +20,9 @@
import android.net.ConnectionInfo;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
-import android.net.NetworkMisc;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkState;
@@ -142,14 +142,19 @@
void setAirplaneMode(boolean enable);
- int registerNetworkFactory(in Messenger messenger, in String name);
-
boolean requestBandwidthUpdate(in Network network);
+ int registerNetworkFactory(in Messenger messenger, in String name);
void unregisterNetworkFactory(in Messenger messenger);
- int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
- in NetworkCapabilities nc, int score, in NetworkMisc misc, in int factorySerialNumber);
+ int registerNetworkProvider(in Messenger messenger, in String name);
+ void unregisterNetworkProvider(in Messenger messenger);
+
+ void declareNetworkRequestUnfulfillable(in NetworkRequest request);
+
+ Network registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
+ in NetworkCapabilities nc, int score, in NetworkAgentConfig config,
+ in int factorySerialNumber);
NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,
in Messenger messenger, int timeoutSec, in IBinder binder, int legacy);
diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl
index 10667ae..fe9141c 100644
--- a/core/java/android/net/INetworkPolicyListener.aidl
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -15,6 +15,7 @@
*/
package android.net;
+import android.telephony.SubscriptionPlan;
/** {@hide} */
oneway interface INetworkPolicyListener {
@@ -23,4 +24,5 @@
void onRestrictBackgroundChanged(boolean restrictBackground);
void onUidPoliciesChanged(int uid, int uidPolicies);
void onSubscriptionOverride(int subId, int overrideMask, int overrideValue);
+ void onSubscriptionPlansChanged(int subId, in SubscriptionPlan[] plans);
}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 385cb1d..72a6b39 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -57,9 +57,6 @@
@UnsupportedAppUsage
boolean getRestrictBackground();
- /** Callback used to change internal state on tethering */
- void onTetheringChanged(String iface, boolean tethering);
-
/** Gets the restrict background status based on the caller's UID:
1 - disabled
2 - whitelisted
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 9994f9f..5fa515a 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -23,6 +23,8 @@
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
+import android.net.netstats.provider.INetworkStatsProvider;
+import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.os.IBinder;
import android.os.Messenger;
import com.android.internal.net.VpnInfo;
@@ -89,4 +91,7 @@
/** Get the total network stats information since boot */
long getTotalStats(int type);
+ /** Registers a network stats provider */
+ INetworkStatsProviderCallback registerNetworkStatsProvider(String tag,
+ in INetworkStatsProvider provider);
}
diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java
index 1ae44e1..37425ff 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/InvalidPacketException.java b/core/java/android/net/InvalidPacketException.java
new file mode 100644
index 0000000..909998d
--- /dev/null
+++ b/core/java/android/net/InvalidPacketException.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Thrown when a packet is invalid.
+ * @hide
+ */
+@SystemApi
+public class InvalidPacketException extends Exception {
+ public final int error;
+
+ // Must match SocketKeepalive#ERROR_INVALID_IP_ADDRESS.
+ /** Invalid IP address. */
+ public static final int ERROR_INVALID_IP_ADDRESS = -21;
+
+ // Must match SocketKeepalive#ERROR_INVALID_PORT.
+ /** Invalid port number. */
+ public static final int ERROR_INVALID_PORT = -22;
+
+ // Must match SocketKeepalive#ERROR_INVALID_LENGTH.
+ /** Invalid packet length. */
+ public static final int ERROR_INVALID_LENGTH = -23;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "ERROR_" }, value = {
+ ERROR_INVALID_IP_ADDRESS,
+ ERROR_INVALID_PORT,
+ ERROR_INVALID_LENGTH
+ })
+ public @interface ErrorCode {}
+
+ /**
+ * This packet is invalid.
+ * See the error code for details.
+ */
+ public InvalidPacketException(@ErrorCode final int error) {
+ this.error = error;
+ }
+}
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
index dddb64d..23d5ff7 100644
--- a/core/java/android/net/IpConfiguration.java
+++ b/core/java/android/net/IpConfiguration.java
@@ -20,8 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
-import android.net.StaticIpConfiguration;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 45d0c73..09ec6c3 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -17,7 +17,6 @@
import static com.android.internal.util.Preconditions.checkNotNull;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
@@ -26,6 +25,7 @@
import android.annotation.TestApi;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.net.annotations.PolicyDirection;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -41,8 +41,6 @@
import java.io.FileDescriptor;
import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
@@ -78,11 +76,6 @@
*/
public static final int DIRECTION_OUT = 1;
- /** @hide */
- @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
- @Retention(RetentionPolicy.SOURCE)
- public @interface PolicyDirection {}
-
/**
* The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
*
diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java
index 9b8b732..2b8b7e6 100644
--- a/core/java/android/net/KeepalivePacketData.java
+++ b/core/java/android/net/KeepalivePacketData.java
@@ -16,13 +16,13 @@
package android.net;
-import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
-import static android.net.SocketKeepalive.ERROR_INVALID_PORT;
+import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS;
+import static android.net.InvalidPacketException.ERROR_INVALID_PORT;
-import android.net.SocketKeepalive.InvalidPacketException;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.net.util.IpUtils;
import android.os.Parcel;
-import android.os.Parcelable;
import android.util.Log;
import java.net.InetAddress;
@@ -33,13 +33,16 @@
*
* @hide
*/
-public class KeepalivePacketData implements Parcelable {
+@SystemApi
+public class KeepalivePacketData {
private static final String TAG = "KeepalivePacketData";
/** Source IP address */
+ @NonNull
public final InetAddress srcAddress;
/** Destination IP address */
+ @NonNull
public final InetAddress dstAddress;
/** Source port */
@@ -51,13 +54,14 @@
/** Packet data. A raw byte string of packet data, not including the link-layer header. */
private final byte[] mPacket;
- protected static final int IPV4_HEADER_LENGTH = 20;
- protected static final int UDP_HEADER_LENGTH = 8;
-
// This should only be constructed via static factory methods, such as
- // nattKeepalivePacket
- protected KeepalivePacketData(InetAddress srcAddress, int srcPort,
- InetAddress dstAddress, int dstPort, byte[] data) throws InvalidPacketException {
+ // nattKeepalivePacket.
+ /**
+ * A holding class for data necessary to build a keepalive packet.
+ */
+ protected KeepalivePacketData(@NonNull InetAddress srcAddress, int srcPort,
+ @NonNull InetAddress dstAddress, int dstPort,
+ @NonNull byte[] data) throws InvalidPacketException {
this.srcAddress = srcAddress;
this.dstAddress = dstAddress;
this.srcPort = srcPort;
@@ -78,16 +82,12 @@
}
}
+ @NonNull
public byte[] getPacket() {
return mPacket.clone();
}
- /* Parcelable Implementation */
- public int describeContents() {
- return 0;
- }
-
- /** Write to parcel */
+ /** @hide */
public void writeToParcel(Parcel out, int flags) {
out.writeString(srcAddress.getHostAddress());
out.writeString(dstAddress.getHostAddress());
@@ -96,6 +96,7 @@
out.writeByteArray(mPacket);
}
+ /** @hide */
protected KeepalivePacketData(Parcel in) {
srcAddress = NetworkUtils.numericToInetAddress(in.readString());
dstAddress = NetworkUtils.numericToInetAddress(in.readString());
@@ -103,17 +104,4 @@
dstPort = in.readInt();
mPacket = in.createByteArray();
}
-
- /** Parcelable Creator */
- public static final @android.annotation.NonNull Parcelable.Creator<KeepalivePacketData> CREATOR =
- new Parcelable.Creator<KeepalivePacketData>() {
- public KeepalivePacketData createFromParcel(Parcel in) {
- return new KeepalivePacketData(in);
- }
-
- public KeepalivePacketData[] newArray(int size) {
- return new KeepalivePacketData[size];
- }
- };
-
}
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 93dd2e4..bf8b38f 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -30,7 +30,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index ed509cb..ec773ef 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -63,12 +63,21 @@
private String mPrivateDnsServerName;
private String mDomains;
private ArrayList<RouteInfo> mRoutes = new ArrayList<>();
+ private Inet4Address mDhcpServerAddress;
private ProxyInfo mHttpProxy;
private int mMtu;
// in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
private String mTcpBufferSizes;
private IpPrefix mNat64Prefix;
private boolean mWakeOnLanSupported;
+ private Uri mCaptivePortalApiUrl;
+ private CaptivePortalData mCaptivePortalData;
+
+ /**
+ * Indicates whether parceling should preserve fields that are set based on permissions of
+ * the process receiving the {@link LinkProperties}.
+ */
+ private final transient boolean mParcelSensitiveFields;
private static final int MIN_MTU = 68;
private static final int MIN_MTU_V6 = 1280;
@@ -173,6 +182,7 @@
* Constructs a new {@code LinkProperties} with default values.
*/
public LinkProperties() {
+ mParcelSensitiveFields = false;
}
/**
@@ -181,25 +191,32 @@
@SystemApi
@TestApi
public LinkProperties(@Nullable LinkProperties source) {
- if (source != null) {
- mIfaceName = source.mIfaceName;
- mLinkAddresses.addAll(source.mLinkAddresses);
- mDnses.addAll(source.mDnses);
- mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses);
- mUsePrivateDns = source.mUsePrivateDns;
- mPrivateDnsServerName = source.mPrivateDnsServerName;
- mPcscfs.addAll(source.mPcscfs);
- mDomains = source.mDomains;
- mRoutes.addAll(source.mRoutes);
- mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy);
- for (LinkProperties l: source.mStackedLinks.values()) {
- addStackedLink(l);
- }
- setMtu(source.mMtu);
- mTcpBufferSizes = source.mTcpBufferSizes;
- mNat64Prefix = source.mNat64Prefix;
- mWakeOnLanSupported = source.mWakeOnLanSupported;
+ this(source, false /* parcelSensitiveFields */);
+ }
+
+ private LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) {
+ mParcelSensitiveFields = parcelSensitiveFields;
+ if (source == null) return;
+ mIfaceName = source.mIfaceName;
+ mLinkAddresses.addAll(source.mLinkAddresses);
+ mDnses.addAll(source.mDnses);
+ mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses);
+ mUsePrivateDns = source.mUsePrivateDns;
+ mPrivateDnsServerName = source.mPrivateDnsServerName;
+ mPcscfs.addAll(source.mPcscfs);
+ mDomains = source.mDomains;
+ mRoutes.addAll(source.mRoutes);
+ mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy);
+ for (LinkProperties l: source.mStackedLinks.values()) {
+ addStackedLink(l);
}
+ setMtu(source.mMtu);
+ setDhcpServerAddress(source.getDhcpServerAddress());
+ mTcpBufferSizes = source.mTcpBufferSizes;
+ mNat64Prefix = source.mNat64Prefix;
+ mWakeOnLanSupported = source.mWakeOnLanSupported;
+ mCaptivePortalApiUrl = source.mCaptivePortalApiUrl;
+ mCaptivePortalData = source.mCaptivePortalData;
}
/**
@@ -460,6 +477,24 @@
}
/**
+ * Set DHCP server address.
+ *
+ * @param serverAddress the server address to set.
+ */
+ public void setDhcpServerAddress(@Nullable Inet4Address serverAddress) {
+ mDhcpServerAddress = serverAddress;
+ }
+
+ /**
+ * Get DHCP server address
+ *
+ * @return The current DHCP server address.
+ */
+ public @Nullable Inet4Address getDhcpServerAddress() {
+ return mDhcpServerAddress;
+ }
+
+ /**
* Returns the private DNS server name that is in use. If not {@code null},
* private DNS is in strict mode. In this mode, applications should ensure
* that all DNS queries are encrypted and sent to this hostname and that
@@ -840,6 +875,11 @@
* Clears this object to its initial state.
*/
public void clear() {
+ if (mParcelSensitiveFields) {
+ throw new UnsupportedOperationException(
+ "Cannot clear LinkProperties when parcelSensitiveFields is set");
+ }
+
mIfaceName = null;
mLinkAddresses.clear();
mDnses.clear();
@@ -851,9 +891,12 @@
mHttpProxy = null;
mStackedLinks.clear();
mMtu = 0;
+ mDhcpServerAddress = null;
mTcpBufferSizes = null;
mNat64Prefix = null;
mWakeOnLanSupported = false;
+ mCaptivePortalApiUrl = null;
+ mCaptivePortalData = null;
}
/**
@@ -919,6 +962,19 @@
resultJoiner.add("WakeOnLanSupported: true");
}
+ if (mDhcpServerAddress != null) {
+ resultJoiner.add("ServerAddress:");
+ resultJoiner.add(mDhcpServerAddress.toString());
+ }
+
+ if (mCaptivePortalApiUrl != null) {
+ resultJoiner.add("CaptivePortalApiUrl: " + mCaptivePortalApiUrl);
+ }
+
+ if (mCaptivePortalData != null) {
+ resultJoiner.add("CaptivePortalData: " + mCaptivePortalData);
+ }
+
if (mTcpBufferSizes != null) {
resultJoiner.add("TcpBufferSizes:");
resultJoiner.add(mTcpBufferSizes);
@@ -1273,6 +1329,17 @@
}
/**
+ * Compares this {@code LinkProperties} DHCP server address against the target
+ *
+ * @param target LinkProperties to compare.
+ * @return {@code true} if both are identical, {@code false} otherwise.
+ * @hide
+ */
+ public boolean isIdenticalDhcpServerAddress(@NonNull LinkProperties target) {
+ return Objects.equals(mDhcpServerAddress, target.mDhcpServerAddress);
+ }
+
+ /**
* Compares this {@code LinkProperties} interface addresses against the target
*
* @param target LinkProperties to compare.
@@ -1442,6 +1509,28 @@
}
/**
+ * Compares this {@code LinkProperties}'s CaptivePortalApiUrl against the target.
+ *
+ * @param target LinkProperties to compare.
+ * @return {@code true} if both are identical, {@code false} otherwise.
+ * @hide
+ */
+ public boolean isIdenticalCaptivePortalApiUrl(LinkProperties target) {
+ return Objects.equals(mCaptivePortalApiUrl, target.mCaptivePortalApiUrl);
+ }
+
+ /**
+ * Compares this {@code LinkProperties}'s CaptivePortalData against the target.
+ *
+ * @param target LinkProperties to compare.
+ * @return {@code true} if both are identical, {@code false} otherwise.
+ * @hide
+ */
+ public boolean isIdenticalCaptivePortalData(LinkProperties target) {
+ return Objects.equals(mCaptivePortalData, target.mCaptivePortalData);
+ }
+
+ /**
* Set whether the network interface supports WakeOnLAN
*
* @param supported WakeOnLAN supported value
@@ -1462,6 +1551,73 @@
}
/**
+ * Set the URL of the captive portal API endpoint to get more information about the network.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public void setCaptivePortalApiUrl(@Nullable Uri url) {
+ mCaptivePortalApiUrl = url;
+ }
+
+ /**
+ * Get the URL of the captive portal API endpoint to get more information about the network.
+ *
+ * <p>This is null unless the application has
+ * {@link android.Manifest.permission.NETWORK_SETTINGS} or
+ * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions, and the network provided
+ * the URL.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @Nullable
+ public Uri getCaptivePortalApiUrl() {
+ return mCaptivePortalApiUrl;
+ }
+
+ /**
+ * Set the CaptivePortalData obtained from the captive portal API (RFC7710bis).
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public void setCaptivePortalData(@Nullable CaptivePortalData data) {
+ mCaptivePortalData = data;
+ }
+
+ /**
+ * Get the CaptivePortalData obtained from the captive portal API (RFC7710bis).
+ *
+ * <p>This is null unless the application has
+ * {@link android.Manifest.permission.NETWORK_SETTINGS} or
+ * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @Nullable
+ public CaptivePortalData getCaptivePortalData() {
+ return mCaptivePortalData;
+ }
+
+ /**
+ * Create a copy of this {@link LinkProperties} that will preserve fields that were set
+ * based on the permissions of the process that received this {@link LinkProperties}.
+ *
+ * <p>By default {@link LinkProperties} does not preserve such fields during parceling, as
+ * they should not be shared outside of the process that receives them without appropriate
+ * checks.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @NonNull
+ public LinkProperties makeSensitiveFieldsParcelingCopy() {
+ return new LinkProperties(this, true /* parcelSensitiveFields */);
+ }
+
+ /**
* Compares this {@code LinkProperties} instance against the target
* LinkProperties in {@code obj}. Two LinkPropertieses are equal if
* all their fields are equal in values.
@@ -1489,6 +1645,7 @@
*/
return isIdenticalInterfaceName(target)
&& isIdenticalAddresses(target)
+ && isIdenticalDhcpServerAddress(target)
&& isIdenticalDnses(target)
&& isIdenticalPrivateDns(target)
&& isIdenticalValidatedPrivateDnses(target)
@@ -1499,7 +1656,9 @@
&& isIdenticalMtu(target)
&& isIdenticalTcpBufferSizes(target)
&& isIdenticalNat64Prefix(target)
- && isIdenticalWakeOnLan(target);
+ && isIdenticalWakeOnLan(target)
+ && isIdenticalCaptivePortalApiUrl(target)
+ && isIdenticalCaptivePortalData(target);
}
/**
@@ -1613,10 +1772,12 @@
+ mMtu * 51
+ ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode())
+ (mUsePrivateDns ? 57 : 0)
+ + ((null == mDhcpServerAddress) ? 0 : mDhcpServerAddress.hashCode())
+ mPcscfs.size() * 67
+ ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode())
+ Objects.hash(mNat64Prefix)
- + (mWakeOnLanSupported ? 71 : 0);
+ + (mWakeOnLanSupported ? 71 : 0)
+ + Objects.hash(mCaptivePortalApiUrl, mCaptivePortalData);
}
/**
@@ -1635,6 +1796,7 @@
dest.writeString(mPrivateDnsServerName);
writeAddresses(dest, mPcscfs);
dest.writeString(mDomains);
+ writeAddress(dest, mDhcpServerAddress);
dest.writeInt(mMtu);
dest.writeString(mTcpBufferSizes);
dest.writeInt(mRoutes.size());
@@ -1654,6 +1816,8 @@
dest.writeList(stackedLinks);
dest.writeBoolean(mWakeOnLanSupported);
+ dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalApiUrl : null, 0);
+ dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalData : null, 0);
}
private static void writeAddresses(@NonNull Parcel dest, @NonNull List<InetAddress> list) {
@@ -1663,8 +1827,9 @@
}
}
- private static void writeAddress(@NonNull Parcel dest, @NonNull InetAddress addr) {
- dest.writeByteArray(addr.getAddress());
+ private static void writeAddress(@NonNull Parcel dest, @Nullable InetAddress addr) {
+ byte[] addressBytes = (addr == null ? null : addr.getAddress());
+ dest.writeByteArray(addressBytes);
if (addr instanceof Inet6Address) {
final Inet6Address v6Addr = (Inet6Address) addr;
final boolean hasScopeId = v6Addr.getScopeId() != 0;
@@ -1673,9 +1838,11 @@
}
}
- @NonNull
+ @Nullable
private static InetAddress readAddress(@NonNull Parcel p) throws UnknownHostException {
final byte[] addr = p.createByteArray();
+ if (addr == null) return null;
+
if (addr.length == INET6_ADDR_LENGTH) {
final boolean hasScopeId = p.readBoolean();
final int scopeId = hasScopeId ? p.readInt() : 0;
@@ -1722,6 +1889,10 @@
} catch (UnknownHostException e) { }
}
netProp.setDomains(in.readString());
+ try {
+ netProp.setDhcpServerAddress((Inet4Address) InetAddress
+ .getByAddress(in.createByteArray()));
+ } catch (UnknownHostException e) { }
netProp.setMtu(in.readInt());
netProp.setTcpBufferSizes(in.readString());
addressCount = in.readInt();
@@ -1738,6 +1909,9 @@
netProp.addStackedLink(stackedLink);
}
netProp.setWakeOnLanSupported(in.readBoolean());
+
+ netProp.setCaptivePortalApiUrl(in.readParcelable(null));
+ netProp.setCaptivePortalData(in.readParcelable(null));
return netProp;
}
diff --git a/core/java/android/net/LinkQualityInfo.java b/core/java/android/net/LinkQualityInfo.java
index 2e6915f..aa56cff 100644
--- a/core/java/android/net/LinkQualityInfo.java
+++ b/core/java/android/net/LinkQualityInfo.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index 6a2031b..5b38f78 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -16,7 +16,8 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.IOException;
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index b066a15..e80e3a6 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
import android.system.Int32Ref;
import android.system.Os;
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 8729514..74c9aac 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.wifi.WifiInfo;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/MobileLinkQualityInfo.java b/core/java/android/net/MobileLinkQualityInfo.java
index a10a14d..a65de6b 100644
--- a/core/java/android/net/MobileLinkQualityInfo.java
+++ b/core/java/android/net/MobileLinkQualityInfo.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
/**
diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java
index a77c244..bd39c13 100644
--- a/core/java/android/net/NattKeepalivePacketData.java
+++ b/core/java/android/net/NattKeepalivePacketData.java
@@ -16,10 +16,11 @@
package android.net;
-import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
-import static android.net.SocketKeepalive.ERROR_INVALID_PORT;
+import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS;
+import static android.net.InvalidPacketException.ERROR_INVALID_PORT;
-import android.net.SocketKeepalive.InvalidPacketException;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.net.util.IpUtils;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,17 +32,22 @@
import java.nio.ByteOrder;
/** @hide */
+@SystemApi
public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable {
+ private static final int IPV4_HEADER_LENGTH = 20;
+ private static final int UDP_HEADER_LENGTH = 8;
+
// This should only be constructed via static factory methods, such as
// nattKeepalivePacket
- private NattKeepalivePacketData(InetAddress srcAddress, int srcPort,
- InetAddress dstAddress, int dstPort, byte[] data) throws
+ public NattKeepalivePacketData(@NonNull InetAddress srcAddress, int srcPort,
+ @NonNull InetAddress dstAddress, int dstPort, @NonNull byte[] data) throws
InvalidPacketException {
super(srcAddress, srcPort, dstAddress, dstPort, data);
}
/**
* Factory method to create Nat-T keepalive packet structure.
+ * @hide
*/
public static NattKeepalivePacketData nattKeepalivePacket(
InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort)
@@ -85,7 +91,7 @@
}
/** Write to parcel */
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeString(srcAddress.getHostAddress());
out.writeString(dstAddress.getHostAddress());
out.writeInt(srcPort);
@@ -93,7 +99,7 @@
}
/** Parcelable Creator */
- public static final Parcelable.Creator<NattKeepalivePacketData> CREATOR =
+ public static final @NonNull Parcelable.Creator<NattKeepalivePacketData> CREATOR =
new Parcelable.Creator<NattKeepalivePacketData>() {
public NattKeepalivePacketData createFromParcel(Parcel in) {
final InetAddress srcAddress =
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index f12ba13..8d1ab33 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.system.ErrnoException;
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index ff4bf2d..7316dfa 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -17,7 +17,7 @@
package android.net;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
@@ -43,11 +43,10 @@
*
* @hide
*/
-public abstract class NetworkAgent extends Handler {
- // Guaranteed to be valid (not NETID_UNSET), otherwise registerNetworkAgent() would have thrown
- // an exception.
- public final int netId;
+public abstract class NetworkAgent {
+ public final Network network;
+ private final Handler mHandler;
private volatile AsyncChannel mAsyncChannel;
private final String LOG_TAG;
private static final boolean DBG = true;
@@ -58,7 +57,7 @@
private static final long BW_REFRESH_MIN_WIN_MS = 500;
private boolean mPollLceScheduled = false;
private AtomicBoolean mPollLcePending = new AtomicBoolean(false);
- public final int mFactorySerialNumber;
+ public final int mProviderId;
private static final int BASE = Protocol.BASE_NETWORK_AGENT;
@@ -219,25 +218,25 @@
// the entire tree.
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score) {
- this(looper, context, logTag, ni, nc, lp, score, null, NetworkFactory.SerialNumber.NONE);
+ this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE);
}
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
- NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
- this(looper, context, logTag, ni, nc, lp, score, misc, NetworkFactory.SerialNumber.NONE);
+ NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) {
+ this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE);
}
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
- NetworkCapabilities nc, LinkProperties lp, int score, int factorySerialNumber) {
- this(looper, context, logTag, ni, nc, lp, score, null, factorySerialNumber);
+ NetworkCapabilities nc, LinkProperties lp, int score, int providerId) {
+ this(looper, context, logTag, ni, nc, lp, score, null, providerId);
}
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
- NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc,
- int factorySerialNumber) {
- super(looper);
+ NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config,
+ int providerId) {
+ mHandler = new NetworkAgentHandler(looper);
LOG_TAG = logTag;
mContext = context;
- mFactorySerialNumber = factorySerialNumber;
+ mProviderId = providerId;
if (ni == null || nc == null || lp == null) {
throw new IllegalArgumentException();
}
@@ -245,117 +244,124 @@
if (VDBG) log("Registering NetworkAgent");
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
- netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
- new LinkProperties(lp), new NetworkCapabilities(nc), score, misc,
- factorySerialNumber);
+ network = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni),
+ new LinkProperties(lp), new NetworkCapabilities(nc), score, config,
+ providerId);
}
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
- if (mAsyncChannel != null) {
- log("Received new connection while already connected!");
- } else {
- if (VDBG) log("NetworkAgent fully connected");
- AsyncChannel ac = new AsyncChannel();
- ac.connected(null, this, msg.replyTo);
- ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
- AsyncChannel.STATUS_SUCCESSFUL);
- synchronized (mPreConnectedQueue) {
- mAsyncChannel = ac;
- for (Message m : mPreConnectedQueue) {
- ac.sendMessage(m);
- }
- mPreConnectedQueue.clear();
- }
- }
- break;
- }
- case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
- if (VDBG) log("CMD_CHANNEL_DISCONNECT");
- if (mAsyncChannel != null) mAsyncChannel.disconnect();
- break;
- }
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
- if (DBG) log("NetworkAgent channel lost");
- // let the client know CS is done with us.
- unwanted();
- synchronized (mPreConnectedQueue) {
- mAsyncChannel = null;
- }
- break;
- }
- case CMD_SUSPECT_BAD: {
- log("Unhandled Message " + msg);
- break;
- }
- case CMD_REQUEST_BANDWIDTH_UPDATE: {
- long currentTimeMs = System.currentTimeMillis();
- if (VDBG) {
- log("CMD_REQUEST_BANDWIDTH_UPDATE request received.");
- }
- if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) {
- mPollLceScheduled = false;
- if (mPollLcePending.getAndSet(true) == false) {
- pollLceData();
- }
- } else {
- // deliver the request at a later time rather than discard it completely.
- if (!mPollLceScheduled) {
- long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS -
- currentTimeMs + 1;
- mPollLceScheduled = sendEmptyMessageDelayed(
- CMD_REQUEST_BANDWIDTH_UPDATE, waitTime);
- }
- }
- break;
- }
- case CMD_REPORT_NETWORK_STATUS: {
- String redirectUrl = ((Bundle)msg.obj).getString(REDIRECT_URL_KEY);
- if (VDBG) {
- log("CMD_REPORT_NETWORK_STATUS(" +
- (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + redirectUrl);
- }
- networkStatus(msg.arg1, redirectUrl);
- break;
- }
- case CMD_SAVE_ACCEPT_UNVALIDATED: {
- saveAcceptUnvalidated(msg.arg1 != 0);
- break;
- }
- case CMD_START_SOCKET_KEEPALIVE: {
- startSocketKeepalive(msg);
- break;
- }
- case CMD_STOP_SOCKET_KEEPALIVE: {
- stopSocketKeepalive(msg);
- break;
- }
+ private class NetworkAgentHandler extends Handler {
+ NetworkAgentHandler(Looper looper) {
+ super(looper);
+ }
- case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: {
- ArrayList<Integer> thresholds =
- ((Bundle) msg.obj).getIntegerArrayList("thresholds");
- // TODO: Change signal strength thresholds API to use an ArrayList<Integer>
- // rather than convert to int[].
- int[] intThresholds = new int[(thresholds != null) ? thresholds.size() : 0];
- for (int i = 0; i < intThresholds.length; i++) {
- intThresholds[i] = thresholds.get(i);
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
+ if (mAsyncChannel != null) {
+ log("Received new connection while already connected!");
+ } else {
+ if (VDBG) log("NetworkAgent fully connected");
+ AsyncChannel ac = new AsyncChannel();
+ ac.connected(null, this, msg.replyTo);
+ ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+ AsyncChannel.STATUS_SUCCESSFUL);
+ synchronized (mPreConnectedQueue) {
+ mAsyncChannel = ac;
+ for (Message m : mPreConnectedQueue) {
+ ac.sendMessage(m);
+ }
+ mPreConnectedQueue.clear();
+ }
+ }
+ break;
}
- setSignalStrengthThresholds(intThresholds);
- break;
- }
- case CMD_PREVENT_AUTOMATIC_RECONNECT: {
- preventAutomaticReconnect();
- break;
- }
- case CMD_ADD_KEEPALIVE_PACKET_FILTER: {
- addKeepalivePacketFilter(msg);
- break;
- }
- case CMD_REMOVE_KEEPALIVE_PACKET_FILTER: {
- removeKeepalivePacketFilter(msg);
- break;
+ case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
+ if (VDBG) log("CMD_CHANNEL_DISCONNECT");
+ if (mAsyncChannel != null) mAsyncChannel.disconnect();
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ if (DBG) log("NetworkAgent channel lost");
+ // let the client know CS is done with us.
+ unwanted();
+ synchronized (mPreConnectedQueue) {
+ mAsyncChannel = null;
+ }
+ break;
+ }
+ case CMD_SUSPECT_BAD: {
+ log("Unhandled Message " + msg);
+ break;
+ }
+ case CMD_REQUEST_BANDWIDTH_UPDATE: {
+ long currentTimeMs = System.currentTimeMillis();
+ if (VDBG) {
+ log("CMD_REQUEST_BANDWIDTH_UPDATE request received.");
+ }
+ if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) {
+ mPollLceScheduled = false;
+ if (!mPollLcePending.getAndSet(true)) {
+ pollLceData();
+ }
+ } else {
+ // deliver the request at a later time rather than discard it completely.
+ if (!mPollLceScheduled) {
+ long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS
+ - currentTimeMs + 1;
+ mPollLceScheduled = sendEmptyMessageDelayed(
+ CMD_REQUEST_BANDWIDTH_UPDATE, waitTime);
+ }
+ }
+ break;
+ }
+ case CMD_REPORT_NETWORK_STATUS: {
+ String redirectUrl = ((Bundle) msg.obj).getString(REDIRECT_URL_KEY);
+ if (VDBG) {
+ log("CMD_REPORT_NETWORK_STATUS("
+ + (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ")
+ + redirectUrl);
+ }
+ networkStatus(msg.arg1, redirectUrl);
+ break;
+ }
+ case CMD_SAVE_ACCEPT_UNVALIDATED: {
+ saveAcceptUnvalidated(msg.arg1 != 0);
+ break;
+ }
+ case CMD_START_SOCKET_KEEPALIVE: {
+ startSocketKeepalive(msg);
+ break;
+ }
+ case CMD_STOP_SOCKET_KEEPALIVE: {
+ stopSocketKeepalive(msg);
+ break;
+ }
+
+ case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: {
+ ArrayList<Integer> thresholds =
+ ((Bundle) msg.obj).getIntegerArrayList("thresholds");
+ // TODO: Change signal strength thresholds API to use an ArrayList<Integer>
+ // rather than convert to int[].
+ int[] intThresholds = new int[(thresholds != null) ? thresholds.size() : 0];
+ for (int i = 0; i < intThresholds.length; i++) {
+ intThresholds[i] = thresholds.get(i);
+ }
+ setSignalStrengthThresholds(intThresholds);
+ break;
+ }
+ case CMD_PREVENT_AUTOMATIC_RECONNECT: {
+ preventAutomaticReconnect();
+ break;
+ }
+ case CMD_ADD_KEEPALIVE_PACKET_FILTER: {
+ addKeepalivePacketFilter(msg);
+ break;
+ }
+ case CMD_REMOVE_KEEPALIVE_PACKET_FILTER: {
+ removeKeepalivePacketFilter(msg);
+ break;
+ }
}
}
}
diff --git a/core/java/android/net/NetworkMisc.aidl b/core/java/android/net/NetworkAgentConfig.aidl
similarity index 95%
rename from core/java/android/net/NetworkMisc.aidl
rename to core/java/android/net/NetworkAgentConfig.aidl
index c65583f..cb70bdd 100644
--- a/core/java/android/net/NetworkMisc.aidl
+++ b/core/java/android/net/NetworkAgentConfig.aidl
@@ -16,4 +16,4 @@
package android.net;
-parcelable NetworkMisc;
+parcelable NetworkAgentConfig;
diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java
new file mode 100644
index 0000000..abc6b67
--- /dev/null
+++ b/core/java/android/net/NetworkAgentConfig.java
@@ -0,0 +1,230 @@
+/*
+ * 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.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+/**
+ * Allows a network transport to provide the system with policy and configuration information about
+ * a particular network when registering a {@link NetworkAgent}. This information cannot change once
+ * the agent is registered.
+ *
+ * @hide
+ */
+@SystemApi
+public final class NetworkAgentConfig implements Parcelable {
+
+ /**
+ * If the {@link Network} is a VPN, whether apps are allowed to bypass the
+ * VPN. This is set by a {@link VpnService} and used by
+ * {@link ConnectivityManager} when creating a VPN.
+ *
+ * @hide
+ */
+ public boolean allowBypass;
+
+ /**
+ * Set if the network was manually/explicitly connected to by the user either from settings
+ * or a 3rd party app. For example, turning on cell data is not explicit but tapping on a wifi
+ * ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to
+ * connect to a particular access point is also explicit, though this may change in the future
+ * as we want apps to use the multinetwork apis.
+ *
+ * @hide
+ */
+ public boolean explicitlySelected;
+
+ /**
+ * Set if the user desires to use this network even if it is unvalidated. This field has meaning
+ * only if {@link explicitlySelected} is true. If it is, this field must also be set to the
+ * appropriate value based on previous user choice.
+ *
+ * @hide
+ */
+ public boolean acceptUnvalidated;
+
+ /**
+ * Whether the user explicitly set that this network should be validated even if presence of
+ * only partial internet connectivity.
+ *
+ * @hide
+ */
+ public boolean acceptPartialConnectivity;
+
+ /**
+ * Set to avoid surfacing the "Sign in to network" notification.
+ * if carrier receivers/apps are registered to handle the carrier-specific provisioning
+ * procedure, a carrier specific provisioning notification will be placed.
+ * only one notification should be displayed. This field is set based on
+ * which notification should be used for provisioning.
+ *
+ * @hide
+ */
+ public boolean provisioningNotificationDisabled;
+
+ /**
+ *
+ * @return whether the sign in to network notification is enabled by this configuration.
+ */
+ public boolean isProvisioningNotificationEnabled() {
+ return !provisioningNotificationDisabled;
+ }
+
+ /**
+ * For mobile networks, this is the subscriber ID (such as IMSI).
+ *
+ * @hide
+ */
+ public String subscriberId;
+
+ /**
+ * @return the subscriber ID, or null if none.
+ */
+ @Nullable
+ public String getSubscriberId() {
+ return subscriberId;
+ }
+
+ /**
+ * Set to skip 464xlat. This means the device will treat the network as IPv6-only and
+ * will not attempt to detect a NAT64 via RFC 7050 DNS lookups.
+ *
+ * @hide
+ */
+ public boolean skip464xlat;
+
+ /**
+ * @return whether NAT64 prefix detection is enabled.
+ */
+ public boolean isNat64DetectionEnabled() {
+ return !skip464xlat;
+ }
+
+ /**
+ * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network.
+ * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode.
+ *
+ * @hide
+ */
+ public boolean hasShownBroken;
+
+ /** @hide */
+ public NetworkAgentConfig() {
+ }
+
+ /** @hide */
+ public NetworkAgentConfig(@Nullable NetworkAgentConfig nac) {
+ if (nac != null) {
+ allowBypass = nac.allowBypass;
+ explicitlySelected = nac.explicitlySelected;
+ acceptUnvalidated = nac.acceptUnvalidated;
+ subscriberId = nac.subscriberId;
+ provisioningNotificationDisabled = nac.provisioningNotificationDisabled;
+ skip464xlat = nac.skip464xlat;
+ }
+ }
+
+ /**
+ * Builder class to facilitate constructing {@link NetworkAgentConfig} objects.
+ */
+ public static class Builder {
+ private final NetworkAgentConfig mConfig = new NetworkAgentConfig();
+
+ /**
+ * Sets the subscriber ID for this network.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder setSubscriberId(@Nullable String subscriberId) {
+ mConfig.subscriberId = subscriberId;
+ return this;
+ }
+
+ /**
+ * Disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to save power
+ * and reduce idle traffic on networks that are known to be IPv6-only without a NAT64.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder disableNat64Detection() {
+ mConfig.skip464xlat = true;
+ return this;
+ }
+
+ /**
+ * Disables the "Sign in to network" notification. Used if the network transport will
+ * perform its own carrier-specific provisioning procedure.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder disableProvisioningNotification() {
+ mConfig.provisioningNotificationDisabled = true;
+ return this;
+ }
+
+ /**
+ * Returns the constructed {@link NetworkAgentConfig} object.
+ */
+ @NonNull
+ public NetworkAgentConfig build() {
+ return mConfig;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeInt(allowBypass ? 1 : 0);
+ out.writeInt(explicitlySelected ? 1 : 0);
+ out.writeInt(acceptUnvalidated ? 1 : 0);
+ out.writeString(subscriberId);
+ out.writeInt(provisioningNotificationDisabled ? 1 : 0);
+ out.writeInt(skip464xlat ? 1 : 0);
+ }
+
+ public static final @NonNull Creator<NetworkAgentConfig> CREATOR =
+ new Creator<NetworkAgentConfig>() {
+ @Override
+ public NetworkAgentConfig createFromParcel(Parcel in) {
+ NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
+ networkAgentConfig.allowBypass = in.readInt() != 0;
+ networkAgentConfig.explicitlySelected = in.readInt() != 0;
+ networkAgentConfig.acceptUnvalidated = in.readInt() != 0;
+ networkAgentConfig.subscriberId = in.readString();
+ networkAgentConfig.provisioningNotificationDisabled = in.readInt() != 0;
+ networkAgentConfig.skip464xlat = in.readInt() != 0;
+ return networkAgentConfig;
+ }
+
+ @Override
+ public NetworkAgentConfig[] newArray(int size) {
+ return new NetworkAgentConfig[size];
+ }
+ };
+}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 421e61b..8ebd139 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.ConnectivityManager.NetworkCallback;
import android.os.Build;
import android.os.Parcel;
@@ -587,15 +587,14 @@
}
/**
- * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are
- * typically provided by restricted networks.
+ * Deduces that all the capabilities it provides are typically provided by restricted networks
+ * or not.
*
- * TODO: consider:
- * - Renaming it to guessRestrictedCapability and make it set the
- * restricted capability bit in addition to clearing it.
+ * @return {@code true} if the network should be restricted.
* @hide
*/
- public void maybeMarkCapabilitiesRestricted() {
+ @SystemApi
+ public boolean deduceRestrictedCapability() {
// Check if we have any capability that forces the network to be restricted.
final boolean forceRestrictedCapability =
(mNetworkCapabilities & FORCE_RESTRICTED_CAPABILITIES) != 0;
@@ -609,8 +608,17 @@
final boolean hasRestrictedCapabilities =
(mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0;
- if (forceRestrictedCapability
- || (hasRestrictedCapabilities && !hasUnrestrictedCapabilities)) {
+ return forceRestrictedCapability
+ || (hasRestrictedCapabilities && !hasUnrestrictedCapabilities);
+ }
+
+ /**
+ * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if deducing the network is restricted.
+ *
+ * @hide
+ */
+ public void maybeMarkCapabilitiesRestricted() {
+ if (deduceRestrictedCapability()) {
removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
}
}
@@ -1275,6 +1283,7 @@
* Gets the SSID of this network, or null if none or unknown.
* @hide
*/
+ @SystemApi
public @Nullable String getSSID() {
return mSSID;
}
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index 5b1d12c..e271037 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -16,7 +16,8 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.NonNull;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
@@ -27,7 +28,6 @@
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Protocol;
@@ -52,7 +52,7 @@
* @hide
**/
public class NetworkFactory extends Handler {
- /** @hide */
+ /* TODO: delete when all callers have migrated to NetworkProvider IDs. */
public static class SerialNumber {
// Guard used by no network factory.
public static final int NONE = -1;
@@ -91,8 +91,8 @@
* with the same NetworkRequest but an updated score.
* Also, network conditions may change for this bearer
* allowing for a better score in the future.
- * msg.arg2 = the serial number of the factory currently responsible for the
- * NetworkAgent handling this request, or SerialNumber.NONE if none.
+ * msg.arg2 = the ID of the NetworkProvider currently responsible for the
+ * NetworkAgent handling this request, or NetworkProvider.ID_NONE if none.
*/
public static final int CMD_REQUEST_NETWORK = BASE;
@@ -115,16 +115,8 @@
*/
private static final int CMD_SET_FILTER = BASE + 3;
- /**
- * Sent by NetworkFactory to ConnectivityService to indicate that a request is
- * unfulfillable.
- * @see #releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest).
- */
- public static final int EVENT_UNFULFILLABLE_REQUEST = BASE + 4;
-
private final Context mContext;
private final ArrayList<Message> mPreConnectedQueue = new ArrayList<Message>();
- private AsyncChannel mAsyncChannel;
private final String LOG_TAG;
private final SparseArray<NetworkRequestInfo> mNetworkRequests =
@@ -135,7 +127,8 @@
private int mRefCount = 0;
private Messenger mMessenger = null;
- private int mSerialNumber;
+ private NetworkProvider mProvider = null;
+ private int mProviderId;
@UnsupportedAppUsage
public NetworkFactory(Looper looper, Context context, String logTag,
@@ -147,55 +140,43 @@
}
public void register() {
- if (DBG) log("Registering NetworkFactory");
- if (mMessenger == null) {
- mMessenger = new Messenger(this);
- mSerialNumber = ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger,
- LOG_TAG);
+ if (mProvider != null) {
+ Log.e(LOG_TAG, "Ignoring attempt to register already-registered NetworkFactory");
+ return;
}
+ if (DBG) log("Registering NetworkFactory");
+
+ mProvider = new NetworkProvider(mContext, NetworkFactory.this.getLooper(), LOG_TAG) {
+ @Override
+ public void onNetworkRequested(@NonNull NetworkRequest request, int score,
+ int servingProviderId) {
+ handleAddRequest((NetworkRequest) request, score, servingProviderId);
+ }
+
+ @Override
+ public void onRequestWithdrawn(@NonNull NetworkRequest request) {
+ handleRemoveRequest(request);
+ }
+ };
+
+ mMessenger = new Messenger(this);
+ mProviderId = ConnectivityManager.from(mContext).registerNetworkProvider(mProvider);
}
public void unregister() {
- if (DBG) log("Unregistering NetworkFactory");
- if (mMessenger != null) {
- ConnectivityManager.from(mContext).unregisterNetworkFactory(mMessenger);
- mMessenger = null;
+ if (mProvider == null) {
+ Log.e(LOG_TAG, "Ignoring attempt to unregister unregistered NetworkFactory");
+ return;
}
+ if (DBG) log("Unregistering NetworkFactory");
+
+ ConnectivityManager.from(mContext).unregisterNetworkProvider(mProvider);
+ mProvider = null;
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
- if (mAsyncChannel != null) {
- log("Received new connection while already connected!");
- break;
- }
- if (VDBG) log("NetworkFactory fully connected");
- AsyncChannel ac = new AsyncChannel();
- ac.connected(null, this, msg.replyTo);
- ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
- AsyncChannel.STATUS_SUCCESSFUL);
- mAsyncChannel = ac;
- for (Message m : mPreConnectedQueue) {
- ac.sendMessage(m);
- }
- mPreConnectedQueue.clear();
- break;
- }
- case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
- if (VDBG) log("CMD_CHANNEL_DISCONNECT");
- if (mAsyncChannel != null) {
- mAsyncChannel.disconnect();
- mAsyncChannel = null;
- }
- break;
- }
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
- if (DBG) log("NetworkFactory channel lost");
- mAsyncChannel = null;
- break;
- }
case CMD_REQUEST_NETWORK: {
handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
break;
@@ -219,13 +200,13 @@
public final NetworkRequest request;
public int score;
public boolean requested; // do we have a request outstanding, limited by score
- public int factorySerialNumber;
+ public int providerId;
- NetworkRequestInfo(NetworkRequest request, int score, int factorySerialNumber) {
+ NetworkRequestInfo(NetworkRequest request, int score, int providerId) {
this.request = request;
this.score = score;
this.requested = false;
- this.factorySerialNumber = factorySerialNumber;
+ this.providerId = providerId;
}
@Override
@@ -240,8 +221,6 @@
*
* @param request the request to handle.
* @param score the score of the NetworkAgent currently satisfying this request.
- * @param servingFactorySerialNumber the serial number of the NetworkFactory that
- * created the NetworkAgent currently satisfying this request.
*/
// TODO : remove this method. It is a stopgap measure to help sheperding a number
// of dependent changes that would conflict throughout the automerger graph. Having this
@@ -249,7 +228,7 @@
// the entire tree.
@VisibleForTesting
protected void handleAddRequest(NetworkRequest request, int score) {
- handleAddRequest(request, score, SerialNumber.NONE);
+ handleAddRequest(request, score, NetworkProvider.ID_NONE);
}
/**
@@ -258,27 +237,26 @@
*
* @param request the request to handle.
* @param score the score of the NetworkAgent currently satisfying this request.
- * @param servingFactorySerialNumber the serial number of the NetworkFactory that
- * created the NetworkAgent currently satisfying this request.
+ * @param servingProviderId the ID of the NetworkProvider that created the NetworkAgent
+ * currently satisfying this request.
*/
@VisibleForTesting
- protected void handleAddRequest(NetworkRequest request, int score,
- int servingFactorySerialNumber) {
+ protected void handleAddRequest(NetworkRequest request, int score, int servingProviderId) {
NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
if (n == null) {
if (DBG) {
log("got request " + request + " with score " + score
- + " and serial " + servingFactorySerialNumber);
+ + " and providerId " + servingProviderId);
}
- n = new NetworkRequestInfo(request, score, servingFactorySerialNumber);
+ n = new NetworkRequestInfo(request, score, servingProviderId);
mNetworkRequests.put(n.request.requestId, n);
} else {
if (VDBG) {
log("new score " + score + " for exisiting request " + request
- + " with serial " + servingFactorySerialNumber);
+ + " and providerId " + servingProviderId);
}
n.score = score;
- n.factorySerialNumber = servingFactorySerialNumber;
+ n.providerId = servingProviderId;
}
if (VDBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
@@ -333,8 +311,8 @@
log(" n.requests = " + n.requested);
log(" n.score = " + n.score);
log(" mScore = " + mScore);
- log(" n.factorySerialNumber = " + n.factorySerialNumber);
- log(" mSerialNumber = " + mSerialNumber);
+ log(" n.providerId = " + n.providerId);
+ log(" mProviderId = " + mProviderId);
}
if (shouldNeedNetworkFor(n)) {
if (VDBG) log(" needNetworkFor");
@@ -355,7 +333,7 @@
// If the score of this request is higher or equal to that of this factory and some
// other factory is responsible for it, then this factory should not track the request
// because it has no hope of satisfying it.
- && (n.score < mScore || n.factorySerialNumber == mSerialNumber)
+ && (n.score < mScore || n.providerId == mProviderId)
// If this factory can't satisfy the capability needs of this request, then it
// should not be tracked.
&& n.request.networkCapabilities.satisfiedByNetworkCapabilities(mCapabilityFilter)
@@ -373,7 +351,7 @@
// assigned to the factory
// - This factory can't satisfy the capability needs of the request
// - The concrete implementation of the factory rejects the request
- && ((n.score > mScore && n.factorySerialNumber != mSerialNumber)
+ && ((n.score > mScore && n.providerId != mProviderId)
|| !n.request.networkCapabilities.satisfiedByNetworkCapabilities(
mCapabilityFilter)
|| !acceptRequest(n.request, n.score));
@@ -408,12 +386,7 @@
protected void releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest r) {
post(() -> {
if (DBG) log("releaseRequestAsUnfulfillableByAnyFactory: " + r);
- Message msg = obtainMessage(EVENT_UNFULFILLABLE_REQUEST, r);
- if (mAsyncChannel != null) {
- mAsyncChannel.sendMessage(msg);
- } else {
- mPreConnectedQueue.add(msg);
- }
+ ConnectivityManager.from(mContext).declareNetworkRequestUnfulfillable(r);
});
}
@@ -444,8 +417,13 @@
return mNetworkRequests.size();
}
+ /* TODO: delete when all callers have migrated to NetworkProvider IDs. */
public int getSerialNumber() {
- return mSerialNumber;
+ return mProviderId;
+ }
+
+ public int getProviderId() {
+ return mProviderId;
}
protected void log(String s) {
@@ -465,8 +443,8 @@
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - mSerialNumber=")
- .append(mSerialNumber).append(", ScoreFilter=")
+ StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - mProviderId=")
+ .append(mProviderId).append(", ScoreFilter=")
.append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=")
.append(mNetworkRequests.size()).append(", refCount=").append(mRefCount)
.append("}");
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 92f105f..d0c5363 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -17,7 +17,7 @@
package android.net;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
deleted file mode 100644
index 4ad52d5..0000000
--- a/core/java/android/net/NetworkMisc.java
+++ /dev/null
@@ -1,133 +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.net;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * A grab-bag of information (metadata, policies, properties, etc) about a
- * {@link Network}. Since this contains PII, it should not be sent outside the
- * system.
- *
- * @hide
- */
-public class NetworkMisc implements Parcelable {
-
- /**
- * If the {@link Network} is a VPN, whether apps are allowed to bypass the
- * VPN. This is set by a {@link VpnService} and used by
- * {@link ConnectivityManager} when creating a VPN.
- */
- public boolean allowBypass;
-
- /**
- * Set if the network was manually/explicitly connected to by the user either from settings
- * or a 3rd party app. For example, turning on cell data is not explicit but tapping on a wifi
- * ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to
- * connect to a particular access point is also explicit, though this may change in the future
- * as we want apps to use the multinetwork apis.
- */
- public boolean explicitlySelected;
-
- /**
- * Set if the user desires to use this network even if it is unvalidated. This field has meaning
- * only if {@link explicitlySelected} is true. If it is, this field must also be set to the
- * appropriate value based on previous user choice.
- */
- public boolean acceptUnvalidated;
-
- /**
- * Whether the user explicitly set that this network should be validated even if presence of
- * only partial internet connectivity.
- */
- public boolean acceptPartialConnectivity;
-
- /**
- * Set to avoid surfacing the "Sign in to network" notification.
- * if carrier receivers/apps are registered to handle the carrier-specific provisioning
- * procedure, a carrier specific provisioning notification will be placed.
- * only one notification should be displayed. This field is set based on
- * which notification should be used for provisioning.
- */
- public boolean provisioningNotificationDisabled;
-
- /**
- * For mobile networks, this is the subscriber ID (such as IMSI).
- */
- public String subscriberId;
-
- /**
- * Set to skip 464xlat. This means the device will treat the network as IPv6-only and
- * will not attempt to detect a NAT64 via RFC 7050 DNS lookups.
- */
- public boolean skip464xlat;
-
- /**
- * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network.
- * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode.
- */
- public boolean hasShownBroken;
-
- public NetworkMisc() {
- }
-
- public NetworkMisc(NetworkMisc nm) {
- if (nm != null) {
- allowBypass = nm.allowBypass;
- explicitlySelected = nm.explicitlySelected;
- acceptUnvalidated = nm.acceptUnvalidated;
- subscriberId = nm.subscriberId;
- provisioningNotificationDisabled = nm.provisioningNotificationDisabled;
- skip464xlat = nm.skip464xlat;
- }
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(allowBypass ? 1 : 0);
- out.writeInt(explicitlySelected ? 1 : 0);
- out.writeInt(acceptUnvalidated ? 1 : 0);
- out.writeString(subscriberId);
- out.writeInt(provisioningNotificationDisabled ? 1 : 0);
- out.writeInt(skip464xlat ? 1 : 0);
- }
-
- public static final @android.annotation.NonNull Creator<NetworkMisc> CREATOR = new Creator<NetworkMisc>() {
- @Override
- public NetworkMisc createFromParcel(Parcel in) {
- NetworkMisc networkMisc = new NetworkMisc();
- networkMisc.allowBypass = in.readInt() != 0;
- networkMisc.explicitlySelected = in.readInt() != 0;
- networkMisc.acceptUnvalidated = in.readInt() != 0;
- networkMisc.subscriberId = in.readString();
- networkMisc.provisioningNotificationDisabled = in.readInt() != 0;
- networkMisc.skip464xlat = in.readInt() != 0;
- return networkMisc;
- }
-
- @Override
- public NetworkMisc[] newArray(int size) {
- return new NetworkMisc[size];
- }
- };
-}
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 33baebb..4f05c9b 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.BackupUtils;
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index bf27262..de962f8 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -19,8 +19,8 @@
import static android.content.pm.PackageManager.GET_SIGNATURES;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -31,6 +31,7 @@
import android.os.Build;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.telephony.SubscriptionPlan;
import android.util.DebugUtils;
import android.util.Pair;
import android.util.Range;
@@ -380,6 +381,8 @@
@Override public void onMeteredIfacesChanged(String[] meteredIfaces) { }
@Override public void onRestrictBackgroundChanged(boolean restrictBackground) { }
@Override public void onUidPoliciesChanged(int uid, int uidPolicies) { }
- @Override public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) { }
+ @Override public void onSubscriptionOverride(int subId, int overrideMask,
+ int overrideValue) { }
+ @Override public void onSubscriptionPlansChanged(int subId, SubscriptionPlan[] plans) { }
}
}
diff --git a/core/java/android/net/NetworkProvider.java b/core/java/android/net/NetworkProvider.java
new file mode 100644
index 0000000..2c0e4aa
--- /dev/null
+++ b/core/java/android/net/NetworkProvider.java
@@ -0,0 +1,166 @@
+/*
+ * 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.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.util.Log;
+
+/**
+ * Base class for network providers such as telephony or Wi-Fi. NetworkProviders connect the device
+ * to networks and makes them available to to the core network stack by creating
+ * {@link NetworkAgent}s. The networks can then provide connectivity to apps and can be interacted
+ * with via networking APIs such as {@link ConnectivityManager}.
+ *
+ * Subclasses should implement {@link #onNetworkRequested} and {@link #onRequestWithdrawn} to
+ * receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the
+ * best (highest-scoring) network for any request is generally not used by the system, and torn
+ * down.
+ *
+ * @hide
+ */
+@SystemApi
+public class NetworkProvider {
+ /**
+ * {@code providerId} value that indicates the absence of a provider. It is the providerId of
+ * any NetworkProvider that is not currently registered, and of any NetworkRequest that is not
+ * currently being satisfied by a network.
+ */
+ public static final int ID_NONE = -1;
+
+ /**
+ * A hardcoded ID for NetworkAgents representing VPNs. These agents are not created by any
+ * provider, so they use this constant for clarity instead of NONE.
+ * @hide only used by ConnectivityService.
+ */
+ public static final int ID_VPN = -2;
+
+ /**
+ * The first providerId value that will be allocated.
+ * @hide only used by ConnectivityService.
+ */
+ public static final int FIRST_PROVIDER_ID = 1;
+
+ /** @hide only used by ConnectivityService */
+ public static final int CMD_REQUEST_NETWORK = 1;
+ /** @hide only used by ConnectivityService */
+ public static final int CMD_CANCEL_REQUEST = 2;
+
+ private final Messenger mMessenger;
+ private final String mName;
+ private final ConnectivityManager mCm;
+
+ private int mProviderId = ID_NONE;
+
+ /**
+ * Constructs a new NetworkProvider.
+ *
+ * @param looper the Looper on which to run {@link #onNetworkRequested} and
+ * {@link #onRequestWithdrawn}.
+ * @param name the name of the listener, used only for debugging.
+ *
+ * @hide
+ */
+ @SystemApi
+ public NetworkProvider(@NonNull Context context, @NonNull Looper looper, @NonNull String name) {
+ mCm = ConnectivityManager.from(context);
+
+ Handler handler = new Handler(looper) {
+ @Override
+ public void handleMessage(Message m) {
+ switch (m.what) {
+ case CMD_REQUEST_NETWORK:
+ onNetworkRequested((NetworkRequest) m.obj, m.arg1, m.arg2);
+ break;
+ case CMD_CANCEL_REQUEST:
+ onRequestWithdrawn((NetworkRequest) m.obj);
+ break;
+ default:
+ Log.e(mName, "Unhandled message: " + m.what);
+ }
+ }
+ };
+ mMessenger = new Messenger(handler);
+ mName = name;
+ }
+
+ // TODO: consider adding a register() method so ConnectivityManager does not need to call this.
+ public @Nullable Messenger getMessenger() {
+ return mMessenger;
+ }
+
+ public @NonNull String getName() {
+ return mName;
+ }
+
+ /**
+ * Returns the ID of this provider. This is known only once the provider is registered via
+ * {@link ConnectivityManager#registerNetworkProvider()}, otherwise the ID is {@link #ID_NONE}.
+ * This ID must be used when registering any {@link NetworkAgent}s.
+ */
+ public int getProviderId() {
+ return mProviderId;
+ }
+
+ /** @hide */
+ public void setProviderId(int providerId) {
+ mProviderId = providerId;
+ }
+
+ /**
+ * Called when a NetworkRequest is received. The request may be a new request or an existing
+ * request with a different score.
+ *
+ * @param request the NetworkRequest being received
+ * @param score the score of the network currently satisfying the request, or 0 if none.
+ * @param providerId the ID of the provider that created the network currently satisfying this
+ * request, or {@link #ID_NONE} if none.
+ *
+ * @hide
+ */
+ @SystemApi
+ public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {}
+
+ /**
+ * Called when a NetworkRequest is withdrawn.
+ * @hide
+ */
+ @SystemApi
+ public void onRequestWithdrawn(@NonNull NetworkRequest request) {}
+
+ /**
+ * Asserts that no provider will ever be able to satisfy the specified request. The provider
+ * must only call this method if it knows that it is the only provider on the system capable of
+ * satisfying this request, and that the request cannot be satisfied. The application filing the
+ * request will receive an {@link NetworkCallback#onUnavailable()} callback.
+ *
+ * @param request the request that cannot be fulfilled
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
+ mCm.declareNetworkRequestUnfulfillable(request);
+ }
+}
diff --git a/core/java/android/net/NetworkQuotaInfo.java b/core/java/android/net/NetworkQuotaInfo.java
index a46cdde..2e52d9c 100644
--- a/core/java/android/net/NetworkQuotaInfo.java
+++ b/core/java/android/net/NetworkQuotaInfo.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 471b23e..ee4379a 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.NetworkCapabilities.NetCapability;
import android.net.NetworkCapabilities.Transport;
import android.os.Build;
@@ -247,9 +247,8 @@
* removing even the capabilities that are set by default when the object is constructed.
*
* @return The builder to facilitate chaining.
- * @hide
*/
- @UnsupportedAppUsage
+ @NonNull
public Builder clearCapabilities() {
mNetworkCapabilities.clearAll();
return this;
@@ -301,22 +300,34 @@
* this without a single transport set will generate an exception, as will
* subsequently adding or removing transports after this is set.
* </p>
- * The interpretation of this {@code String} is bearer specific and bearers that use
- * it should document their particulars. For example, Bluetooth may use some sort of
- * device id while WiFi could used ssid and/or bssid. Cellular may use carrier spn.
+ * If the {@code networkSpecifier} is provided, it shall be interpreted as follows:
+ * <ul>
+ * <li>If the specifier can be parsed as an integer, it will be treated as a
+ * {@link android.net TelephonyNetworkSpecifier}, and the provided integer will be
+ * interpreted as a SubscriptionId.
+ * <li>If the value is an ethernet interface name, it will be treated as such.
+ * <li>For all other cases, the behavior is undefined.
+ * </ul>
*
- * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
- * specific network specifier where the bearer has a choice of
- * networks.
+ * @param networkSpecifier A {@code String} of either a SubscriptionId in cellular
+ * network request or an ethernet interface name in ethernet
+ * network request.
+ *
+ * @deprecated Use {@link #setNetworkSpecifier(NetworkSpecifier)} instead.
*/
+ @Deprecated
public Builder setNetworkSpecifier(String networkSpecifier) {
- /*
- * A StringNetworkSpecifier does not accept null or empty ("") strings. When network
- * specifiers were strings a null string and an empty string were considered equivalent.
- * Hence no meaning is attached to a null or empty ("") string.
- */
- return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null
- : new StringNetworkSpecifier(networkSpecifier));
+ try {
+ int subId = Integer.parseInt(networkSpecifier);
+ return setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
+ .setSubscriptionId(subId).build());
+ } catch (NumberFormatException nfe) {
+ // A StringNetworkSpecifier does not accept null or empty ("") strings. When network
+ // specifiers were strings a null string and an empty string were considered
+ // equivalent. Hence no meaning is attached to a null or empty ("") string.
+ return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null
+ : new StringNetworkSpecifier(networkSpecifier));
+ }
}
/**
@@ -456,6 +467,19 @@
}
/**
+ * Returns true iff. the capabilities requested in this NetworkRequest are satisfied by the
+ * provided {@link NetworkCapabilities}.
+ *
+ * @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not
+ * satisfy any request.
+ * @hide
+ */
+ @SystemApi
+ public boolean satisfiedBy(@Nullable NetworkCapabilities nc) {
+ return networkCapabilities.satisfiedByNetworkCapabilities(nc);
+ }
+
+ /**
* @see Builder#addTransportType(int)
*/
public boolean hasTransport(@Transport int transportType) {
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index f6dc525..c233ec0 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -163,27 +163,26 @@
public static final String EXTRA_NEW_SCORER = "newScorer";
/** @hide */
- @IntDef({CACHE_FILTER_NONE, CACHE_FILTER_CURRENT_NETWORK, CACHE_FILTER_SCAN_RESULTS})
+ @IntDef({SCORE_FILTER_NONE, SCORE_FILTER_CURRENT_NETWORK, SCORE_FILTER_SCAN_RESULTS})
@Retention(RetentionPolicy.SOURCE)
- public @interface CacheUpdateFilter {}
+ public @interface ScoreUpdateFilter {}
/**
- * Do not filter updates sent to the cache.
- * @hide
+ * Do not filter updates sent to the {@link NetworkScoreCallback}].
*/
- public static final int CACHE_FILTER_NONE = 0;
+ public static final int SCORE_FILTER_NONE = 0;
/**
- * Only send cache updates when the network matches the connected network.
- * @hide
+ * Only send updates to the {@link NetworkScoreCallback} when the network matches the connected
+ * network.
*/
- public static final int CACHE_FILTER_CURRENT_NETWORK = 1;
+ public static final int SCORE_FILTER_CURRENT_NETWORK = 1;
/**
- * Only send cache updates when the network is part of the current scan result set.
- * @hide
+ * Only send updates to the {@link NetworkScoreCallback} when the network is part of the
+ * current scan result set.
*/
- public static final int CACHE_FILTER_SCAN_RESULTS = 2;
+ public static final int SCORE_FILTER_SCAN_RESULTS = 2;
/** @hide */
@IntDef({RECOMMENDATIONS_ENABLED_FORCED_OFF, RECOMMENDATIONS_ENABLED_OFF,
@@ -404,13 +403,13 @@
* @throws SecurityException if the caller does not hold the
* {@link permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
- * @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE.
+ * @deprecated equivalent to registering for cache updates with {@link #SCORE_FILTER_NONE}.
* @hide
*/
@RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
@Deprecated // migrate to registerNetworkScoreCache(int, INetworkScoreCache, int)
public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
- registerNetworkScoreCache(networkType, scoreCache, CACHE_FILTER_NONE);
+ registerNetworkScoreCache(networkType, scoreCache, SCORE_FILTER_NONE);
}
/**
@@ -418,7 +417,7 @@
*
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
- * @param filterType the {@link CacheUpdateFilter} to apply
+ * @param filterType the {@link ScoreUpdateFilter} to apply
* @throws SecurityException if the caller does not hold the
* {@link permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
@@ -426,7 +425,7 @@
*/
@RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache,
- @CacheUpdateFilter int filterType) {
+ @ScoreUpdateFilter int filterType) {
try {
mService.registerNetworkScoreCache(networkType, scoreCache, filterType);
} catch (RemoteException e) {
@@ -510,7 +509,7 @@
* Register a network score callback.
*
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
- * @param filterType the {@link CacheUpdateFilter} to apply
+ * @param filterType the {@link ScoreUpdateFilter} to apply
* @param callback implementation of {@link NetworkScoreCallback} that will be invoked when the
* scores change.
* @param executor The executor on which to execute the callbacks.
@@ -522,7 +521,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
public void registerNetworkScoreCallback(@NetworkKey.NetworkType int networkType,
- @CacheUpdateFilter int filterType,
+ @ScoreUpdateFilter int filterType,
@NonNull @CallbackExecutor Executor executor,
@NonNull NetworkScoreCallback callback) throws SecurityException {
if (callback == null || executor == null) {
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index 2bc3eb5..cf31d21 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -16,6 +16,9 @@
package android.net;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+
/**
* Describes specific properties of a requested network for use in a {@link NetworkRequest}.
*
@@ -31,7 +34,8 @@
*
* @hide
*/
- public abstract boolean satisfiedBy(NetworkSpecifier other);
+ @SystemApi
+ public abstract boolean satisfiedBy(@Nullable NetworkSpecifier other);
/**
* Optional method which can be overridden by concrete implementations of NetworkSpecifier to
@@ -45,6 +49,7 @@
*
* @hide
*/
+ @SystemApi
public void assertValidFromUid(int requestorUid) {
// empty
}
@@ -68,6 +73,8 @@
*
* @hide
*/
+ @SystemApi
+ @Nullable
public NetworkSpecifier redact() {
// TODO (b/122160111): convert default to null once all platform NetworkSpecifiers
// implement this method.
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index 292cf50..e449615 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 6c7aa13..96d7a80 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -19,7 +19,10 @@
import static android.os.Process.CLAT_UID;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -48,59 +51,104 @@
* @hide
*/
// @NotThreadSafe
-public class NetworkStats implements Parcelable {
+@SystemApi
+public final class NetworkStats implements Parcelable {
private static final String TAG = "NetworkStats";
+
/** {@link #iface} value when interface details unavailable. */
- public static final String IFACE_ALL = null;
+ @SuppressLint("CompileTimeConstant")
+ @Nullable public static final String IFACE_ALL = null;
+ /**
+ * Virtual network interface for video telephony. This is for VT data usage counting
+ * purpose.
+ */
+ public static final String IFACE_VT = "vt_data0";
+
/** {@link #uid} value when UID details unavailable. */
public static final int UID_ALL = -1;
- /** {@link #tag} value matching any tag. */
+ /** Special UID value for data usage by tethering. */
+ public static final int UID_TETHERING = -5;
+
+ /**
+ * {@link #tag} value matching any tag.
+ * @hide
+ */
// TODO: Rename TAG_ALL to TAG_ANY.
public static final int TAG_ALL = -1;
- /** {@link #set} value for all sets combined, not including debug sets. */
+ /**
+ * {@link #set} value for all sets combined, not including debug sets.
+ * @hide
+ */
public static final int SET_ALL = -1;
/** {@link #set} value where background data is accounted. */
public static final int SET_DEFAULT = 0;
/** {@link #set} value where foreground data is accounted. */
public static final int SET_FOREGROUND = 1;
- /** All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values. */
+ /**
+ * All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values.
+ * @hide
+ */
public static final int SET_DEBUG_START = 1000;
- /** Debug {@link #set} value when the VPN stats are moved in. */
+ /**
+ * Debug {@link #set} value when the VPN stats are moved in.
+ * @hide
+ */
public static final int SET_DBG_VPN_IN = 1001;
- /** Debug {@link #set} value when the VPN stats are moved out of a vpn UID. */
+ /**
+ * Debug {@link #set} value when the VPN stats are moved out of a vpn UID.
+ * @hide
+ */
public static final int SET_DBG_VPN_OUT = 1002;
- /** Include all interfaces when filtering */
- public static final String[] INTERFACES_ALL = null;
+ /**
+ * Include all interfaces when filtering
+ * @hide
+ */
+ public @Nullable static final String[] INTERFACES_ALL = null;
/** {@link #tag} value for total data across all tags. */
// TODO: Rename TAG_NONE to TAG_ALL.
public static final int TAG_NONE = 0;
- /** {@link #metered} value to account for all metered states. */
+ /**
+ * {@link #metered} value to account for all metered states.
+ * @hide
+ */
public static final int METERED_ALL = -1;
/** {@link #metered} value where native, unmetered data is accounted. */
public static final int METERED_NO = 0;
/** {@link #metered} value where metered data is accounted. */
public static final int METERED_YES = 1;
- /** {@link #roaming} value to account for all roaming states. */
+ /**
+ * {@link #roaming} value to account for all roaming states.
+ * @hide
+ */
public static final int ROAMING_ALL = -1;
/** {@link #roaming} value where native, non-roaming data is accounted. */
public static final int ROAMING_NO = 0;
/** {@link #roaming} value where roaming data is accounted. */
public static final int ROAMING_YES = 1;
- /** {@link #onDefaultNetwork} value to account for all default network states. */
+ /**
+ * {@link #onDefaultNetwork} value to account for all default network states.
+ * @hide
+ */
public static final int DEFAULT_NETWORK_ALL = -1;
/** {@link #onDefaultNetwork} value to account for usage while not the default network. */
public static final int DEFAULT_NETWORK_NO = 0;
/** {@link #onDefaultNetwork} value to account for usage while the default network. */
public static final int DEFAULT_NETWORK_YES = 1;
- /** Denotes a request for stats at the interface level. */
+ /**
+ * Denotes a request for stats at the interface level.
+ * @hide
+ */
public static final int STATS_PER_IFACE = 0;
- /** Denotes a request for stats at the interface and UID level. */
+ /**
+ * Denotes a request for stats at the interface and UID level.
+ * @hide
+ */
public static final int STATS_PER_UID = 1;
private static final String CLATD_INTERFACE_PREFIX = "v4-";
@@ -144,60 +192,78 @@
@UnsupportedAppUsage
private long[] operations;
+ /** @hide */
+ @SystemApi
public static class Entry {
+ /** @hide */
@UnsupportedAppUsage
public String iface;
+ /** @hide */
@UnsupportedAppUsage
public int uid;
+ /** @hide */
@UnsupportedAppUsage
public int set;
+ /** @hide */
@UnsupportedAppUsage
public int tag;
/**
* Note that this is only populated w/ the default value when read from /proc or written
* to disk. We merge in the correct value when reporting this value to clients of
* getSummary().
+ * @hide
*/
public int metered;
/**
* Note that this is only populated w/ the default value when read from /proc or written
* to disk. We merge in the correct value when reporting this value to clients of
* getSummary().
+ * @hide
*/
public int roaming;
/**
* Note that this is only populated w/ the default value when read from /proc or written
* to disk. We merge in the correct value when reporting this value to clients of
* getSummary().
+ * @hide
*/
public int defaultNetwork;
+ /** @hide */
@UnsupportedAppUsage
public long rxBytes;
+ /** @hide */
@UnsupportedAppUsage
public long rxPackets;
+ /** @hide */
@UnsupportedAppUsage
public long txBytes;
+ /** @hide */
@UnsupportedAppUsage
public long txPackets;
+ /** @hide */
+ @UnsupportedAppUsage
public long operations;
+ /** @hide */
@UnsupportedAppUsage
public Entry() {
this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
}
+ /** @hide */
public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets,
operations);
}
+ /** @hide */
public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
long txBytes, long txPackets, long operations) {
this(iface, uid, set, tag, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO,
rxBytes, rxPackets, txBytes, txPackets, operations);
}
- public Entry(String iface, int uid, int set, int tag, int metered, int roaming,
+ public Entry(@Nullable String iface, int uid, int set, int tag, int metered, int roaming,
int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
long operations) {
this.iface = iface;
@@ -214,15 +280,18 @@
this.operations = operations;
}
+ /** @hide */
public boolean isNegative() {
return rxBytes < 0 || rxPackets < 0 || txBytes < 0 || txPackets < 0 || operations < 0;
}
+ /** @hide */
public boolean isEmpty() {
return rxBytes == 0 && rxPackets == 0 && txBytes == 0 && txPackets == 0
&& operations == 0;
}
+ /** @hide */
public void add(Entry another) {
this.rxBytes += another.rxBytes;
this.rxPackets += another.rxPackets;
@@ -249,6 +318,7 @@
return builder.toString();
}
+ /** @hide */
@Override
public boolean equals(Object o) {
if (o instanceof Entry) {
@@ -262,13 +332,13 @@
return false;
}
+ /** @hide */
@Override
public int hashCode() {
return Objects.hash(uid, set, tag, metered, roaming, defaultNetwork, iface);
}
}
- @UnsupportedAppUsage
public NetworkStats(long elapsedRealtime, int initialSize) {
this.elapsedRealtime = elapsedRealtime;
this.size = 0;
@@ -292,6 +362,7 @@
}
}
+ /** @hide */
@UnsupportedAppUsage
public NetworkStats(Parcel parcel) {
elapsedRealtime = parcel.readLong();
@@ -312,7 +383,7 @@
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(elapsedRealtime);
dest.writeInt(size);
dest.writeInt(capacity);
@@ -330,19 +401,23 @@
dest.writeLongArray(operations);
}
+ /**
+ * @hide
+ */
@Override
public NetworkStats clone() {
final NetworkStats clone = new NetworkStats(elapsedRealtime, size);
NetworkStats.Entry entry = null;
for (int i = 0; i < size; i++) {
entry = getValues(i, entry);
- clone.addValues(entry);
+ clone.addEntry(entry);
}
return clone;
}
/**
* Clear all data stored in this object.
+ * @hide
*/
public void clear() {
this.capacity = 0;
@@ -360,25 +435,28 @@
this.operations = EmptyArray.LONG;
}
+ /** @hide */
@VisibleForTesting
public NetworkStats addIfaceValues(
String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
- return addValues(
+ return addEntry(
iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
}
+ /** @hide */
@VisibleForTesting
- public NetworkStats addValues(String iface, int uid, int set, int tag, long rxBytes,
+ public NetworkStats addEntry(String iface, int uid, int set, int tag, long rxBytes,
long rxPackets, long txBytes, long txPackets, long operations) {
- return addValues(new Entry(
+ return addEntry(new Entry(
iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
}
+ /** @hide */
@VisibleForTesting
- public NetworkStats addValues(String iface, int uid, int set, int tag, int metered, int roaming,
+ public NetworkStats addEntry(String iface, int uid, int set, int tag, int metered, int roaming,
int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
long operations) {
- return addValues(new Entry(
+ return addEntry(new Entry(
iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets,
txBytes, txPackets, operations));
}
@@ -386,8 +464,9 @@
/**
* Add new stats entry, copying from given {@link Entry}. The {@link Entry}
* object can be recycled across multiple calls.
+ * @hide
*/
- public NetworkStats addValues(Entry entry) {
+ public NetworkStats addEntry(Entry entry) {
if (size >= capacity) {
final int newLength = Math.max(size, 10) * 3 / 2;
iface = Arrays.copyOf(iface, newLength);
@@ -428,6 +507,7 @@
/**
* Return specific stats entry.
+ * @hide
*/
@UnsupportedAppUsage
public Entry getValues(int i, Entry recycle) {
@@ -467,10 +547,12 @@
operations[dest] = operations[src];
}
+ /** @hide */
public long getElapsedRealtime() {
return elapsedRealtime;
}
+ /** @hide */
public void setElapsedRealtime(long time) {
elapsedRealtime = time;
}
@@ -478,21 +560,25 @@
/**
* Return age of this {@link NetworkStats} object with respect to
* {@link SystemClock#elapsedRealtime()}.
+ * @hide
*/
public long getElapsedRealtimeAge() {
return SystemClock.elapsedRealtime() - elapsedRealtime;
}
+ /** @hide */
@UnsupportedAppUsage
public int size() {
return size;
}
+ /** @hide */
@VisibleForTesting
public int internalSize() {
return capacity;
}
+ /** @hide */
@Deprecated
public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
long txBytes, long txPackets, long operations) {
@@ -501,6 +587,7 @@
txPackets, operations);
}
+ /** @hide */
public NetworkStats combineValues(String iface, int uid, int set, int tag,
long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
return combineValues(new Entry(
@@ -509,16 +596,20 @@
/**
* Combine given values with an existing row, or create a new row if
- * {@link #findIndex(String, int, int, int, int)} is unable to find match. Can
- * also be used to subtract values from existing rows.
+ * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
+ * also be used to subtract values from existing rows. This method mutates the referencing
+ * {@link NetworkStats} object.
+ *
+ * @param entry the {@link Entry} to combine.
+ * @return a reference to this mutated {@link NetworkStats} object.
+ * @hide
*/
- @UnsupportedAppUsage
- public NetworkStats combineValues(Entry entry) {
+ public @NonNull NetworkStats combineValues(@NonNull Entry entry) {
final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered,
entry.roaming, entry.defaultNetwork);
if (i == -1) {
// only create new entry when positive contribution
- addValues(entry);
+ addEntry(entry);
} else {
rxBytes[i] += entry.rxBytes;
rxPackets[i] += entry.rxPackets;
@@ -530,10 +621,33 @@
}
/**
- * Combine all values from another {@link NetworkStats} into this object.
+ * Add given values with an existing row, or create a new row if
+ * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
+ * also be used to subtract values from existing rows.
+ *
+ * @param entry the {@link Entry} to add.
+ * @return a new constructed {@link NetworkStats} object that contains the result.
*/
- @UnsupportedAppUsage
- public void combineAllValues(NetworkStats another) {
+ public @NonNull NetworkStats addValues(@NonNull Entry entry) {
+ return this.clone().combineValues(entry);
+ }
+
+ /**
+ * Add the given {@link NetworkStats} objects.
+ *
+ * @return the sum of two objects.
+ */
+ public @NonNull NetworkStats add(@NonNull NetworkStats another) {
+ final NetworkStats ret = this.clone();
+ ret.combineAllValues(another);
+ return ret;
+ }
+
+ /**
+ * Combine all values from another {@link NetworkStats} into this object.
+ * @hide
+ */
+ public void combineAllValues(@NonNull NetworkStats another) {
NetworkStats.Entry entry = null;
for (int i = 0; i < another.size; i++) {
entry = another.getValues(i, entry);
@@ -543,6 +657,7 @@
/**
* Find first stats index that matches the requested parameters.
+ * @hide
*/
public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming,
int defaultNetwork) {
@@ -560,6 +675,7 @@
/**
* Find first stats index that matches the requested parameters, starting
* search around the hinted index as an optimization.
+ * @hide
*/
@VisibleForTesting
public int findIndexHinted(String iface, int uid, int set, int tag, int metered, int roaming,
@@ -589,6 +705,7 @@
* Splice in {@link #operations} from the given {@link NetworkStats} based
* on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface},
* since operation counts are at data layer.
+ * @hide
*/
public void spliceOperationsFrom(NetworkStats stats) {
for (int i = 0; i < size; i++) {
@@ -604,6 +721,7 @@
/**
* Return list of unique interfaces known by this data structure.
+ * @hide
*/
public String[] getUniqueIfaces() {
final HashSet<String> ifaces = new HashSet<String>();
@@ -617,6 +735,7 @@
/**
* Return list of unique UIDs known by this data structure.
+ * @hide
*/
@UnsupportedAppUsage
public int[] getUniqueUids() {
@@ -636,6 +755,7 @@
/**
* Return total bytes represented by this snapshot object, usually used when
* checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
+ * @hide
*/
@UnsupportedAppUsage
public long getTotalBytes() {
@@ -645,6 +765,7 @@
/**
* Return total of all fields represented by this snapshot object.
+ * @hide
*/
@UnsupportedAppUsage
public Entry getTotal(Entry recycle) {
@@ -654,6 +775,7 @@
/**
* Return total of all fields represented by this snapshot object matching
* the requested {@link #uid}.
+ * @hide
*/
@UnsupportedAppUsage
public Entry getTotal(Entry recycle, int limitUid) {
@@ -663,11 +785,13 @@
/**
* Return total of all fields represented by this snapshot object matching
* the requested {@link #iface}.
+ * @hide
*/
public Entry getTotal(Entry recycle, HashSet<String> limitIface) {
return getTotal(recycle, limitIface, UID_ALL, false);
}
+ /** @hide */
@UnsupportedAppUsage
public Entry getTotalIncludingTags(Entry recycle) {
return getTotal(recycle, null, UID_ALL, true);
@@ -717,6 +841,7 @@
/**
* Fast path for battery stats.
+ * @hide
*/
public long getTotalPackets() {
long total = 0;
@@ -729,9 +854,12 @@
/**
* Subtract the given {@link NetworkStats}, effectively leaving the delta
* between two snapshots in time. Assumes that statistics rows collect over
- * time, and that none of them have disappeared.
+ * time, and that none of them have disappeared. This method does not mutate
+ * the referencing object.
+ *
+ * @return the delta between two objects.
*/
- public NetworkStats subtract(NetworkStats right) {
+ public @NonNull NetworkStats subtract(@NonNull NetworkStats right) {
return subtract(this, right, null, null);
}
@@ -742,6 +870,7 @@
* <p>
* If counters have rolled backwards, they are clamped to {@code 0} and
* reported to the given {@link NonMonotonicObserver}.
+ * @hide
*/
public static <C> NetworkStats subtract(NetworkStats left, NetworkStats right,
NonMonotonicObserver<C> observer, C cookie) {
@@ -759,6 +888,7 @@
* If <var>recycle</var> is supplied, this NetworkStats object will be
* reused (and returned) as the result if it is large enough to contain
* the data.
+ * @hide
*/
public static <C> NetworkStats subtract(NetworkStats left, NetworkStats right,
NonMonotonicObserver<C> observer, C cookie, NetworkStats recycle) {
@@ -817,7 +947,7 @@
entry.operations = Math.max(entry.operations, 0);
}
- result.addValues(entry);
+ result.addEntry(entry);
}
return result;
@@ -847,6 +977,7 @@
* @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated.
* @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
* @param useBpfStats True if eBPF is in use.
+ * @hide
*/
public static void apply464xlatAdjustments(NetworkStats baseTraffic,
NetworkStats stackedTraffic, Map<String, String> stackedIfaces, boolean useBpfStats) {
@@ -899,6 +1030,7 @@
* {@link #apply464xlatAdjustments(NetworkStats, NetworkStats, Map)} with {@code this} as
* base and stacked traffic.
* @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
+ * @hide
*/
public void apply464xlatAdjustments(Map<String, String> stackedIfaces, boolean useBpfStats) {
apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats);
@@ -907,6 +1039,7 @@
/**
* Return total statistics grouped by {@link #iface}; doesn't mutate the
* original structure.
+ * @hide
*/
public NetworkStats groupedByIface() {
final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
@@ -938,6 +1071,7 @@
/**
* Return total statistics grouped by {@link #uid}; doesn't mutate the
* original structure.
+ * @hide
*/
public NetworkStats groupedByUid() {
final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
@@ -968,6 +1102,7 @@
/**
* Remove all rows that match one of specified UIDs.
+ * @hide
*/
public void removeUids(int[] uids) {
int nextOutputEntry = 0;
@@ -989,6 +1124,7 @@
* @param limitUid UID to filter for, or {@link #UID_ALL}.
* @param limitIfaces Interfaces to filter for, or {@link #INTERFACES_ALL}.
* @param limitTag Tag to filter for, or {@link #TAG_ALL}.
+ * @hide
*/
public void filter(int limitUid, String[] limitIfaces, int limitTag) {
if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
@@ -1004,6 +1140,7 @@
* Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}.
*
* <p>This mutates the original structure in place.
+ * @hide
*/
public void filterDebugEntries() {
filter(e -> e.set < SET_DEBUG_START);
@@ -1024,6 +1161,7 @@
size = nextOutputEntry;
}
+ /** @hide */
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix);
pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
@@ -1047,6 +1185,7 @@
/**
* Return text description of {@link #set} value.
+ * @hide
*/
public static String setToString(int set) {
switch (set) {
@@ -1067,6 +1206,7 @@
/**
* Return text description of {@link #set} value.
+ * @hide
*/
public static String setToCheckinString(int set) {
switch (set) {
@@ -1087,6 +1227,7 @@
/**
* @return true if the querySet matches the dataSet.
+ * @hide
*/
public static boolean setMatches(int querySet, int dataSet) {
if (querySet == dataSet) {
@@ -1098,6 +1239,7 @@
/**
* Return text description of {@link #tag} value.
+ * @hide
*/
public static String tagToString(int tag) {
return "0x" + Integer.toHexString(tag);
@@ -1105,6 +1247,7 @@
/**
* Return text description of {@link #metered} value.
+ * @hide
*/
public static String meteredToString(int metered) {
switch (metered) {
@@ -1121,6 +1264,7 @@
/**
* Return text description of {@link #roaming} value.
+ * @hide
*/
public static String roamingToString(int roaming) {
switch (roaming) {
@@ -1137,6 +1281,7 @@
/**
* Return text description of {@link #defaultNetwork} value.
+ * @hide
*/
public static String defaultNetworkToString(int defaultNetwork) {
switch (defaultNetwork) {
@@ -1151,6 +1296,7 @@
}
}
+ /** @hide */
@Override
public String toString() {
final CharArrayWriter writer = new CharArrayWriter();
@@ -1163,8 +1309,7 @@
return 0;
}
- @UnsupportedAppUsage
- public static final @android.annotation.NonNull Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
+ public static final @NonNull Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
@Override
public NetworkStats createFromParcel(Parcel in) {
return new NetworkStats(in);
@@ -1176,6 +1321,7 @@
}
};
+ /** @hide */
public interface NonMonotonicObserver<C> {
public void foundNonMonotonic(
NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, C cookie);
@@ -1195,6 +1341,7 @@
* @param tunUid uid of the VPN application
* @param tunIface iface of the vpn tunnel
* @param underlyingIfaces underlying network ifaces used by the VPN application
+ * @hide
*/
public void migrateTun(int tunUid, @NonNull String tunIface,
@NonNull String[] underlyingIfaces) {
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index f61260e..7b799e2 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -30,7 +30,7 @@
import static com.android.internal.util.ArrayUtils.total;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.service.NetworkStatsHistoryBucketProto;
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 87c7118..5e6c47a 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -34,7 +34,7 @@
import static android.net.NetworkStats.ROAMING_YES;
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.BackupUtils;
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index d0f54b4..08cc4e2 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -20,7 +20,7 @@
import static android.system.OsConstants.AF_INET6;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.shared.Inet4AddressUtils;
import android.os.Build;
import android.system.ErrnoException;
@@ -61,13 +61,6 @@
public static native void detachBPFFilter(FileDescriptor fd) throws SocketException;
/**
- * Configures a socket for receiving ICMPv6 router solicitations and sending advertisements.
- * @param fd the socket's {@link FileDescriptor}.
- * @param ifIndex the interface index.
- */
- public native static void setupRaSocket(FileDescriptor fd, int ifIndex) throws SocketException;
-
- /**
* Binds the current process to the network designated by {@code netId}. All sockets created
* in the future (and not explicitly bound via a bound {@link SocketFactory} (see
* {@link Network#getSocketFactory}) will be bound to this network. Note that if this
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index a1c7fce..767b693 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -8,4 +8,4 @@
reminv@google.com
satk@google.com
-per-file SSL*, Uri*, Url* = flooey@google.com, narayan@google.com, tobiast@google.com
+per-file SSL*, Uri*, Url* = prb@google.com, dauletz@google.com, narayan@google.com, tobiast@google.com
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 4600942..4ba7394 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -18,7 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index 9d92db4..ffe9ae9 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 52d3fc4..ea6002c 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 39cb323..8b6ac42 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.SystemProperties;
import android.util.Log;
diff --git a/core/java/android/net/SSLSessionCache.java b/core/java/android/net/SSLSessionCache.java
index 9667e82..944bc54 100644
--- a/core/java/android/net/SSLSessionCache.java
+++ b/core/java/android/net/SSLSessionCache.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.Log;
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index f9c2def..8c6faf6 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.SystemClock;
import android.util.Log;
diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java
index ec73866..fc9a8f6 100644
--- a/core/java/android/net/SocketKeepalive.java
+++ b/core/java/android/net/SocketKeepalive.java
@@ -20,6 +20,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -53,7 +54,11 @@
public abstract class SocketKeepalive implements AutoCloseable {
static final String TAG = "SocketKeepalive";
- /** @hide */
+ /**
+ * No errors.
+ * @hide
+ */
+ @SystemApi
public static final int SUCCESS = 0;
/** @hide */
@@ -147,17 +152,6 @@
}
}
- /**
- * This packet is invalid.
- * See the error code for details.
- * @hide
- */
- public static class InvalidPacketException extends ErrorCodeException {
- public InvalidPacketException(final int error) {
- super(error);
- }
- }
-
@NonNull final IConnectivityManager mService;
@NonNull final Network mNetwork;
@NonNull final ParcelFileDescriptor mPfd;
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 990c114..f24a9bd 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.shared.InetAddressUtils;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/TelephonyNetworkSpecifier.java b/core/java/android/net/TelephonyNetworkSpecifier.java
new file mode 100644
index 0000000..726f770
--- /dev/null
+++ b/core/java/android/net/TelephonyNetworkSpecifier.java
@@ -0,0 +1,146 @@
+/*
+ * 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.net;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * NetworkSpecifier object for cellular network request. Apps should use the
+ * {@link TelephonyNetworkSpecifier.Builder} class to create an instance.
+ */
+public final class TelephonyNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+
+ private final int mSubId;
+
+ /**
+ * Return the subscription Id of current TelephonyNetworkSpecifier object.
+ *
+ * @return The subscription id.
+ */
+ public int getSubscriptionId() {
+ return mSubId;
+ }
+
+ /**
+ * @hide
+ */
+ public TelephonyNetworkSpecifier(int subId) {
+ this.mSubId = subId;
+ }
+
+ public static final @NonNull Creator<TelephonyNetworkSpecifier> CREATOR =
+ new Creator<TelephonyNetworkSpecifier>() {
+ @Override
+ public TelephonyNetworkSpecifier createFromParcel(Parcel in) {
+ int subId = in.readInt();
+ return new TelephonyNetworkSpecifier(subId);
+ }
+
+ @Override
+ public TelephonyNetworkSpecifier[] newArray(int size) {
+ return new TelephonyNetworkSpecifier[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mSubId);
+ }
+
+ @Override
+ public int hashCode() {
+ return mSubId;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof TelephonyNetworkSpecifier)) {
+ return false;
+ }
+
+ TelephonyNetworkSpecifier lhs = (TelephonyNetworkSpecifier) obj;
+ return mSubId == lhs.mSubId;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder()
+ .append("TelephonyNetworkSpecifier [")
+ .append("mSubId = ").append(mSubId)
+ .append("]")
+ .toString();
+ }
+
+ /** @hide */
+ @Override
+ public boolean satisfiedBy(NetworkSpecifier other) {
+ // Any generic requests should be satisfied by a specific telephony network.
+ // For simplicity, we treat null same as MatchAllNetworkSpecifier
+ return equals(other) || other == null || other instanceof MatchAllNetworkSpecifier;
+ }
+
+
+ /**
+ * Builder to create {@link TelephonyNetworkSpecifier} object.
+ */
+ public static final class Builder {
+ // Integer.MIN_VALUE which is not a valid subId, services as the sentinel to check if
+ // subId was set
+ private static final int SENTINEL_SUB_ID = Integer.MIN_VALUE;
+
+ private int mSubId;
+
+ public Builder() {
+ mSubId = SENTINEL_SUB_ID;
+ }
+
+ /**
+ * Set the subscription id.
+ *
+ * @param subId The subscription Id.
+ * @return Instance of {@link Builder} to enable the chaining of the builder method.
+ */
+ public @NonNull Builder setSubscriptionId(int subId) {
+ mSubId = subId;
+ return this;
+ }
+
+ /**
+ * Create a NetworkSpecifier for the cellular network request.
+ *
+ * @return TelephonyNetworkSpecifier object.
+ * @throws IllegalArgumentException when subscription Id is not provided through
+ * {@link #setSubscriptionId(int)}.
+ */
+ public @NonNull TelephonyNetworkSpecifier build() {
+ if (mSubId == SENTINEL_SUB_ID) {
+ throw new IllegalArgumentException("Subscription Id is not provided.");
+ }
+ return new TelephonyNetworkSpecifier(mSubId);
+ }
+ }
+}
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index bf4884a..8108cf0 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -20,10 +20,10 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.DownloadManager;
import android.app.backup.BackupManager;
import android.app.usage.NetworkStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Build;
@@ -89,7 +89,7 @@
*
* @hide
*/
- public static final int UID_TETHERING = -5;
+ public static final int UID_TETHERING = NetworkStats.UID_TETHERING;
/**
* Tag values in this range are reserved for the network stack. The network stack is
diff --git a/core/java/android/net/Uri.aidl b/core/java/android/net/Uri.aidl
index 6bd3be5..b85f63b 100644
--- a/core/java/android/net/Uri.aidl
+++ b/core/java/android/net/Uri.aidl
@@ -16,4 +16,4 @@
package android.net;
-parcelable Uri;
+@JavaOnlyStableParcelable parcelable Uri;
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index c3166e9..ddca4b4 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Environment;
import android.os.Parcel;
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index ed7cddc..4b804b0 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -23,11 +23,11 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.Service;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/net/WebAddress.java b/core/java/android/net/WebAddress.java
index 994c794..aa3777d 100644
--- a/core/java/android/net/WebAddress.java
+++ b/core/java/android/net/WebAddress.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import java.util.Locale;
diff --git a/core/java/android/net/annotations/PolicyDirection.java b/core/java/android/net/annotations/PolicyDirection.java
new file mode 100644
index 0000000..febd9b4
--- /dev/null
+++ b/core/java/android/net/annotations/PolicyDirection.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.annotations;
+
+import android.annotation.IntDef;
+import android.net.IpSecManager;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * IPsec traffic direction.
+ *
+ * <p>Mainline modules cannot reference hidden @IntDef. Moving this annotation to a separate class
+ * to allow others to statically include it.
+ *
+ * @hide
+ */
+@IntDef(value = {IpSecManager.DIRECTION_IN, IpSecManager.DIRECTION_OUT})
+@Retention(RetentionPolicy.SOURCE)
+public @interface PolicyDirection {}
diff --git a/core/java/android/net/http/OWNERS b/core/java/android/net/http/OWNERS
index 6b8c9ed..3092612 100644
--- a/core/java/android/net/http/OWNERS
+++ b/core/java/android/net/http/OWNERS
@@ -1,3 +1,4 @@
-flooey@google.com
narayan@google.com
tobiast@google.com
+include platform/libcore:/OWNERS
+include platform/external/conscrypt:/OWNERS
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
index 01dd08f..250cff2 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -17,7 +17,7 @@
package android.net.http;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Bundle;
import android.text.format.DateFormat;
diff --git a/core/java/android/net/http/SslError.java b/core/java/android/net/http/SslError.java
index b3f2fb7..d43c616 100644
--- a/core/java/android/net/http/SslError.java
+++ b/core/java/android/net/http/SslError.java
@@ -16,8 +16,9 @@
package android.net.http;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
+
import java.security.cert.X509Certificate;
/**
diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java
index 8243be9..f93907a 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index eac5579..b221cb9 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index 5f9f507..8fc1ef8 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/core/java/android/net/netstats/provider/AbstractNetworkStatsProvider.java b/core/java/android/net/netstats/provider/AbstractNetworkStatsProvider.java
new file mode 100644
index 0000000..740aa92
--- /dev/null
+++ b/core/java/android/net/netstats/provider/AbstractNetworkStatsProvider.java
@@ -0,0 +1,70 @@
+/*
+ * 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.net.netstats.provider;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.net.NetworkStats;
+
+/**
+ * A base class that allows external modules to implement a custom network statistics provider.
+ * @hide
+ */
+@SystemApi
+public abstract class AbstractNetworkStatsProvider {
+ /**
+ * A value used by {@link #setLimit} and {@link #setAlert} indicates there is no limit.
+ */
+ public static final int QUOTA_UNLIMITED = -1;
+
+ /**
+ * Called by {@code NetworkStatsService} when global polling is needed. Custom
+ * implementation of providers MUST respond to it by calling
+ * {@link NetworkStatsProviderCallback#onStatsUpdated} within one minute. Responding
+ * later than this may cause the stats to be dropped.
+ *
+ * @param token a positive number identifying the new state of the system under which
+ * {@link NetworkStats} have to be gathered from now on. When this is called,
+ * custom implementations of providers MUST report the latest stats with the
+ * previous token, under which stats were being gathered so far.
+ */
+ public abstract void requestStatsUpdate(int token);
+
+ /**
+ * Called by {@code NetworkStatsService} when setting the interface quota for the specified
+ * upstream interface. When this is called, the custom implementation should block all egress
+ * packets on the {@code iface} associated with the provider when {@code quotaBytes} bytes have
+ * been reached, and MUST respond to it by calling
+ * {@link NetworkStatsProviderCallback#onLimitReached()}.
+ *
+ * @param iface the interface requiring the operation.
+ * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
+ * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
+ */
+ public abstract void setLimit(@NonNull String iface, long quotaBytes);
+
+ /**
+ * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations
+ * MUST call {@link NetworkStatsProviderCallback#onAlertReached()} when {@code quotaBytes} bytes
+ * have been reached. Unlike {@link #setLimit(String, long)}, the custom implementation should
+ * not block all egress packets.
+ *
+ * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
+ * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no alert.
+ */
+ public abstract void setAlert(long quotaBytes);
+}
diff --git a/core/java/android/net/NetworkMisc.aidl b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl
similarity index 60%
copy from core/java/android/net/NetworkMisc.aidl
copy to core/java/android/net/netstats/provider/INetworkStatsProvider.aidl
index c65583f..55b3d4e 100644
--- a/core/java/android/net/NetworkMisc.aidl
+++ b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,6 +14,15 @@
* limitations under the License.
*/
-package android.net;
+package android.net.netstats.provider;
-parcelable NetworkMisc;
+/**
+ * Interface for NetworkStatsService to query network statistics and set data limits.
+ *
+ * @hide
+ */
+oneway interface INetworkStatsProvider {
+ void requestStatsUpdate(int token);
+ void setLimit(String iface, long quotaBytes);
+ void setAlert(long quotaBytes);
+}
diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
new file mode 100644
index 0000000..3ea9318
--- /dev/null
+++ b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.net.netstats.provider;
+
+import android.net.NetworkStats;
+
+/**
+ * Interface for implementor of {@link INetworkStatsProviderCallback} to push events
+ * such as network statistics update or notify limit reached.
+ * @hide
+ */
+oneway interface INetworkStatsProviderCallback {
+ void onStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats);
+ void onAlertReached();
+ void onLimitReached();
+ void unregister();
+}
diff --git a/core/java/android/net/netstats/provider/NetworkStatsProviderCallback.java b/core/java/android/net/netstats/provider/NetworkStatsProviderCallback.java
new file mode 100644
index 0000000..e17a8ee
--- /dev/null
+++ b/core/java/android/net/netstats/provider/NetworkStatsProviderCallback.java
@@ -0,0 +1,98 @@
+/*
+ * 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.net.netstats.provider;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.net.NetworkStats;
+import android.os.RemoteException;
+
+/**
+ * A callback class that allows callers to report events to the system.
+ * @hide
+ */
+@SystemApi
+@SuppressLint("CallbackMethodName")
+public class NetworkStatsProviderCallback {
+ @NonNull private final INetworkStatsProviderCallback mBinder;
+
+ /** @hide */
+ public NetworkStatsProviderCallback(@NonNull INetworkStatsProviderCallback binder) {
+ mBinder = binder;
+ }
+
+ /**
+ * Notify the system of new network statistics.
+ *
+ * Send the network statistics recorded since the last call to {@link #onStatsUpdated}. Must be
+ * called within one minute of {@link AbstractNetworkStatsProvider#requestStatsUpdate(int)}
+ * being called. The provider can also call this whenever it wants to reports new stats for any
+ * reason. Note that the system will not necessarily immediately propagate the statistics to
+ * reflect the update.
+ *
+ * @param token the token under which these stats were gathered. Providers can call this method
+ * with the current token as often as they want, until the token changes.
+ * {@see AbstractNetworkStatsProvider#requestStatsUpdate()}
+ * @param ifaceStats the {@link NetworkStats} per interface to be reported.
+ * The provider should not include any traffic that is already counted by
+ * kernel interface counters.
+ * @param uidStats the same stats as above, but counts {@link NetworkStats}
+ * per uid.
+ */
+ public void onStatsUpdated(int token, @NonNull NetworkStats ifaceStats,
+ @NonNull NetworkStats uidStats) {
+ try {
+ mBinder.onStatsUpdated(token, ifaceStats, uidStats);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Notify system that the quota set by {@code setAlert} has been reached.
+ */
+ public void onAlertReached() {
+ try {
+ mBinder.onAlertReached();
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Notify system that the quota set by {@code setLimit} has been reached.
+ */
+ public void onLimitReached() {
+ try {
+ mBinder.onLimitReached();
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Unregister the provider and the referencing callback.
+ */
+ public void unregister() {
+ try {
+ mBinder.unregister();
+ } catch (RemoteException e) {
+ // Ignore error.
+ }
+ }
+}
diff --git a/core/java/android/net/netstats/provider/NetworkStatsProviderWrapper.java b/core/java/android/net/netstats/provider/NetworkStatsProviderWrapper.java
new file mode 100644
index 0000000..4bf7c9b
--- /dev/null
+++ b/core/java/android/net/netstats/provider/NetworkStatsProviderWrapper.java
@@ -0,0 +1,48 @@
+/*
+ * 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.net.netstats.provider;
+
+import android.annotation.NonNull;
+
+/**
+ * A wrapper class of {@link INetworkStatsProvider} that hides the binder interface from exposing
+ * to outer world.
+ *
+ * @hide
+ */
+public class NetworkStatsProviderWrapper extends INetworkStatsProvider.Stub {
+ @NonNull final AbstractNetworkStatsProvider mProvider;
+
+ public NetworkStatsProviderWrapper(AbstractNetworkStatsProvider provider) {
+ mProvider = provider;
+ }
+
+ @Override
+ public void requestStatsUpdate(int token) {
+ mProvider.requestStatsUpdate(token);
+ }
+
+ @Override
+ public void setLimit(@NonNull String iface, long quotaBytes) {
+ mProvider.setLimit(iface, quotaBytes);
+ }
+
+ @Override
+ public void setAlert(long quotaBytes) {
+ mProvider.setAlert(quotaBytes);
+ }
+}
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index 459b140..0946499 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -17,13 +17,13 @@
package android.net.nsd;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Parcelable;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
+import android.os.Parcelable;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Base64;
import android.util.Log;
-import android.util.ArrayMap;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
diff --git a/core/java/android/nfc/ErrorCodes.java b/core/java/android/nfc/ErrorCodes.java
index 98e31ad..d2c81cd 100644
--- a/core/java/android/nfc/ErrorCodes.java
+++ b/core/java/android/nfc/ErrorCodes.java
@@ -16,7 +16,7 @@
package android.nfc;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* This class defines all the error codes that can be returned by the service
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 5044a86..fe316c4 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -16,7 +16,7 @@
package android.nfc;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.net.Uri;
import android.os.Parcel;
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index abfa133..935374d1 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -16,9 +16,9 @@
package android.nfc;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.Application;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.Intent;
import android.net.Uri;
@@ -26,7 +26,6 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 7ab984f..d320f61 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -21,11 +21,11 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.OnActivityPausedListener;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.IPackageManager;
diff --git a/core/java/android/nfc/NfcManager.java b/core/java/android/nfc/NfcManager.java
index 030066e..644e312 100644
--- a/core/java/android/nfc/NfcManager.java
+++ b/core/java/android/nfc/NfcManager.java
@@ -17,7 +17,7 @@
package android.nfc;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 5a4c465..b9e6ff4 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -16,7 +16,7 @@
package android.nfc;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.nfc.tech.IsoDep;
import android.nfc.tech.MifareClassic;
@@ -455,12 +455,12 @@
*
* @hide
*/
- public synchronized void setConnectedTechnology(int technology) {
- if (mConnectedTechnology == -1) {
- mConnectedTechnology = technology;
- } else {
- throw new IllegalStateException("Close other technology first!");
+ public synchronized boolean setConnectedTechnology(int technology) {
+ if (mConnectedTechnology != -1) {
+ return false;
}
+ mConnectedTechnology = technology;
+ return true;
}
/**
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
index 77b5552..c4f5e0b 100644
--- a/core/java/android/nfc/cardemulation/AidGroup.java
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -16,18 +16,18 @@
package android.nfc.cardemulation;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
/**
* The AidGroup class represents a group of Application Identifiers (AIDs).
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index d9000e4..8da9db1 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -16,7 +16,7 @@
package android.nfc.cardemulation;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
diff --git a/core/java/android/nfc/tech/BasicTagTechnology.java b/core/java/android/nfc/tech/BasicTagTechnology.java
index b6b347c..ae468fe 100644
--- a/core/java/android/nfc/tech/BasicTagTechnology.java
+++ b/core/java/android/nfc/tech/BasicTagTechnology.java
@@ -75,7 +75,10 @@
if (errorCode == ErrorCodes.SUCCESS) {
// Store this in the tag object
- mTag.setConnectedTechnology(mSelectedTechnology);
+ if (!mTag.setConnectedTechnology(mSelectedTechnology)) {
+ Log.e(TAG, "Close other technology first!");
+ throw new IOException("Only one TagTechnology can be connected at a time.");
+ }
mIsConnected = true;
} else if (errorCode == ErrorCodes.ERROR_NOT_SUPPORTED) {
throw new UnsupportedOperationException("Connecting to " +
diff --git a/core/java/android/os/AppZygote.java b/core/java/android/os/AppZygote.java
index 6daa5b4..9257496 100644
--- a/core/java/android/os/AppZygote.java
+++ b/core/java/android/os/AppZygote.java
@@ -21,6 +21,8 @@
import com.android.internal.annotations.GuardedBy;
+import dalvik.system.VMRuntime;
+
/**
* AppZygote is responsible for interfacing with an application-specific zygote.
*
@@ -113,7 +115,7 @@
"app_zygote", // seInfo
abi, // abi
abi, // acceptedAbiList
- null, // instructionSet
+ VMRuntime.getInstructionSet(abi), // instructionSet
mZygoteUidGidMin,
mZygoteUidGidMax);
diff --git a/core/java/android/os/AsyncResult.java b/core/java/android/os/AsyncResult.java
index 58a2701..e80528b 100644
--- a/core/java/android/os/AsyncResult.java
+++ b/core/java/android/os/AsyncResult.java
@@ -16,8 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Message;
+import android.compat.annotation.UnsupportedAppUsage;
/** @hide */
public class AsyncResult
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index b37e176..e1dabd3 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -18,8 +18,8 @@
import android.annotation.MainThread;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.ArrayDeque;
import java.util.concurrent.Callable;
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 7f63f8f..e6ad917 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Log;
import android.util.MathUtils;
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 5ced86c..12ec0a0 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -21,7 +21,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.hardware.health.V1_0.Constants;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 6efe1de4..44f7fa3 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -19,9 +19,9 @@
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.job.JobParameters;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.server.ServerProtoEnums;
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 2e6d2cc..9c4a36f 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ExceptionUtils;
import android.util.Log;
import android.util.Slog;
diff --git a/core/java/android/os/Broadcaster.java b/core/java/android/os/Broadcaster.java
index 6ac7f1a..d1a953f 100644
--- a/core/java/android/os/Broadcaster.java
+++ b/core/java/android/os/Broadcaster.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/** @hide */
public class Broadcaster
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1d25bc1..6750fc7 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -22,9 +22,9 @@
import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.Application;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.sysprop.TelephonyProperties;
import android.text.TextUtils;
@@ -161,7 +161,7 @@
try {
Application application = ActivityThread.currentApplication();
String callingPackage = application != null ? application.getPackageName() : null;
- return service.getSerialForPackage(callingPackage);
+ return service.getSerialForPackage(callingPackage, null);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index b82e517..a2071e0 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -17,7 +17,7 @@
package android.os;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Size;
import android.util.SizeF;
diff --git a/core/java/android/os/CancellationSignal.java b/core/java/android/os/CancellationSignal.java
index 99fb998..260f7ad 100644
--- a/core/java/android/os/CancellationSignal.java
+++ b/core/java/android/os/CancellationSignal.java
@@ -16,9 +16,7 @@
package android.os;
-import android.os.ICancellationSignal;
-
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Provides the ability to cancel an operation in progress.
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index d7ed055..5037922 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.Log;
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index b7cccc6..18ba5a8 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -24,7 +24,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.Log;
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 7a131e5..6639d57 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -20,10 +20,10 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index 4d9ebc2..4628910 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import java.io.File;
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 2ac3def..a47fbba 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -40,7 +40,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.provider.DocumentsContract.Document;
import android.system.ErrnoException;
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index a99bdabe..fa7404c 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.Printer;
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index 09afdc7..7c42c36 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -18,7 +18,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import libcore.util.NativeAllocationRegistry;
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 9786f16..fb36e6f 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import dalvik.annotation.optimization.FastNative;
diff --git a/core/java/android/os/HwRemoteBinder.java b/core/java/android/os/HwRemoteBinder.java
index 72ec958..756202e 100644
--- a/core/java/android/os/HwRemoteBinder.java
+++ b/core/java/android/os/HwRemoteBinder.java
@@ -16,7 +16,8 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import libcore.util.NativeAllocationRegistry;
/** @hide */
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index 83f88ad..d9ed327 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.FileDescriptor;
diff --git a/core/java/android/os/IDeviceIdentifiersPolicyService.aidl b/core/java/android/os/IDeviceIdentifiersPolicyService.aidl
index 87d358f..d11aa0c 100644
--- a/core/java/android/os/IDeviceIdentifiersPolicyService.aidl
+++ b/core/java/android/os/IDeviceIdentifiersPolicyService.aidl
@@ -21,5 +21,5 @@
*/
interface IDeviceIdentifiersPolicyService {
String getSerial();
- String getSerialForPackage(in String callingPackage);
-}
\ No newline at end of file
+ String getSerialForPackage(in String callingPackage, String callingFeatureId);
+}
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 6b881fe..264ab60 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -24,7 +24,8 @@
{
boolean hasVibrator();
boolean hasAmplitudeControl();
- boolean setAlwaysOnEffect(int id, in VibrationEffect effect, in AudioAttributes attributes);
+ boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, in VibrationEffect effect,
+ in AudioAttributes attributes);
void vibrate(int uid, String opPkg, in VibrationEffect effect, in AudioAttributes attributes,
String reason, IBinder token);
void cancelVibrate(IBinder token);
diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java
index 0de09ef..0bf387e 100644
--- a/core/java/android/os/LocaleList.java
+++ b/core/java/android/os/LocaleList.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.icu.util.ULocale;
import com.android.internal.annotations.GuardedBy;
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index d468972..5dc64d5 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.Printer;
import android.util.Slog;
diff --git a/core/java/android/os/MemoryFile.java b/core/java/android/os/MemoryFile.java
index 5a1e3d4..f84f9f05 100644
--- a/core/java/android/os/MemoryFile.java
+++ b/core/java/android/os/MemoryFile.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
import java.io.FileDescriptor;
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 6055bef..8ac245b 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index f98fdc3..4e91057 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -19,8 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
-import android.os.MessageQueueProto;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.Printer;
import android.util.SparseArray;
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 041f31d..382c838 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 2a4576a..214b3bb 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -32,7 +32,7 @@
import static android.system.OsConstants.S_IWOTH;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import android.os.MessageQueue.OnFileDescriptorEventListener;
diff --git a/core/java/android/os/ParcelUuid.java b/core/java/android/os/ParcelUuid.java
index cc50c89..0b52c75 100644
--- a/core/java/android/os/ParcelUuid.java
+++ b/core/java/android/os/ParcelUuid.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.UUID;
diff --git a/core/java/android/os/ParcelableParcel.java b/core/java/android/os/ParcelableParcel.java
index 61f3968..38d980e 100644
--- a/core/java/android/os/ParcelableParcel.java
+++ b/core/java/android/os/ParcelableParcel.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.MathUtils;
/**
diff --git a/core/java/android/os/PerformanceCollector.java b/core/java/android/os/PerformanceCollector.java
index 33c86b8..27de48d 100644
--- a/core/java/android/os/PerformanceCollector.java
+++ b/core/java/android/os/PerformanceCollector.java
@@ -17,7 +17,8 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.ArrayList;
/**
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index 6f1bf71..29aaf53 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -16,17 +16,24 @@
package android.os;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.ArrayMap;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
/**
@@ -339,4 +346,44 @@
proto.end(token);
}
+
+ /**
+ * Writes the content of the {@link PersistableBundle} to a {@link OutputStream}.
+ *
+ * <p>The content can be read by a {@link #readFromStream}.
+ *
+ * @see #readFromStream
+ */
+ public void writeToStream(@NonNull OutputStream outputStream) throws IOException {
+ FastXmlSerializer serializer = new FastXmlSerializer();
+ serializer.setOutput(outputStream, UTF_8.name());
+ serializer.startTag(null, "bundle");
+ try {
+ saveToXml(serializer);
+ } catch (XmlPullParserException e) {
+ throw new IOException(e);
+ }
+ serializer.endTag(null, "bundle");
+ serializer.flush();
+ }
+
+ /**
+ * Reads a {@link PersistableBundle} from an {@link InputStream}.
+ *
+ * <p>The stream must be generated by {@link #writeToStream}.
+ *
+ * @see #writeToStream
+ */
+ @NonNull
+ public static PersistableBundle readFromStream(@NonNull InputStream inputStream)
+ throws IOException {
+ try {
+ XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+ parser.setInput(inputStream, UTF_8.name());
+ parser.next();
+ return PersistableBundle.restoreFromXml(parser);
+ } catch (XmlPullParserException e) {
+ throw new IOException(e);
+ }
+ }
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index c618dbc..febc36c 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -26,7 +26,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.service.dreams.Sandman;
import android.util.ArrayMap;
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 1130f1d..6f4f30c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.system.Os;
import android.system.OsConstants;
import android.webkit.WebViewZygote;
@@ -740,11 +740,12 @@
/**
* Set the priority of a thread, based on Linux priorities.
- *
- * @param tid The identifier of the thread/process to change.
+ *
+ * @param tid The identifier of the thread/process to change. It should be
+ * the native thread id but not the managed id of {@link java.lang.Thread}.
* @param priority A Linux priority level, from -20 for highest scheduling
* priority to 19 for lowest scheduling priority.
- *
+ *
* @throws IllegalArgumentException Throws IllegalArgumentException if
* <var>tid</var> does not exist.
* @throws SecurityException Throws SecurityException if your process does
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index e3f6e12..1901820 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -22,8 +22,8 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/os/Registrant.java b/core/java/android/os/Registrant.java
index 572b975..d6afd04 100644
--- a/core/java/android/os/Registrant.java
+++ b/core/java/android/os/Registrant.java
@@ -16,9 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Handler;
-import android.os.Message;
+import android.compat.annotation.UnsupportedAppUsage;
import java.lang.ref.WeakReference;
diff --git a/core/java/android/os/RegistrantList.java b/core/java/android/os/RegistrantList.java
index 9c017df..98f949b 100644
--- a/core/java/android/os/RegistrantList.java
+++ b/core/java/android/os/RegistrantList.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.ArrayList;
diff --git a/core/java/android/os/RemoteCallback.java b/core/java/android/os/RemoteCallback.java
index da58d0f..373060f 100644
--- a/core/java/android/os/RemoteCallback.java
+++ b/core/java/android/os/RemoteCallback.java
@@ -20,8 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index 6165146..df4ade0 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Slog;
diff --git a/core/java/android/os/RemoteException.java b/core/java/android/os/RemoteException.java
index 2e673a8..c2f7f1b 100644
--- a/core/java/android/os/RemoteException.java
+++ b/core/java/android/os/RemoteException.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.AndroidException;
/**
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index 34809e7..f64a811 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Slog;
import java.io.File;
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index bf9225a..c008f4d 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Log;
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 94671c8..39ddcb2 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Native implementation of the service manager. Most clients will only
diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java
index 57a8801..26d9c7d 100644
--- a/core/java/android/os/SharedMemory.java
+++ b/core/java/android/os/SharedMemory.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index 2fe8726..814aac4 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Slog;
import com.android.internal.util.FastPrintWriter;
diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java
index 881d0b4..6d1a116 100644
--- a/core/java/android/os/StatFs.java
+++ b/core/java/android/os/StatFs.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStatVfs;
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 0bf634e..3faaff7 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -20,10 +20,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.IActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index 210f5d7..29852a8 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -17,8 +17,8 @@
package android.os;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.IAlarmManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.location.ILocationManager;
import android.location.LocationTime;
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index f08e1ff..a681ec0 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.MutableInt;
diff --git a/core/java/android/os/SystemService.java b/core/java/android/os/SystemService.java
index 968c761..5871d2d 100644
--- a/core/java/android/os/SystemService.java
+++ b/core/java/android/os/SystemService.java
@@ -16,9 +16,10 @@
package android.os;
+import android.compat.annotation.UnsupportedAppUsage;
+
import com.google.android.collect.Maps;
-import android.annotation.UnsupportedAppUsage;
import java.util.HashMap;
import java.util.concurrent.TimeoutException;
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index fbd11ca..11a425d 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.AudioAttributes;
import android.util.Log;
@@ -70,13 +70,14 @@
}
@Override
- public boolean setAlwaysOnEffect(int id, VibrationEffect effect, AudioAttributes attributes) {
+ public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect,
+ AudioAttributes attributes) {
if (mService == null) {
Log.w(TAG, "Failed to set always-on effect; no vibrator service.");
return false;
}
try {
- return mService.setAlwaysOnEffect(id, effect, attributes);
+ return mService.setAlwaysOnEffect(uid, opPkg, alwaysOnId, effect, attributes);
} catch (RemoteException e) {
Log.w(TAG, "Failed to set always-on effect.", e);
}
diff --git a/core/java/android/util/TimestampedValue.java b/core/java/android/os/TimestampedValue.java
similarity index 88%
rename from core/java/android/util/TimestampedValue.java
rename to core/java/android/os/TimestampedValue.java
index 4505673..f4c87ac 100644
--- a/core/java/android/util/TimestampedValue.java
+++ b/core/java/android/os/TimestampedValue.java
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-package android.util;
+package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
+import android.annotation.SystemApi;
import java.util.Objects;
@@ -38,19 +36,27 @@
* @param <T> the type of the value with an associated timestamp
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class TimestampedValue<T> implements Parcelable {
private final long mReferenceTimeMillis;
+ @Nullable
private final T mValue;
- public TimestampedValue(long referenceTimeMillis, T value) {
+ public TimestampedValue(long referenceTimeMillis, @Nullable T value) {
mReferenceTimeMillis = referenceTimeMillis;
mValue = value;
}
+ /** Returns the reference time value. See {@link TimestampedValue} for more information. */
public long getReferenceTimeMillis() {
return mReferenceTimeMillis;
}
+ /**
+ * Returns the value associated with the timestamp. See {@link TimestampedValue} for more
+ * information.
+ */
+ @Nullable
public T getValue() {
return mValue;
}
@@ -89,6 +95,8 @@
return one.mReferenceTimeMillis - two.mReferenceTimeMillis;
}
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final @NonNull Parcelable.Creator<TimestampedValue<?>> CREATOR =
new Parcelable.ClassLoaderCreator<TimestampedValue<?>>() {
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index e132c11..25584f1 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -17,9 +17,7 @@
package android.os;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-
-import com.android.internal.os.Zygote;
+import android.compat.annotation.UnsupportedAppUsage;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
diff --git a/core/java/android/os/UEventObserver.java b/core/java/android/os/UEventObserver.java
index dc98c42..fa30e50 100644
--- a/core/java/android/os/UEventObserver.java
+++ b/core/java/android/os/UEventObserver.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import java.util.ArrayList;
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index a9ddffe..73e1adf 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -16,8 +16,10 @@
package android.os;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.content.res.AssetFileDescriptor;
import android.os.IUpdateEngine;
import android.os.IUpdateEngineCallback;
import android.os.RemoteException;
@@ -140,8 +142,43 @@
* {@code SWITCH_SLOT_ON_REBOOT=0}. See {@link #applyPayload}.
*/
public static final int UPDATED_BUT_NOT_ACTIVE = 52;
+
+ /**
+ * Error code: there is not enough space on the device to apply the update. User should
+ * be prompted to free up space and re-try the update.
+ *
+ * <p>See {@link UpdateEngine#allocateSpace}.
+ */
+ public static final int NOT_ENOUGH_SPACE = 60;
+
+ /**
+ * Error code: the device is corrupted and no further updates may be applied.
+ *
+ * <p>See {@link UpdateEngine#cleanupAppliedPayload}.
+ */
+ public static final int DEVICE_CORRUPTED = 61;
}
+ /** @hide */
+ @IntDef(value = {
+ ErrorCodeConstants.SUCCESS,
+ ErrorCodeConstants.ERROR,
+ ErrorCodeConstants.FILESYSTEM_COPIER_ERROR,
+ ErrorCodeConstants.POST_INSTALL_RUNNER_ERROR,
+ ErrorCodeConstants.PAYLOAD_MISMATCHED_TYPE_ERROR,
+ ErrorCodeConstants.INSTALL_DEVICE_OPEN_ERROR,
+ ErrorCodeConstants.KERNEL_DEVICE_OPEN_ERROR,
+ ErrorCodeConstants.DOWNLOAD_TRANSFER_ERROR,
+ ErrorCodeConstants.PAYLOAD_HASH_MISMATCH_ERROR,
+ ErrorCodeConstants.PAYLOAD_SIZE_MISMATCH_ERROR,
+ ErrorCodeConstants.DOWNLOAD_PAYLOAD_VERIFICATION_ERROR,
+ ErrorCodeConstants.PAYLOAD_TIMESTAMP_ERROR,
+ ErrorCodeConstants.UPDATED_BUT_NOT_ACTIVE,
+ ErrorCodeConstants.NOT_ENOUGH_SPACE,
+ ErrorCodeConstants.DEVICE_CORRUPTED,
+ })
+ public @interface ErrorCode {}
+
/**
* Status codes for update engine. Values must agree with the ones in
* {@code system/update_engine/client_library/include/update_engine/update_status.h}.
@@ -313,16 +350,17 @@
}
/**
- * Applies the payload passed as ParcelFileDescriptor {@code pfd} instead of
- * using the {@code file://} scheme.
+ * Applies the payload passed as AssetFileDescriptor {@code assetFd}
+ * instead of using the {@code file://} scheme.
*
* <p>See {@link #applyPayload(String)} for {@code offset}, {@code size} and
* {@code headerKeyValuePairs} parameters.
*/
- public void applyPayload(@NonNull ParcelFileDescriptor pfd, long offset, long size,
+ public void applyPayload(@NonNull AssetFileDescriptor assetFd,
@NonNull String[] headerKeyValuePairs) {
try {
- mUpdateEngine.applyPayloadFd(pfd, offset, size, headerKeyValuePairs);
+ mUpdateEngine.applyPayloadFd(assetFd.getParcelFileDescriptor(),
+ assetFd.getStartOffset(), assetFd.getLength(), headerKeyValuePairs);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -419,4 +457,138 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Return value of {@link #allocateSpace.}
+ */
+ public static final class AllocateSpaceResult {
+ private @ErrorCode int mErrorCode = ErrorCodeConstants.SUCCESS;
+ private long mFreeSpaceRequired = 0;
+ private AllocateSpaceResult() {}
+ /**
+ * Error code.
+ *
+ * @return The following error codes:
+ * <ul>
+ * <li>{@link ErrorCodeConstants#SUCCESS} if space has been allocated
+ * successfully.</li>
+ * <li>{@link ErrorCodeConstants#NOT_ENOUGH_SPACE} if insufficient
+ * space.</li>
+ * <li>Other {@link ErrorCodeConstants} for other errors.</li>
+ * </ul>
+ */
+ @ErrorCode
+ public int errorCode() {
+ return mErrorCode;
+ }
+
+ /**
+ * Estimated total space that needs to be available on the userdata partition to apply the
+ * payload (in bytes).
+ *
+ * <p>
+ * Note that in practice, more space needs to be made available before applying the payload
+ * to keep the device working.
+ *
+ * @return The following values:
+ * <ul>
+ * <li>zero if {@link #errorCode} returns {@link ErrorCodeConstants#SUCCESS}</li>
+ * <li>non-zero if {@link #errorCode} returns {@link ErrorCodeConstants#NOT_ENOUGH_SPACE}.
+ * Value is the estimated total space required on userdata partition.</li>
+ * </ul>
+ * @throws IllegalStateException if {@link #errorCode} is not one of the above.
+ *
+ */
+ public long freeSpaceRequired() {
+ if (mErrorCode == ErrorCodeConstants.SUCCESS) {
+ return 0;
+ }
+ if (mErrorCode == ErrorCodeConstants.NOT_ENOUGH_SPACE) {
+ return mFreeSpaceRequired;
+ }
+ throw new IllegalStateException(String.format(
+ "freeSpaceRequired() is not available when error code is %d", mErrorCode));
+ }
+ }
+
+ /**
+ * Initialize partitions for a payload associated with the given payload
+ * metadata {@code payloadMetadataFilename} by preallocating required space.
+ *
+ * <p>This function should be called after payload has been verified after
+ * {@link #verifyPayloadMetadata}. This function does not verify whether
+ * the given payload is applicable or not.
+ *
+ * <p>Implementation of {@code allocateSpace} uses
+ * {@code headerKeyValuePairs} to determine whether space has been allocated
+ * for a different or same payload previously. If space has been allocated
+ * for a different payload before, space will be reallocated for the given
+ * payload. If space has been allocated for the same payload, no actions to
+ * storage devices are taken.
+ *
+ * <p>This function is synchronous and may take a non-trivial amount of
+ * time. Callers should call this function in a background thread.
+ *
+ * @param payloadMetadataFilename See {@link #verifyPayloadMetadata}.
+ * @param headerKeyValuePairs See {@link #applyPayload}.
+ * @return See {@link AllocateSpaceResult}.
+ */
+ @NonNull
+ public AllocateSpaceResult allocateSpace(
+ @NonNull String payloadMetadataFilename,
+ @NonNull String[] headerKeyValuePairs) {
+ AllocateSpaceResult result = new AllocateSpaceResult();
+ try {
+ result.mFreeSpaceRequired = mUpdateEngine.allocateSpaceForPayload(
+ payloadMetadataFilename,
+ headerKeyValuePairs);
+ result.mErrorCode = result.mFreeSpaceRequired == 0
+ ? ErrorCodeConstants.SUCCESS
+ : ErrorCodeConstants.NOT_ENOUGH_SPACE;
+ return result;
+ } catch (ServiceSpecificException e) {
+ result.mErrorCode = e.errorCode;
+ result.mFreeSpaceRequired = 0;
+ return result;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Cleanup files used by the previous update and free up space after the
+ * device has been booted successfully into the new build.
+ *
+ * <p>In particular, this function waits until delta files for snapshots for
+ * Virtual A/B update are merged to OS partitions, then delete these delta
+ * files.
+ *
+ * <p>This function is synchronous and may take a non-trivial amount of
+ * time. Callers should call this function in a background thread.
+ *
+ * <p>This function does not delete payload binaries downloaded for a
+ * non-streaming OTA update.
+ *
+ * @return One of the following:
+ * <ul>
+ * <li>{@link ErrorCodeConstants#SUCCESS} if execution is successful.</li>
+ * <li>{@link ErrorCodeConstants#ERROR} if a transient error has occurred.
+ * The device should be able to recover after a reboot. The function should
+ * be retried after the reboot.</li>
+ * <li>{@link ErrorCodeConstants#DEVICE_CORRUPTED} if a permanent error is
+ * encountered. Device is corrupted, and future updates must not be applied.
+ * The device cannot recover without flashing and factory resets.
+ * </ul>
+ *
+ * @throws ServiceSpecificException if other transient errors has occurred.
+ * A reboot may or may not help resolving the issue.
+ */
+ @ErrorCode
+ public int cleanupAppliedPayload() {
+ try {
+ return mUpdateEngine.cleanupSuccessfulUpdate();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/os/UpdateEngineCallback.java b/core/java/android/os/UpdateEngineCallback.java
index f07294e..7fe7024 100644
--- a/core/java/android/os/UpdateEngineCallback.java
+++ b/core/java/android/os/UpdateEngineCallback.java
@@ -44,5 +44,6 @@
* unsuccessfully. The value of {@code errorCode} will be one of the
* values from {@link UpdateEngine.ErrorCodeConstants}.
*/
- public abstract void onPayloadApplicationComplete(int errorCode);
+ public abstract void onPayloadApplicationComplete(
+ @UpdateEngine.ErrorCode int errorCode);
}
diff --git a/core/java/android/os/UpdateLock.java b/core/java/android/os/UpdateLock.java
index ea273ce..036d095 100644
--- a/core/java/android/os/UpdateLock.java
+++ b/core/java/android/os/UpdateLock.java
@@ -16,7 +16,7 @@
package android.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.Log;
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 45ee4ef..0ec8658 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -20,8 +20,8 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.PrintWriter;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index c15618b..a507e25 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -25,12 +25,12 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 5769c34..75b4724 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.hardware.vibrator.V1_0.EffectStrength;
@@ -27,8 +28,6 @@
import android.net.Uri;
import android.util.MathUtils;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 6456d72..ae75f3d 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -20,8 +20,8 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.AudioAttributes;
import android.util.Log;
@@ -155,7 +155,7 @@
/**
* Configure an always-on haptics effect.
*
- * @param id The board-specific always-on ID to configure.
+ * @param alwaysOnId The board-specific always-on ID to configure.
* @param effect Vibration effect to assign to always-on id. Passing null will disable it.
* @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
* specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
@@ -164,8 +164,17 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
- public boolean setAlwaysOnEffect(int id, @Nullable VibrationEffect effect,
- @Nullable AudioAttributes attributes) {
+ public boolean setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect,
+ @Nullable AudioAttributes attributes) {
+ return setAlwaysOnEffect(Process.myUid(), mPackageName, alwaysOnId, effect, attributes);
+ }
+
+ /**
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
+ public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
+ @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes) {
Log.w(TAG, "Always-on effects aren't supported");
return false;
}
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 825fc64..6846035 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -4,9 +4,8 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.os.WorkSourceProto;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.util.Log;
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index c2d3ecc..016823e 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
diff --git a/core/java/android/os/health/HealthStatsParceler.java b/core/java/android/os/health/HealthStatsParceler.java
index 384342c..f28a974 100644
--- a/core/java/android/os/health/HealthStatsParceler.java
+++ b/core/java/android/os/health/HealthStatsParceler.java
@@ -17,11 +17,10 @@
package android.os.health;
import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
/**
* Class to allow sending the HealthStats through aidl generated glue.
*
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index a92e28a..6e259ea 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -17,14 +17,13 @@
package android.os.health;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.BatteryStats;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
import com.android.internal.app.IBatteryStats;
diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java
index 921f0f2..5cb3361 100644
--- a/core/java/android/os/image/DynamicSystemClient.java
+++ b/core/java/android/os/image/DynamicSystemClient.java
@@ -256,9 +256,13 @@
mService.send(msg);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to get status from installation service");
- mExecutor.execute(() -> {
+ if (mExecutor != null) {
+ mExecutor.execute(() -> {
+ mListener.onStatusChanged(STATUS_UNKNOWN, CAUSE_ERROR_IPC, 0, e);
+ });
+ } else {
mListener.onStatusChanged(STATUS_UNKNOWN, CAUSE_ERROR_IPC, 0, e);
- });
+ }
}
}
diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java
index 4c92c28..cbf531c 100644
--- a/core/java/android/os/image/DynamicSystemManager.java
+++ b/core/java/android/os/image/DynamicSystemManager.java
@@ -106,9 +106,9 @@
* @return true if the call succeeds
*/
@RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
- public boolean startInstallation() {
+ public boolean startInstallation(String dsuSlot) {
try {
- return mService.startInstallation();
+ return mService.startInstallation(dsuSlot);
} catch (RemoteException e) {
throw new RuntimeException(e.toString());
}
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index 69cbab2..cc32f99 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -22,9 +22,10 @@
{
/**
* Start DynamicSystem installation.
+ * @param dsuSlot Name used to identify this installation
* @return true if the call succeeds
*/
- boolean startInstallation();
+ boolean startInstallation(@utf8InCpp String dsuSlot);
/**
* Create a DSU partition. This call may take 60~90 seconds. The caller
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index b797324..df3c4d5 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java
index 39d5b45..9fd9e4e 100644
--- a/core/java/android/os/storage/StorageEventListener.java
+++ b/core/java/android/os/storage/StorageEventListener.java
@@ -16,7 +16,7 @@
package android.os.storage;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Used for receiving notifications from the StorageManager
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 69c1295..c7709b9 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -40,12 +40,12 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index aefe843..05b45fa 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 7699a05..ff82982 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java
index 1a794eb..c497c8b 100644
--- a/core/java/android/os/storage/VolumeRecord.java
+++ b/core/java/android/os/storage/VolumeRecord.java
@@ -16,7 +16,7 @@
package android.os.storage;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DebugUtils;
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index 32511e9..dfdb57c4 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -21,9 +21,9 @@
import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlertDialog;
import android.app.Dialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
diff --git a/core/java/android/preference/EditTextPreference.java b/core/java/android/preference/EditTextPreference.java
index 74c5e3e..af6f184 100644
--- a/core/java/android/preference/EditTextPreference.java
+++ b/core/java/android/preference/EditTextPreference.java
@@ -17,7 +17,7 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/ListPreference.java b/core/java/android/preference/ListPreference.java
index 830de525..0b64809 100644
--- a/core/java/android/preference/ListPreference.java
+++ b/core/java/android/preference/ListPreference.java
@@ -17,8 +17,8 @@
package android.preference;
import android.annotation.ArrayRes;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlertDialog.Builder;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index e82e60d..f508dda 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -21,7 +21,7 @@
import android.annotation.LayoutRes;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 4750971..ae4a626 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -19,13 +19,13 @@
import android.animation.LayoutTransition;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
import android.app.Fragment;
import android.app.FragmentBreadCrumbs;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListActivity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index d6c069f0..3f6e505 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -17,10 +17,10 @@
package android.preference;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
import android.app.Activity;
import android.app.Fragment;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java
index dcc5d4c..b263f50 100644
--- a/core/java/android/preference/PreferenceGroupAdapter.java
+++ b/core/java/android/preference/PreferenceGroupAdapter.java
@@ -16,7 +16,7 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.preference.Preference.OnPreferenceChangeInternalListener;
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index f741bd6..9d3f349 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -18,9 +18,9 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
diff --git a/core/java/android/preference/PreferenceScreen.java b/core/java/android/preference/PreferenceScreen.java
index a353dbc..01fe2f3 100644
--- a/core/java/android/preference/PreferenceScreen.java
+++ b/core/java/android/preference/PreferenceScreen.java
@@ -16,8 +16,8 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
import android.app.Dialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/RingtonePreference.java b/core/java/android/preference/RingtonePreference.java
index 025aad0..c6d8c08 100644
--- a/core/java/android/preference/RingtonePreference.java
+++ b/core/java/android/preference/RingtonePreference.java
@@ -16,7 +16,7 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/SeekBarDialogPreference.java b/core/java/android/preference/SeekBarDialogPreference.java
index 32ef821..46be122 100644
--- a/core/java/android/preference/SeekBarDialogPreference.java
+++ b/core/java/android/preference/SeekBarDialogPreference.java
@@ -16,7 +16,7 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
diff --git a/core/java/android/preference/SeekBarPreference.java b/core/java/android/preference/SeekBarPreference.java
index 99ab9db..a2852bc 100644
--- a/core/java/android/preference/SeekBarPreference.java
+++ b/core/java/android/preference/SeekBarPreference.java
@@ -16,7 +16,7 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 2b3a2ab..5ff98f9 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -17,8 +17,8 @@
package android.preference;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.NotificationManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/preference/SwitchPreference.java b/core/java/android/preference/SwitchPreference.java
index 9dea1c8..baa023e 100644
--- a/core/java/android/preference/SwitchPreference.java
+++ b/core/java/android/preference/SwitchPreference.java
@@ -17,7 +17,7 @@
package android.preference;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index bb771d7..5eb5d17 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -17,7 +17,7 @@
package android.preference;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index a2d5a23..6eb524a 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -16,8 +16,8 @@
package android.preference;
-import android.annotation.UnsupportedAppUsage;
import android.app.Dialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
diff --git a/core/java/android/print/PrintDocumentAdapter.java b/core/java/android/print/PrintDocumentAdapter.java
index d1b6efc..7ea5655 100644
--- a/core/java/android/print/PrintDocumentAdapter.java
+++ b/core/java/android/print/PrintDocumentAdapter.java
@@ -16,7 +16,7 @@
package android.print;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 25f383c..63f38f8 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -23,7 +23,7 @@
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index e1ede93..9abce5d 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -22,9 +22,9 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.Application.ActivityLifecycleCallbacks;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentSender;
diff --git a/core/java/android/print/PrinterId.java b/core/java/android/print/PrinterId.java
index 42570c6..75ca750 100644
--- a/core/java/android/print/PrinterId.java
+++ b/core/java/android/print/PrinterId.java
@@ -17,7 +17,7 @@
package android.print;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 30021b4..afa7b80 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -16,10 +16,8 @@
package android.provider;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
@@ -30,8 +28,6 @@
import android.provider.BrowserContract.Bookmarks;
import android.provider.BrowserContract.Combined;
import android.provider.BrowserContract.History;
-import android.provider.BrowserContract.Searches;
-import android.util.Log;
import android.webkit.WebIconDatabase;
public class Browser {
diff --git a/core/java/android/provider/BrowserContract.java b/core/java/android/provider/BrowserContract.java
index 57dde66..5083b8b2 100644
--- a/core/java/android/provider/BrowserContract.java
+++ b/core/java/android/provider/BrowserContract.java
@@ -17,7 +17,7 @@
package android.provider;
import android.accounts.Account;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index f1d90be..9c6c92a 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -20,11 +20,11 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -40,7 +40,7 @@
import android.net.Uri;
import android.os.RemoteException;
import android.text.format.DateUtils;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -1680,7 +1680,7 @@
* <h3>Writing to Events</h3> There are further restrictions on all Updates
* and Inserts in the Events table:
* <ul>
- * <li>If allDay is set to 1 eventTimezone must be {@link Time#TIMEZONE_UTC}
+ * <li>If allDay is set to 1 eventTimezone must be "UTC"
* and the time must correspond to a midnight boundary.</li>
* <li>Exceptions are not allowed to recur. If rrule or rdate is not empty,
* original_id and original_sync_id must be empty.</li>
@@ -2609,9 +2609,7 @@
@UnsupportedAppUsage
public static void scheduleAlarm(Context context, AlarmManager manager, long alarmTime) {
if (DEBUG) {
- Time time = new Time();
- time.set(alarmTime);
- String schedTime = time.format(" %a, %b %d, %Y %I:%M%P");
+ String schedTime = TimeMigrationUtils.formatMillisWithFixedFormat(alarmTime);
Log.d(TAG, "Schedule alarm at " + alarmTime + " " + schedTime);
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 391f3a2..9ffeff9 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -17,7 +17,7 @@
package android.provider;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index f10e184..5247311 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -21,8 +21,8 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProviderClient;
diff --git a/core/java/android/provider/ContactsInternal.java b/core/java/android/provider/ContactsInternal.java
index 69c4b9b..aa2a89c 100644
--- a/core/java/android/provider/ContactsInternal.java
+++ b/core/java/android/provider/ContactsInternal.java
@@ -15,15 +15,14 @@
*/
package android.provider;
-import android.annotation.UnsupportedAppUsage;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.UriMatcher;
import android.net.Uri;
-import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.widget.Toast;
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index fd81178..4bbd213 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -22,7 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentInterface;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 9a384c6..48410a7 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -16,8 +16,8 @@
package android.provider;
-import android.annotation.UnsupportedAppUsage;
import android.app.DownloadManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.NetworkPolicyManager;
import android.net.Uri;
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 2299aad..f6cf1d2 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -27,9 +27,9 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e348b5f..1f3ae09 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -37,7 +37,6 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.ActivityThread;
import android.app.AppOpsManager;
@@ -46,6 +45,7 @@
import android.app.NotificationManager;
import android.app.SearchManager;
import android.app.WallpaperManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -231,7 +231,9 @@
* @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_TETHER_PROVISIONING =
+ @SystemApi
+ @TestApi
+ public static final String ACTION_TETHER_PROVISIONING_UI =
"android.settings.TETHER_PROVISIONING_UI";
/**
@@ -10441,6 +10443,8 @@
* is interpreted as |false|.
* @hide
*/
+ @SystemApi
+ @TestApi
public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
/**
@@ -15264,8 +15268,9 @@
* current time.
* @hide
*/
- public static boolean checkAndNoteWriteSettingsOperation(Context context, int uid,
- String callingPackage, boolean throwException) {
+ @SystemApi
+ public static boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
+ @NonNull String callingPackage, boolean throwException) {
return isCallingPackageAllowedToPerformAppOpsProtectedOperation(context, uid,
callingPackage, throwException, AppOpsManager.OP_WRITE_SETTINGS,
PM_WRITE_SETTINGS, true);
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index df36f14..90ac821 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -24,7 +24,7 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -35,6 +35,7 @@
import android.database.sqlite.SqliteWrapper;
import android.net.Uri;
import android.os.Build;
+import android.os.Bundle;
import android.os.Parcel;
import android.telephony.Rlog;
import android.telephony.ServiceState;
@@ -3522,7 +3523,8 @@
* can manage DPC-owned APNs.
* @hide
*/
- public static final Uri DPC_URI = Uri.parse("content://telephony/carriers/dpc");
+ @SystemApi
+ public static final @NonNull Uri DPC_URI = Uri.parse("content://telephony/carriers/dpc");
/**
* The {@code content://} style URL to be called from Telephony to query APNs.
@@ -3831,6 +3833,13 @@
public static final String USER_EDITABLE = "user_editable";
/**
+ * Integer value denoting an invalid APN id
+ * @hide
+ */
+ @SystemApi
+ public static final int INVALID_APN_ID = -1;
+
+ /**
* {@link #EDITED_STATUS APN edit status} indicates that this APN has not been edited or
* fails to edit.
* <p>Type: INTEGER </p>
@@ -4050,6 +4059,108 @@
public static final Uri MESSAGE_HISTORY_URI = Uri.parse("content://cellbroadcasts/history");
/**
+ * The authority for the legacy cellbroadcast provider.
+ * This is used for OEM data migration. OEMs want to migrate message history or
+ * sharepreference data to mainlined cellbroadcastreceiver app, should have a
+ * contentprovider with authority: cellbroadcast-legacy. Mainlined cellbroadcastreceiver
+ * will interact with this URI to retrieve data and persists to mainlined cellbroadcast app.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final @NonNull String AUTHORITY_LEGACY = "cellbroadcast-legacy";
+
+ /**
+ * A content:// style uri to the authority for the legacy cellbroadcast provider.
+ * @hide
+ */
+ @SystemApi
+ public static final @NonNull Uri AUTHORITY_LEGACY_URI =
+ Uri.parse("content://cellbroadcast-legacy");
+
+ /**
+ * Method name to {@link android.content.ContentProvider#call(String, String, Bundle)
+ * for {@link #AUTHORITY_LEGACY}. Used to query cellbroadcast {@link Preference},
+ * containing following supported entries
+ * <ul>
+ * <li>{@link #ENABLE_AREA_UPDATE_INFO_PREF}</li>
+ * <li>{@link #ENABLE_TEST_ALERT_PREF}</li>
+ * <li>{@link #ENABLE_STATE_LOCAL_TEST_PREF}</li>
+ * <li>{@link #ENABLE_PUBLIC_SAFETY_PREF}</li>
+ * <li>{@link #ENABLE_CMAS_AMBER_PREF}</li>
+ * <li>{@link #ENABLE_CMAS_SEVERE_THREAT_PREF}</li>
+ * <li>{@link #ENABLE_CMAS_EXTREME_THREAT_PREF}</li>
+ * <li>{@link #ENABLE_CMAS_PRESIDENTIAL_PREF}</li>
+ * <li>{@link #ENABLE_ALERT_VIBRATION_PREF}</li>
+ * <li>{@link #ENABLE_EMERGENCY_PERF}</li>
+ * <li>{@link #ENABLE_CMAS_IN_SECOND_LANGUAGE_PREF}</li>
+ * </ul>
+ * @hide
+ */
+ @SystemApi
+ public static final @NonNull String CALL_METHOD_GET_PREFERENCE = "get_preference";
+
+ /**
+ * Arg name to {@link android.content.ContentProvider#call(String, String, Bundle)}
+ * for {@link #AUTHORITY_LEGACY}.
+ * Contains all supported shared preferences for cellbroadcast.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final class Preference {
+ /**
+ * Not Instantiatable.
+ * @hide
+ */
+ private Preference() {}
+
+ /** Preference to enable area update info alert */
+ public static final @NonNull String ENABLE_AREA_UPDATE_INFO_PREF =
+ "enable_area_update_info_alerts";
+
+ /** Preference to enable test alert */
+ public static final @NonNull String ENABLE_TEST_ALERT_PREF =
+ "enable_test_alerts";
+
+ /** Preference to enable state local test alert */
+ public static final @NonNull String ENABLE_STATE_LOCAL_TEST_PREF
+ = "enable_state_local_test_alerts";
+
+ /** Preference to enable public safety alert */
+ public static final @NonNull String ENABLE_PUBLIC_SAFETY_PREF
+ = "enable_public_safety_messages";
+
+ /** Preference to enable amber alert */
+ public static final @NonNull String ENABLE_CMAS_AMBER_PREF
+ = "enable_cmas_amber_alerts";
+
+ /** Preference to enable severe threat alert */
+ public static final @NonNull String ENABLE_CMAS_SEVERE_THREAT_PREF
+ = "enable_cmas_severe_threat_alerts";
+
+ /** Preference to enable extreme threat alert */
+ public static final @NonNull String ENABLE_CMAS_EXTREME_THREAT_PREF =
+ "enable_cmas_extreme_threat_alerts";
+
+ /** Preference to enable presidential alert */
+ public static final @NonNull String ENABLE_CMAS_PRESIDENTIAL_PREF =
+ "enable_cmas_presidential_alerts";
+
+ /** Preference to enable alert vibration */
+ public static final @NonNull String ENABLE_ALERT_VIBRATION_PREF =
+ "enable_alert_vibrate";
+
+ /** Preference to enable emergency alert */
+ public static final @NonNull String ENABLE_EMERGENCY_PERF =
+ "enable_emergency_alerts";
+
+ /** Preference to enable receive alerts in second language */
+ public static final @NonNull String ENABLE_CMAS_IN_SECOND_LANGUAGE_PREF =
+ "receive_cmas_in_second_language";
+ }
+
+ /**
* The subscription which received this cell broadcast message.
* <P>Type: INTEGER</P>
*/
diff --git a/core/java/android/se/omapi/SEService.java b/core/java/android/se/omapi/SEService.java
index d646e23..a5c5c61 100644
--- a/core/java/android/se/omapi/SEService.java
+++ b/core/java/android/se/omapi/SEService.java
@@ -22,14 +22,11 @@
package android.se.omapi;
-import android.app.ActivityThread;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -101,6 +98,8 @@
private static final String TAG = "OMAPI.SEService";
+ private static final String UICC_TERMINAL = "SIM";
+
private final Object mLock = new Object();
/** The client context (e.g. activity). */
@@ -143,10 +142,6 @@
throw new NullPointerException("Arguments must not be null");
}
- if (!hasOMAPIReaders()) {
- throw new UnsupportedOperationException("Device does not support any OMAPI reader");
- }
-
mContext = context;
mSEListener.mListener = listener;
mSEListener.mExecutor = executor;
@@ -197,32 +192,33 @@
* is of length 0.
*/
public @NonNull Reader[] getReaders() {
- if (mSecureElementService == null) {
- throw new IllegalStateException("service not connected to system");
- }
- String[] readerNames;
- try {
- readerNames = mSecureElementService.getReaders();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
+ loadReaders();
- Reader[] readers = new Reader[readerNames.length];
- int i = 0;
- for (String readerName : readerNames) {
- if (mReaders.get(readerName) == null) {
- try {
- mReaders.put(readerName, new Reader(this, readerName,
- getReader(readerName)));
- readers[i++] = mReaders.get(readerName);
- } catch (Exception e) {
- Log.e(TAG, "Error adding Reader: " + readerName, e);
- }
- } else {
- readers[i++] = mReaders.get(readerName);
- }
- }
- return readers;
+ return mReaders.values().toArray(new Reader[0]);
+ }
+
+ /**
+ * Obtain a UICC Reader instance with specific slot number from the SecureElementService
+ *
+ * @param slotNumber The index of the uicc slot. The index starts from 1.
+ * @throws IllegalArgumentException if the reader object corresponding to the uiccSlotNumber
+ * is not exist.
+ * @return A Reader object for this uicc slot.
+ */
+ public @NonNull Reader getUiccReader(int slotNumber) {
+ if (slotNumber < 1) {
+ throw new IllegalArgumentException("slotNumber should be larger than 0");
+ }
+ loadReaders();
+
+ String readerName = UICC_TERMINAL + slotNumber;
+ Reader reader = mReaders.get(readerName);
+
+ if (reader == null) {
+ throw new IllegalArgumentException("Reader:" + readerName + " doesn't exist");
+ }
+
+ return reader;
}
/**
@@ -279,21 +275,28 @@
}
/**
- * Helper to check if this device support any OMAPI readers
+ * Load available Secure Element Readers
*/
- private static boolean hasOMAPIReaders() {
- IPackageManager pm = ActivityThread.getPackageManager();
- if (pm == null) {
- Log.e(TAG, "Cannot get package manager, assuming OMAPI readers supported");
- return true;
+ private void loadReaders() {
+ if (mSecureElementService == null) {
+ throw new IllegalStateException("service not connected to system");
}
+ String[] readerNames;
try {
- return pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_UICC, 0)
- || pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_ESE, 0)
- || pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_SD, 0);
+ readerNames = mSecureElementService.getReaders();
} catch (RemoteException e) {
- Log.e(TAG, "Package manager query failed, assuming OMAPI readers supported", e);
- return true;
+ throw e.rethrowAsRuntimeException();
+ }
+
+ for (String readerName : readerNames) {
+ if (mReaders.get(readerName) == null) {
+ try {
+ mReaders.put(readerName, new Reader(this, readerName,
+ getReader(readerName)));
+ } catch (Exception e) {
+ Log.e(TAG, "Error adding Reader: " + readerName, e);
+ }
+ }
}
}
}
diff --git a/core/java/android/security/KeystoreArguments.java b/core/java/android/security/KeystoreArguments.java
index e634234..a59c4e0 100644
--- a/core/java/android/security/KeystoreArguments.java
+++ b/core/java/android/security/KeystoreArguments.java
@@ -16,7 +16,7 @@
package android.security;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/keymaster/ExportResult.java b/core/java/android/security/keymaster/ExportResult.java
index 1be5ae9..037b852 100644
--- a/core/java/android/security/keymaster/ExportResult.java
+++ b/core/java/android/security/keymaster/ExportResult.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index 2eb2cef..d8382fa 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/keymaster/KeymasterArguments.java b/core/java/android/security/keymaster/KeymasterArguments.java
index d2dbdec..e009e12 100644
--- a/core/java/android/security/keymaster/KeymasterArguments.java
+++ b/core/java/android/security/keymaster/KeymasterArguments.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/keymaster/KeymasterBlob.java b/core/java/android/security/keymaster/KeymasterBlob.java
index 6a2024f..68365bf 100644
--- a/core/java/android/security/keymaster/KeymasterBlob.java
+++ b/core/java/android/security/keymaster/KeymasterBlob.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/keymaster/KeymasterBlobArgument.java b/core/java/android/security/keymaster/KeymasterBlobArgument.java
index fc562bd..81b08c5 100644
--- a/core/java/android/security/keymaster/KeymasterBlobArgument.java
+++ b/core/java/android/security/keymaster/KeymasterBlobArgument.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
/**
diff --git a/core/java/android/security/keymaster/KeymasterBooleanArgument.java b/core/java/android/security/keymaster/KeymasterBooleanArgument.java
index 4286aa0..25b2ac4 100644
--- a/core/java/android/security/keymaster/KeymasterBooleanArgument.java
+++ b/core/java/android/security/keymaster/KeymasterBooleanArgument.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
/**
diff --git a/core/java/android/security/keymaster/KeymasterDateArgument.java b/core/java/android/security/keymaster/KeymasterDateArgument.java
index 3e04c15..218f488 100644
--- a/core/java/android/security/keymaster/KeymasterDateArgument.java
+++ b/core/java/android/security/keymaster/KeymasterDateArgument.java
@@ -16,8 +16,9 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
+
import java.util.Date;
/**
diff --git a/core/java/android/security/keymaster/KeymasterIntArgument.java b/core/java/android/security/keymaster/KeymasterIntArgument.java
index 4aadce4..01d38c7 100644
--- a/core/java/android/security/keymaster/KeymasterIntArgument.java
+++ b/core/java/android/security/keymaster/KeymasterIntArgument.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
/**
diff --git a/core/java/android/security/keymaster/KeymasterLongArgument.java b/core/java/android/security/keymaster/KeymasterLongArgument.java
index bc2255e..3ac27cc 100644
--- a/core/java/android/security/keymaster/KeymasterLongArgument.java
+++ b/core/java/android/security/keymaster/KeymasterLongArgument.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
/**
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index c278eb3..b4e155a 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/net/config/RootTrustManager.java b/core/java/android/security/net/config/RootTrustManager.java
index d8936d9..58dc4ba 100644
--- a/core/java/android/security/net/config/RootTrustManager.java
+++ b/core/java/android/security/net/config/RootTrustManager.java
@@ -16,15 +16,16 @@
package android.security.net.config;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.net.Socket;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
-import android.annotation.UnsupportedAppUsage;
-import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
import javax.net.ssl.X509ExtendedTrustManager;
/**
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 38de794..de4a551 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -21,9 +21,9 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlarmManager;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.drawable.ColorDrawable;
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index b44c9d5..5da34a3 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -22,7 +22,6 @@
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.INotificationManager;
import android.app.Notification;
@@ -33,6 +32,7 @@
import android.app.Person;
import android.app.Service;
import android.companion.CompanionDeviceManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 905c781..d8ea971 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -17,10 +17,10 @@
package android.service.notification;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Person;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 93bcdbf..9e7af1f 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -20,11 +20,11 @@
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index bd953ca..e6b1922 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -19,8 +19,8 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
@@ -32,7 +32,6 @@
import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
-import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent;
import android.media.AudioFormat;
import android.os.AsyncTask;
import android.os.Handler;
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 0de17ca..36e057f 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.SdkConstant;
-import android.annotation.UnsupportedAppUsage;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/service/vr/VrListenerService.java b/core/java/android/service/vr/VrListenerService.java
index 3c38495..2758ace 100644
--- a/core/java/android/service/vr/VrListenerService.java
+++ b/core/java/android/service/vr/VrListenerService.java
@@ -18,9 +18,9 @@
import android.annotation.NonNull;
import android.annotation.SdkConstant;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/service/wallpaper/Android.bp b/core/java/android/service/wallpaper/Android.bp
index aa6123f..ffbdb03 100644
--- a/core/java/android/service/wallpaper/Android.bp
+++ b/core/java/android/service/wallpaper/Android.bp
@@ -6,6 +6,8 @@
"I*.aidl",
],
+ libs: ["unsupportedappusage"],
+
// Enforce that the library is built against java 8 so that there are
// no compatibility issues with launcher
java_version: "1.8",
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index d645e3f..3cb3ec3 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -20,11 +20,11 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Service;
import android.app.WallpaperColors;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 100774c..f3650d6 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -20,7 +20,7 @@
import android.annotation.RawRes;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java
index 2fab404..a8aea7c 100644
--- a/core/java/android/speech/tts/TtsEngines.java
+++ b/core/java/android/speech/tts/TtsEngines.java
@@ -18,7 +18,7 @@
import static android.provider.Settings.Secure.getString;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 146c1c3..f886cf5 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -21,10 +21,9 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Build;
-import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
@@ -179,6 +178,10 @@
* Listen for {@link android.telephony.Annotation.PreciseCallStates} of ringing,
* background and foreground calls.
*
+ * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+ * or the calling app has carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}).
+ *
* @hide
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@@ -188,13 +191,13 @@
/**
* Listen for {@link PreciseDataConnectionState} on the data connection (cellular).
*
- * <p>Requires permission {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+ * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
* or the calling app has carrier privileges
* (see {@link TelephonyManager#hasCarrierPrivileges}).
*
* @see #onPreciseDataConnectionStateChanged
*/
- @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE))
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 0x00001000;
/**
@@ -319,26 +322,36 @@
* Listen for call disconnect causes which contains {@link DisconnectCause} and
* {@link PreciseDisconnectCause}.
*
+ * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+ * or the calling app has carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}).
+ *
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
public static final int LISTEN_CALL_DISCONNECT_CAUSES = 0x02000000;
/**
* Listen for changes to the call attributes of a currently active call.
- * {@more}
- * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
- * READ_PRECISE_PHONE_STATE}
+ *
+ * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+ * or the calling app has carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}).
*
* @see #onCallAttributesChanged
* @hide
*/
@SystemApi
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 0x04000000;
/**
* Listen for IMS call disconnect causes which contains
* {@link android.telephony.ims.ImsReasonInfo}
*
+ * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+ * or the calling app has carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}).
+ *
* @see #onImsCallDisconnectCauseChanged(ImsReasonInfo)
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@@ -370,6 +383,21 @@
@RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 0x20000000;
+ /**
+ * Listen for Registration Failures.
+ *
+ * Listen for indications that a registration procedure has failed in either the CS or PS
+ * domain. This indication does not necessarily indicate a change of service state, which should
+ * be tracked via {@link #LISTEN_SERVICE_STATE}.
+ *
+ * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
+ * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+ *
+ * @see #onRegistrationFailed()
+ */
+ @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
+ public static final int LISTEN_REGISTRATION_FAILURE = 0x40000000;
+
/*
* Subscription used to listen to the phone state changes
* @hide
@@ -933,6 +961,38 @@
}
/**
+ * Report that Registration or a Location/Routing/Tracking Area update has failed.
+ *
+ * <p>Indicate whenever a registration procedure, including a location, routing, or tracking
+ * area update fails. This includes procedures that do not necessarily result in a change of
+ * the modem's registration status. If the modem's registration status changes, that is
+ * reflected in the onNetworkStateChanged() and subsequent get{Voice/Data}RegistrationState().
+ *
+ * <p>Because registration failures are ephemeral, this callback is not sticky.
+ * Registrants will not receive the most recent past value when registering.
+ *
+ * @param cellIdentity the CellIdentity, which must include the globally unique identifier
+ * for the cell (for example, all components of the CGI or ECGI).
+ * @param chosenPlmn a 5 or 6 digit alphanumeric PLMN (MCC|MNC) among those broadcast by the
+ * cell that was chosen for the failed registration attempt.
+ * @param domain DOMAIN_CS, DOMAIN_PS or both in case of a combined procedure.
+ * @param causeCode the primary failure cause code of the procedure.
+ * For GSM/UMTS (MM), values are in TS 24.008 Sec 10.5.95
+ * For GSM/UMTS (GMM), values are in TS 24.008 Sec 10.5.147
+ * For LTE (EMM), cause codes are TS 24.301 Sec 9.9.3.9
+ * For NR (5GMM), cause codes are TS 24.501 Sec 9.11.3.2
+ * Integer.MAX_VALUE if this value is unused.
+ * @param additionalCauseCode the cause code of any secondary/combined procedure if appropriate.
+ * For UMTS, if a combined attach succeeds for PS only, then the GMM cause code shall be
+ * included as an additionalCauseCode. For LTE (ESM), cause codes are in
+ * TS 24.301 9.9.4.4. Integer.MAX_VALUE if this value is unused.
+ */
+ public void onRegistrationFailed(@NonNull CellIdentity cellIdentity, @NonNull String chosenPlmn,
+ @NetworkRegistrationInfo.Domain int domain, int causeCode, int additionalCauseCode) {
+ // default implementation empty
+ }
+
+ /**
* The callback methods need to be called on the handler thread where
* this object was created. If the binder did that for us it'd be nice.
*
@@ -984,8 +1044,11 @@
() -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi)));
}
- public void onCellLocationChanged(Bundle bundle) {
- CellLocation location = CellLocation.newFromBundle(bundle);
+ public void onCellLocationChanged(CellIdentity cellIdentity) {
+ // There is no system/public API to create an CellIdentity in system server,
+ // so the server pass a null to indicate an empty initial location.
+ CellLocation location =
+ cellIdentity == null ? CellLocation.getEmpty() : cellIdentity.asCellLocation();
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
@@ -1201,6 +1264,18 @@
() -> psl.onImsCallDisconnectCauseChanged(disconnectCause)));
}
+
+ public void onRegistrationFailed(@NonNull CellIdentity cellIdentity,
+ @NonNull String chosenPlmn, @NetworkRegistrationInfo.Domain int domain,
+ int causeCode, int additionalCauseCode) {
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onRegistrationFailed(
+ cellIdentity, chosenPlmn, domain, causeCode, additionalCauseCode)));
+ // default implementation empty
+ }
}
diff --git a/core/java/android/telephony/Rlog.java b/core/java/android/telephony/Rlog.java
index cdab2dc..2afdd33 100644
--- a/core/java/android/telephony/Rlog.java
+++ b/core/java/android/telephony/Rlog.java
@@ -16,12 +16,11 @@
package android.telephony;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.text.TextUtils;
-import android.util.Log;
-
-import android.annotation.UnsupportedAppUsage;
import android.util.Base64;
+import android.util.Log;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
diff --git a/core/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
index ec2050f..28a5c20 100644
--- a/core/java/android/telephony/SubscriptionPlan.java
+++ b/core/java/android/telephony/SubscriptionPlan.java
@@ -24,6 +24,7 @@
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Annotation.NetworkType;
import android.util.Range;
import android.util.RecurrenceRule;
@@ -33,6 +34,7 @@
import java.lang.annotation.RetentionPolicy;
import java.time.Period;
import java.time.ZonedDateTime;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.Objects;
@@ -42,6 +44,14 @@
* as explaining how much mobile data they have remaining, and what will happen
* when they run out.
*
+ * If specifying network types, the developer must supply at least one plan
+ * that applies to all network types (default), and all additional plans
+ * may not include a particular network type more than once.
+ * This is enforced by {@link SubscriptionManager} when setting the plans.
+ *
+ * Plan selection will prefer plans that have specific network types defined
+ * over plans that apply to all network types.
+ *
* @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
* @see SubscriptionManager#getSubscriptionPlans(int)
*/
@@ -80,6 +90,8 @@
private int dataLimitBehavior = LIMIT_BEHAVIOR_UNKNOWN;
private long dataUsageBytes = BYTES_UNKNOWN;
private long dataUsageTime = TIME_UNKNOWN;
+ private @NetworkType int[] networkTypes;
+ private long networkTypesBitMask;
private SubscriptionPlan(RecurrenceRule cycleRule) {
this.cycleRule = Preconditions.checkNotNull(cycleRule);
@@ -93,6 +105,7 @@
dataLimitBehavior = source.readInt();
dataUsageBytes = source.readLong();
dataUsageTime = source.readLong();
+ networkTypes = source.createIntArray();
}
@Override
@@ -109,6 +122,7 @@
dest.writeInt(dataLimitBehavior);
dest.writeLong(dataUsageBytes);
dest.writeLong(dataUsageTime);
+ dest.writeIntArray(networkTypes);
}
@Override
@@ -121,13 +135,14 @@
.append(" dataLimitBehavior=").append(dataLimitBehavior)
.append(" dataUsageBytes=").append(dataUsageBytes)
.append(" dataUsageTime=").append(dataUsageTime)
+ .append(" networkTypes=").append(Arrays.toString(networkTypes))
.append("}").toString();
}
@Override
public int hashCode() {
return Objects.hash(cycleRule, title, summary, dataLimitBytes, dataLimitBehavior,
- dataUsageBytes, dataUsageTime);
+ dataUsageBytes, dataUsageTime, Arrays.hashCode(networkTypes));
}
@Override
@@ -140,7 +155,8 @@
&& dataLimitBytes == other.dataLimitBytes
&& dataLimitBehavior == other.dataLimitBehavior
&& dataUsageBytes == other.dataUsageBytes
- && dataUsageTime == other.dataUsageTime;
+ && dataUsageTime == other.dataUsageTime
+ && Arrays.equals(networkTypes, other.networkTypes);
}
return false;
}
@@ -204,6 +220,32 @@
}
/**
+ * Return an array containing all {@link NetworkType}s this SubscriptionPlan applies to.
+ * A null value means this SubscriptionPlan applies to all network types.
+ */
+ public @Nullable @NetworkType int[] getNetworkTypes() {
+ return networkTypes;
+ }
+
+ /**
+ * Return the networkTypes array converted to a {@link TelephonyManager.NetworkTypeBitMask}
+ * @hide
+ */
+ public long getNetworkTypesBitMask() {
+ // calculate bitmask the first time and save for future calls
+ if (networkTypesBitMask == 0) {
+ if (networkTypes == null) {
+ networkTypesBitMask = ~0;
+ } else {
+ for (int networkType : networkTypes) {
+ networkTypesBitMask |= TelephonyManager.getBitMaskForNetworkType(networkType);
+ }
+ }
+ }
+ return networkTypesBitMask;
+ }
+
+ /**
* Return an iterator that will return all valid data usage cycles based on
* any recurrence rules. The iterator starts from the currently active cycle
* and walks backwards through time.
@@ -335,5 +377,17 @@
plan.dataUsageTime = dataUsageTime;
return this;
}
+
+ /**
+ * Set the network types this SubscriptionPlan applies to.
+ *
+ * @param networkTypes a set of all {@link NetworkType}s that apply to this plan.
+ * A null value means the plan applies to all network types,
+ * and an empty array means the plan applies to no network types.
+ */
+ public @NonNull Builder setNetworkTypes(@Nullable @NetworkType int[] networkTypes) {
+ plan.networkTypes = networkTypes;
+ return this;
+ }
}
}
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index c11a99d..a242294 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -22,7 +22,6 @@
import android.annotation.TestApi;
import android.content.Context;
import android.os.Binder;
-import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Annotation.CallState;
@@ -116,7 +115,8 @@
};
mSubscriptionChangedListenerMap.put(listener, callback);
try {
- sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(), callback);
+ sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(),
+ null, callback);
} catch (RemoteException ex) {
// system server crash
}
@@ -175,7 +175,7 @@
mOpportunisticSubscriptionChangedListenerMap.put(listener, callback);
try {
sRegistry.addOnOpportunisticSubscriptionsChangedListener(mContext.getOpPackageName(),
- callback);
+ null, callback);
} catch (RemoteException ex) {
// system server crash
}
@@ -621,9 +621,9 @@
* Notify call disconnect causes which contains {@link DisconnectCause} and {@link
* android.telephony.PreciseDisconnectCause}.
*
- * @param subId for which call disconnected.
* @param slotIndex for which call disconnected. Can be derived from subId except when subId is
* invalid.
+ * @param subId for which call disconnected.
* @param cause {@link DisconnectCause} for the disconnected call.
* @param preciseCause {@link android.telephony.PreciseDisconnectCause} for the disconnected
* call.
@@ -639,10 +639,14 @@
}
/**
- * TODO change from bundle to CellLocation?
+ * Notify {@link android.telephony.CellLocation} changed.
+ *
+ * <p>To be compatible with {@link TelephonyRegistry}, use {@link CellIdentity} which is
+ * parcelable, and convert to CellLocation in client code.
+ *
* @hide
*/
- public void notifyCellLocation(int subId, Bundle cellLocation) {
+ public void notifyCellLocation(int subId, CellIdentity cellLocation) {
try {
sRegistry.notifyCellLocationForSubscriber(subId, cellLocation);
} catch (RemoteException ex) {
@@ -678,4 +682,36 @@
}
}
+
+ /**
+ * Report that Registration or a Location/Routing/Tracking Area update has failed.
+ *
+ * @param slotIndex for which call disconnected. Can be derived from subId except when subId is
+ * invalid.
+ * @param subId for which cellinfo changed.
+ * @param cellIdentity the CellIdentity, which must include the globally unique identifier
+ * for the cell (for example, all components of the CGI or ECGI).
+ * @param chosenPlmn a 5 or 6 digit alphanumeric PLMN (MCC|MNC) among those broadcast by the
+ * cell that was chosen for the failed registration attempt.
+ * @param domain DOMAIN_CS, DOMAIN_PS or both in case of a combined procedure.
+ * @param causeCode the primary failure cause code of the procedure.
+ * For GSM/UMTS (MM), values are in TS 24.008 Sec 10.5.95
+ * For GSM/UMTS (GMM), values are in TS 24.008 Sec 10.5.147
+ * For LTE (EMM), cause codes are TS 24.301 Sec 9.9.3.9
+ * For NR (5GMM), cause codes are TS 24.501 Sec 9.11.3.2
+ * Integer.MAX_VALUE if this value is unused.
+ * @param additionalCauseCode the cause code of any secondary/combined procedure if appropriate.
+ * For UMTS, if a combined attach succeeds for PS only, then the GMM cause code shall be
+ * included as an additionalCauseCode. For LTE (ESM), cause codes are in
+ * TS 24.301 9.9.4.4. Integer.MAX_VALUE if this value is unused.
+ */
+ public void notifyRegistrationFailed(int slotIndex, int subId,
+ @NonNull CellIdentity cellIdentity, @NonNull String chosenPlmn,
+ @NetworkRegistrationInfo.Domain int domain, int causeCode, int additionalCauseCode) {
+ try {
+ sRegistry.notifyRegistrationFailed(slotIndex, subId, cellIdentity,
+ chosenPlmn, domain, causeCode, additionalCauseCode);
+ } catch (RemoteException ex) {
+ }
+ }
}
diff --git a/core/java/android/text/AndroidBidi.java b/core/java/android/text/AndroidBidi.java
index bb7fb44..f1e2181 100644
--- a/core/java/android/text/AndroidBidi.java
+++ b/core/java/android/text/AndroidBidi.java
@@ -16,7 +16,7 @@
package android.text;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.icu.lang.UCharacter;
import android.icu.lang.UCharacterDirection;
import android.icu.lang.UProperty;
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index cf6987c..3ee1a90 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -16,7 +16,7 @@
package android.text;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 32982f9..c60d446 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -20,7 +20,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 19c55d5..b5688a4 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -21,7 +21,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.fonts.FontVariationAxis;
import android.net.Uri;
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index 18f8db2..55af087 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -16,9 +16,9 @@
package android.text;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.Application;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Typeface;
diff --git a/core/java/android/text/InputFilter.java b/core/java/android/text/InputFilter.java
index a9a7b2f..96e7bd0 100644
--- a/core/java/android/text/InputFilter.java
+++ b/core/java/android/text/InputFilter.java
@@ -17,7 +17,7 @@
package android.text;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.Preconditions;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 2c2c295..8a4497a 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 68199a4..57c1d23 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -17,7 +17,7 @@
package android.text;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.text.BreakIterator;
diff --git a/core/java/android/text/SpanSet.java b/core/java/android/text/SpanSet.java
index 362825a..81bdd65 100644
--- a/core/java/android/text/SpanSet.java
+++ b/core/java/android/text/SpanSet.java
@@ -16,7 +16,8 @@
package android.text;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.lang.reflect.Array;
import java.util.Arrays;
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 0d29da0..ac27e3d 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -17,7 +17,7 @@
package android.text;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.BaseCanvas;
import android.graphics.Paint;
import android.util.Log;
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index a986633..b85ef76 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -16,7 +16,7 @@
package android.text;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 69cfc03..85e2d98 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -20,7 +20,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Paint;
import android.graphics.text.LineBreaker;
import android.os.Build;
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 1c50d73..3c51fa7 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -19,7 +19,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
index d5aad33..73825b1 100644
--- a/core/java/android/text/TextPaint.java
+++ b/core/java/android/text/TextPaint.java
@@ -18,7 +18,7 @@
import android.annotation.ColorInt;
import android.annotation.Px;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Paint;
/**
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 81643e9..788d98b 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -24,7 +24,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.PluralsRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.icu.lang.UCharacter;
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 3c8de94..0863a81 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -17,9 +17,8 @@
package android.text.format;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.os.UserHandle;
import android.provider.Settings;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 90625183..f236f19 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -16,7 +16,7 @@
package android.text.format;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index d7baa10..17d3ae4 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.icu.text.MeasureFormat;
diff --git a/core/java/android/text/format/TimeFormatter.java b/core/java/android/text/format/TimeFormatter.java
index 5a14092..f7fd89d 100644
--- a/core/java/android/text/format/TimeFormatter.java
+++ b/core/java/android/text/format/TimeFormatter.java
@@ -26,6 +26,9 @@
import libcore.util.ZoneInfo;
import java.nio.CharBuffer;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.util.Formatter;
import java.util.Locale;
import java.util.TimeZone;
@@ -86,6 +89,59 @@
}
/**
+ * The implementation of {@link TimeMigrationUtils#formatMillisWithFixedFormat(long)} for
+ * 2038-safe formatting with the pattern "%Y-%m-%d %H:%M:%S" and including the historic
+ * incorrect digit localization behavior.
+ */
+ String formatMillisWithFixedFormat(long timeMillis) {
+ // This method is deliberately not a general purpose replacement for
+ // format(String, ZoneInfo.WallTime, ZoneInfo): It hard-codes the pattern used; many of the
+ // pattern characters supported by Time.format() have unusual behavior which would make
+ // using java.time.format or similar packages difficult. It would be a lot of work to share
+ // behavior and many internal Android usecases can be covered by this common pattern
+ // behavior.
+
+ // No need to worry about overflow / underflow: long millis is representable by Instant and
+ // LocalDateTime with room to spare.
+ Instant instant = Instant.ofEpochMilli(timeMillis);
+
+ // Date/times are calculated in the current system default time zone.
+ LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
+
+ // You'd think it would be as simple as:
+ // DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", locale);
+ // return formatter.format(localDateTime);
+ // but we retain Time's behavior around digits.
+
+ StringBuilder stringBuilder = new StringBuilder(19);
+
+ // This effectively uses the US locale because number localization is handled separately
+ // (see below).
+ stringBuilder.append(localDateTime.getYear());
+ stringBuilder.append('-');
+ append2DigitNumber(stringBuilder, localDateTime.getMonthValue());
+ stringBuilder.append('-');
+ append2DigitNumber(stringBuilder, localDateTime.getDayOfMonth());
+ stringBuilder.append(' ');
+ append2DigitNumber(stringBuilder, localDateTime.getHour());
+ stringBuilder.append(':');
+ append2DigitNumber(stringBuilder, localDateTime.getMinute());
+ stringBuilder.append(':');
+ append2DigitNumber(stringBuilder, localDateTime.getSecond());
+
+ String result = stringBuilder.toString();
+ return localizeDigits(result);
+ }
+
+ /** Zero-pads value as needed to achieve a 2-digit number. */
+ private static void append2DigitNumber(StringBuilder builder, int value) {
+ if (value < 10) {
+ builder.append('0');
+ }
+ builder.append(value);
+ }
+
+ /**
* Format the specified {@code wallTime} using {@code pattern}. The output is returned.
*/
public String format(String pattern, ZoneInfo.WallTime wallTime, ZoneInfo zoneInfo) {
@@ -99,12 +155,9 @@
formatInternal(pattern, wallTime, zoneInfo);
String result = stringBuilder.toString();
- // This behavior is the source of a bug since some formats are defined as being
- // in ASCII and not localized.
- if (localeData.zeroDigit != '0') {
- result = localizeDigits(result);
- }
- return result;
+ // The localizeDigits() behavior is the source of a bug since some formats are defined
+ // as being in ASCII and not localized.
+ return localizeDigits(result);
} finally {
outputBuilder = null;
numberFormatter = null;
@@ -112,6 +165,10 @@
}
private String localizeDigits(String s) {
+ if (localeData.zeroDigit == '0') {
+ return s;
+ }
+
int length = s.length();
int offsetToLocalizedDigits = localeData.zeroDigit - '0';
StringBuilder result = new StringBuilder(length);
diff --git a/core/java/android/text/format/TimeMigrationUtils.java b/core/java/android/text/format/TimeMigrationUtils.java
new file mode 100644
index 0000000..17bac8d
--- /dev/null
+++ b/core/java/android/text/format/TimeMigrationUtils.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.text.format;
+
+/**
+ * Logic to ease migration away from {@link Time} in Android internal code. {@link Time} is
+ * afflicted by the Y2038 issue and deprecated. The methods here are intended to allow minimal
+ * changes to classes that use {@link Time} for common behavior.
+ *
+ * @hide
+ */
+public class TimeMigrationUtils {
+
+ private TimeMigrationUtils() {}
+
+ /**
+ * A Y2038-safe replacement for various users of the {@link Time#format(String)} with the
+ * pattern "%Y-%m-%d %H:%M:%S". Note, this method retains the unusual localization behavior
+ * originally implemented by Time, which can lead to non-latin numbers being produced if the
+ * default locale does not use latin numbers.
+ */
+ public static String formatMillisWithFixedFormat(long timeMillis) {
+ // Delegate to TimeFormatter so that the unusual localization / threading behavior can be
+ // reused.
+ return new TimeFormatter().formatMillisWithFixedFormat(timeMillis);
+ }
+}
diff --git a/core/java/android/text/method/AllCapsTransformationMethod.java b/core/java/android/text/method/AllCapsTransformationMethod.java
index 5a7c98d..305b056 100644
--- a/core/java/android/text/method/AllCapsTransformationMethod.java
+++ b/core/java/android/text/method/AllCapsTransformationMethod.java
@@ -17,7 +17,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Rect;
import android.text.Spanned;
diff --git a/core/java/android/text/method/HideReturnsTransformationMethod.java b/core/java/android/text/method/HideReturnsTransformationMethod.java
index 440a4b1..40ce871 100644
--- a/core/java/android/text/method/HideReturnsTransformationMethod.java
+++ b/core/java/android/text/method/HideReturnsTransformationMethod.java
@@ -16,7 +16,7 @@
package android.text.method;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
/**
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index a0c44a8..c544c41 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -16,7 +16,7 @@
package android.text.method;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.text.Layout;
import android.text.NoCopySpan;
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
index ec7ed34b..d1d7c96 100644
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ b/core/java/android/text/method/MetaKeyKeyListener.java
@@ -16,7 +16,7 @@
package android.text.method;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.Editable;
import android.text.NoCopySpan;
import android.text.Spannable;
diff --git a/core/java/android/text/method/PasswordTransformationMethod.java b/core/java/android/text/method/PasswordTransformationMethod.java
index c96fc5d..53553be 100644
--- a/core/java/android/text/method/PasswordTransformationMethod.java
+++ b/core/java/android/text/method/PasswordTransformationMethod.java
@@ -16,7 +16,7 @@
package android.text.method;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/text/method/TransformationMethod2.java b/core/java/android/text/method/TransformationMethod2.java
index 0bf401a..8d5ec24 100644
--- a/core/java/android/text/method/TransformationMethod2.java
+++ b/core/java/android/text/method/TransformationMethod2.java
@@ -15,7 +15,7 @@
*/
package android.text.method;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* TransformationMethod2 extends the TransformationMethod interface
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
index 313567a..d766186 100644
--- a/core/java/android/text/method/WordIterator.java
+++ b/core/java/android/text/method/WordIterator.java
@@ -17,7 +17,7 @@
package android.text.method;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.icu.lang.UCharacter;
import android.icu.lang.UProperty;
import android.icu.text.BreakIterator;
diff --git a/core/java/android/text/style/BulletSpan.java b/core/java/android/text/style/BulletSpan.java
index 9b1dfbf..ad61788 100644
--- a/core/java/android/text/style/BulletSpan.java
+++ b/core/java/android/text/style/BulletSpan.java
@@ -21,7 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Px;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java
index 1a508a1..f37e423 100644
--- a/core/java/android/text/style/DynamicDrawableSpan.java
+++ b/core/java/android/text/style/DynamicDrawableSpan.java
@@ -22,7 +22,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
diff --git a/core/java/android/text/style/EasyEditSpan.java b/core/java/android/text/style/EasyEditSpan.java
index bfb2873..b23c2b7 100644
--- a/core/java/android/text/style/EasyEditSpan.java
+++ b/core/java/android/text/style/EasyEditSpan.java
@@ -17,8 +17,8 @@
package android.text.style;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextUtils;
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 98f58be..ec55aeb 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -19,7 +19,7 @@
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
diff --git a/core/java/android/text/style/SpellCheckSpan.java b/core/java/android/text/style/SpellCheckSpan.java
index 6ffde38..e8ec3c6 100644
--- a/core/java/android/text/style/SpellCheckSpan.java
+++ b/core/java/android/text/style/SpellCheckSpan.java
@@ -16,7 +16,7 @@
package android.text.style;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextUtils;
diff --git a/core/java/android/text/style/SuggestionRangeSpan.java b/core/java/android/text/style/SuggestionRangeSpan.java
index d958dde..2b04a7a 100644
--- a/core/java/android/text/style/SuggestionRangeSpan.java
+++ b/core/java/android/text/style/SuggestionRangeSpan.java
@@ -16,7 +16,7 @@
package android.text.style;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextPaint;
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index c000ae3..be01bfb 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -19,7 +19,7 @@
import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index df54209..6931a32 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
diff --git a/core/java/android/timezone/CountryTimeZones.java b/core/java/android/timezone/CountryTimeZones.java
new file mode 100644
index 0000000..e5bbdf4
--- /dev/null
+++ b/core/java/android/timezone/CountryTimeZones.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.icu.util.TimeZone;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Information about a country's time zones.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class CountryTimeZones {
+
+ /**
+ * A mapping to a time zone ID with some associated metadata.
+ *
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static final class TimeZoneMapping {
+
+ @NonNull
+ private libcore.timezone.CountryTimeZones.TimeZoneMapping mDelegate;
+
+ TimeZoneMapping(libcore.timezone.CountryTimeZones.TimeZoneMapping delegate) {
+ this.mDelegate = Objects.requireNonNull(delegate);
+ }
+
+ /**
+ * Returns the ID for this mapping. See also {@link #getTimeZone()} which handles when the
+ * ID is unrecognized.
+ */
+ @NonNull
+ public String getTimeZoneId() {
+ return mDelegate.timeZoneId;
+ }
+
+ /**
+ * Returns a {@link TimeZone} object for this mapping, or {@code null} if the ID is
+ * unrecognized.
+ */
+ @Nullable
+ public TimeZone getTimeZone() {
+ return mDelegate.getTimeZone();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TimeZoneMapping that = (TimeZoneMapping) o;
+ return this.mDelegate.equals(that.mDelegate);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.mDelegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return mDelegate.toString();
+ }
+ }
+
+ /**
+ * The result of lookup up a time zone using offset information (and possibly more).
+ *
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static final class OffsetResult {
+
+ private final TimeZone mTimeZone;
+ private final boolean mIsOnlyMatch;
+
+ /** Creates an instance with the supplied information. */
+ public OffsetResult(@NonNull TimeZone timeZone, boolean isOnlyMatch) {
+ mTimeZone = Objects.requireNonNull(timeZone);
+ mIsOnlyMatch = isOnlyMatch;
+ }
+
+ /**
+ * Returns a time zone that matches the supplied criteria.
+ */
+ @NonNull
+ public TimeZone getTimeZone() {
+ return mTimeZone;
+ }
+
+ /**
+ * Returns {@code true} if there is only one matching time zone for the supplied criteria.
+ */
+ public boolean isOnlyMatch() {
+ return mIsOnlyMatch;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ OffsetResult that = (OffsetResult) o;
+ return mIsOnlyMatch == that.mIsOnlyMatch
+ && mTimeZone.getID().equals(that.mTimeZone.getID());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mTimeZone, mIsOnlyMatch);
+ }
+
+ @Override
+ public String toString() {
+ return "OffsetResult{"
+ + "mTimeZone=" + mTimeZone
+ + ", mIsOnlyMatch=" + mIsOnlyMatch
+ + '}';
+ }
+ }
+
+ @NonNull
+ private final libcore.timezone.CountryTimeZones mDelegate;
+
+ CountryTimeZones(libcore.timezone.CountryTimeZones delegate) {
+ mDelegate = delegate;
+ }
+
+ /**
+ * Returns true if the ISO code for the country is a match for the one specified.
+ */
+ public boolean isForCountryCode(@NonNull String countryIso) {
+ return mDelegate.isForCountryCode(countryIso);
+ }
+
+ /**
+ * Returns the default time zone ID for the country. Can return {@code null} in cases when no
+ * data is available or the time zone ID was not recognized.
+ */
+ @Nullable
+ public String getDefaultTimeZoneId() {
+ return mDelegate.getDefaultTimeZoneId();
+ }
+
+ /**
+ * Returns the default time zone for the country. Can return {@code null} in cases when no data
+ * is available or the time zone ID was not recognized.
+ */
+ @Nullable
+ public TimeZone getDefaultTimeZone() {
+ return mDelegate.getDefaultTimeZone();
+ }
+
+ /**
+ * Qualifier for a country's default time zone. {@code true} indicates whether the default
+ * would be a good choice <em>generally</em> when there's no other information available.
+ */
+ public boolean isDefaultTimeZoneBoosted() {
+ return mDelegate.getDefaultTimeZoneBoost();
+ }
+
+ /**
+ * Returns true if the country has at least one zone that is the same as UTC at the given time.
+ */
+ public boolean hasUtcZone(long whenMillis) {
+ return mDelegate.hasUtcZone(whenMillis);
+ }
+
+ /**
+ * Returns a time zone for the country, if there is one, that matches the desired properties. If
+ * there are multiple matches and the {@code bias} is one of them then it is returned, otherwise
+ * an arbitrary match is returned based on the {@link #getEffectiveTimeZoneMappingsAt(long)}
+ * ordering.
+ *
+ * @param totalOffsetMillis the offset from UTC at {@code whenMillis}
+ * @param isDst the Daylight Savings Time state at {@code whenMillis}. {@code true} means DST,
+ * {@code false} means not DST, {@code null} means unknown
+ * @param dstOffsetMillis the part of {@code totalOffsetMillis} contributed by DST, only used if
+ * {@code isDst} is {@code true}. The value can be {@code null} if the DST offset is
+ * unknown
+ * @param whenMillis the UTC time to match against
+ * @param bias the time zone to prefer, can be {@code null}
+ */
+ @Nullable
+ public OffsetResult lookupByOffsetWithBias(int totalOffsetMillis, @Nullable Boolean isDst,
+ @SuppressLint("AutoBoxing") @Nullable Integer dstOffsetMillis, long whenMillis,
+ @Nullable TimeZone bias) {
+ libcore.timezone.CountryTimeZones.OffsetResult delegateOffsetResult =
+ mDelegate.lookupByOffsetWithBias(
+ totalOffsetMillis, isDst, dstOffsetMillis, whenMillis, bias);
+ return delegateOffsetResult == null ? null :
+ new OffsetResult(delegateOffsetResult.mTimeZone, delegateOffsetResult.mOneMatch);
+ }
+
+ /**
+ * Returns an immutable, ordered list of time zone mappings for the country in an undefined but
+ * "priority" order, filtered so that only "effective" time zone IDs are returned. An
+ * "effective" time zone is one that differs from another time zone used in the country after
+ * {@code whenMillis}. The list can be empty if there were no zones configured or the configured
+ * zone IDs were not recognized.
+ */
+ @NonNull
+ public List<TimeZoneMapping> getEffectiveTimeZoneMappingsAt(long whenMillis) {
+ List<libcore.timezone.CountryTimeZones.TimeZoneMapping> delegateList =
+ mDelegate.getEffectiveTimeZoneMappingsAt(whenMillis);
+
+ List<TimeZoneMapping> toReturn = new ArrayList<>(delegateList.size());
+ for (libcore.timezone.CountryTimeZones.TimeZoneMapping delegateMapping : delegateList) {
+ toReturn.add(new TimeZoneMapping(delegateMapping));
+ }
+ return Collections.unmodifiableList(toReturn);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ CountryTimeZones that = (CountryTimeZones) o;
+ return mDelegate.equals(that.mDelegate);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mDelegate);
+ }
+
+ @Override
+ public String toString() {
+ return mDelegate.toString();
+ }
+}
diff --git a/core/java/android/timezone/TelephonyLookup.java b/core/java/android/timezone/TelephonyLookup.java
new file mode 100644
index 0000000..eebccf4
--- /dev/null
+++ b/core/java/android/timezone/TelephonyLookup.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.Objects;
+
+/**
+ * A class that can find time zone-related information about telephony networks.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public class TelephonyLookup {
+
+ private static Object sLock = new Object();
+ @GuardedBy("sLock")
+ private static TelephonyLookup sInstance;
+
+ /**
+ * Obtains an instance for use when resolving telephony time zone information.
+ */
+ @NonNull
+ public static TelephonyLookup getInstance() {
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new TelephonyLookup(libcore.timezone.TelephonyLookup.getInstance());
+ }
+ return sInstance;
+ }
+ }
+
+ @NonNull
+ private final libcore.timezone.TelephonyLookup mDelegate;
+
+ private TelephonyLookup(@NonNull libcore.timezone.TelephonyLookup delegate) {
+ mDelegate = Objects.requireNonNull(delegate);
+ }
+
+ /**
+ * Returns an object capable of querying telephony network information. This method can return
+ * {@code null} in the event of an error while reading the underlying data files.
+ */
+ @Nullable
+ public TelephonyNetworkFinder getTelephonyNetworkFinder() {
+ libcore.timezone.TelephonyNetworkFinder telephonyNetworkFinderDelegate =
+ mDelegate.getTelephonyNetworkFinder();
+ return telephonyNetworkFinderDelegate != null
+ ? new TelephonyNetworkFinder(telephonyNetworkFinderDelegate) : null;
+ }
+}
diff --git a/core/java/android/timezone/TelephonyNetwork.java b/core/java/android/timezone/TelephonyNetwork.java
new file mode 100644
index 0000000..ae39fbd
--- /dev/null
+++ b/core/java/android/timezone/TelephonyNetwork.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
+import java.util.Objects;
+
+/**
+ * Information about a telephony network.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public class TelephonyNetwork {
+
+ @NonNull
+ private final libcore.timezone.TelephonyNetwork mDelegate;
+
+ TelephonyNetwork(@NonNull libcore.timezone.TelephonyNetwork delegate) {
+ mDelegate = Objects.requireNonNull(delegate);
+ }
+
+ /**
+ * Returns the Mobile Country Code of the network.
+ */
+ @NonNull
+ public String getMcc() {
+ return mDelegate.getMcc();
+ }
+
+ /**
+ * Returns the Mobile Network Code of the network.
+ */
+ @NonNull
+ public String getMnc() {
+ return mDelegate.getMnc();
+ }
+
+ /**
+ * Returns the country in which the network operates as an ISO 3166 alpha-2 (lower case).
+ */
+ @NonNull
+ public String getCountryIsoCode() {
+ return mDelegate.getCountryIsoCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TelephonyNetwork that = (TelephonyNetwork) o;
+ return mDelegate.equals(that.mDelegate);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mDelegate);
+ }
+
+ @Override
+ public String toString() {
+ return "TelephonyNetwork{"
+ + "mDelegate=" + mDelegate
+ + '}';
+ }
+}
diff --git a/core/java/android/timezone/TelephonyNetworkFinder.java b/core/java/android/timezone/TelephonyNetworkFinder.java
new file mode 100644
index 0000000..079d088
--- /dev/null
+++ b/core/java/android/timezone/TelephonyNetworkFinder.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+
+import java.util.Objects;
+
+/**
+ * A class that can find telephony network information loaded via {@link TelephonyLookup}.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public class TelephonyNetworkFinder {
+
+ @NonNull
+ private final libcore.timezone.TelephonyNetworkFinder mDelegate;
+
+ TelephonyNetworkFinder(libcore.timezone.TelephonyNetworkFinder delegate) {
+ mDelegate = Objects.requireNonNull(delegate);
+ }
+
+ /**
+ * Returns information held about a specific MCC + MNC combination. It is expected for this
+ * method to return {@code null}. Only known, unusual networks will typically have information
+ * returned, e.g. if they operate in countries other than the one suggested by their MCC.
+ */
+ @Nullable
+ public TelephonyNetwork findNetworkByMccMnc(@NonNull String mcc, @NonNull String mnc) {
+ Objects.requireNonNull(mcc);
+ Objects.requireNonNull(mnc);
+
+ libcore.timezone.TelephonyNetwork telephonyNetworkDelegate =
+ mDelegate.findNetworkByMccMnc(mcc, mnc);
+ return telephonyNetworkDelegate != null
+ ? new TelephonyNetwork(telephonyNetworkDelegate) : null;
+ }
+}
diff --git a/core/java/android/timezone/TimeZoneFinder.java b/core/java/android/timezone/TimeZoneFinder.java
new file mode 100644
index 0000000..9327b00
--- /dev/null
+++ b/core/java/android/timezone/TimeZoneFinder.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.Objects;
+
+/**
+ * A class that can be used to find time zones using information like country and offset.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class TimeZoneFinder {
+
+ private static Object sLock = new Object();
+ @GuardedBy("sLock")
+ private static TimeZoneFinder sInstance;
+
+ /**
+ * Obtains the singleton instance.
+ */
+ @NonNull
+ public static TimeZoneFinder getInstance() {
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new TimeZoneFinder(libcore.timezone.TimeZoneFinder.getInstance());
+ }
+ }
+ return sInstance;
+ }
+
+ @NonNull
+ private final libcore.timezone.TimeZoneFinder mDelegate;
+
+ private TimeZoneFinder(@NonNull libcore.timezone.TimeZoneFinder delegate) {
+ mDelegate = Objects.requireNonNull(delegate);
+ }
+
+ /**
+ * Returns the IANA rules version associated with the data. If there is no version information
+ * or there is a problem reading the file then {@code null} is returned.
+ */
+ @Nullable
+ public String getIanaVersion() {
+ return mDelegate.getIanaVersion();
+ }
+
+ /**
+ * Returns a {@link CountryTimeZones} object associated with the specified country code.
+ * Caching is handled as needed. If the country code is not recognized or there is an error
+ * during lookup this method can return null.
+ */
+ @Nullable
+ public CountryTimeZones lookupCountryTimeZones(@NonNull String countryIso) {
+ libcore.timezone.CountryTimeZones delegate = mDelegate.lookupCountryTimeZones(countryIso);
+ return delegate == null ? null : new CountryTimeZones(delegate);
+ }
+}
diff --git a/core/java/android/timezone/TzDataSetVersion.java b/core/java/android/timezone/TzDataSetVersion.java
new file mode 100644
index 0000000..aba7c4c
--- /dev/null
+++ b/core/java/android/timezone/TzDataSetVersion.java
@@ -0,0 +1,154 @@
+/*
+ * 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.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Version information associated with the set of time zone data on a device.
+ *
+ * <p>Time Zone Data Sets have a major ({@link #getFormatMajorVersion()}) and minor
+ * ({@link #currentFormatMinorVersion()}) version number:
+ * <ul>
+ * <li>Major version numbers are mutually incompatible. e.g. v2 is not compatible with a v1 or a
+ * v3 device.</li>
+ * <li>Minor version numbers are backwards compatible. e.g. a v2.2 data set will work
+ * on a v2.1 device but not a v2.3 device. The minor version is reset to 1 when the major version
+ * is incremented.</li>
+ * </ul>
+ *
+ * <p>Data sets contain time zone rules and other data associated wtih a tzdb release
+ * ({@link #getRulesVersion()}) and an additional Android-specific revision number
+ * ({@link #getRevision()}).
+ *
+ * <p>See platform/system/timezone/README.android for more information.
+ * @hide
+ */
+@VisibleForTesting
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class TzDataSetVersion {
+
+ /**
+ * Returns the major tz data format version supported by this device.
+ */
+ public static int currentFormatMajorVersion() {
+ return libcore.timezone.TzDataSetVersion.currentFormatMajorVersion();
+ }
+
+ /**
+ * Returns the minor tz data format version supported by this device.
+ */
+ public static int currentFormatMinorVersion() {
+ return libcore.timezone.TzDataSetVersion.currentFormatMinorVersion();
+ }
+
+ /**
+ * Returns true if the version information provided would be compatible with this device, i.e.
+ * with the current system image, and set of active modules.
+ */
+ public static boolean isCompatibleWithThisDevice(TzDataSetVersion tzDataSetVersion) {
+ return libcore.timezone.TzDataSetVersion.isCompatibleWithThisDevice(
+ tzDataSetVersion.mDelegate);
+ }
+
+ /**
+ * Reads the current Android time zone data set version file.
+ */
+ @NonNull
+ public static TzDataSetVersion read() throws IOException, TzDataSetException {
+ try {
+ return new TzDataSetVersion(
+ libcore.timezone.TzDataSetVersion.readTimeZoneModuleVersion());
+ } catch (libcore.timezone.TzDataSetVersion.TzDataSetException e) {
+ throw new TzDataSetException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * A checked exception used in connection with time zone data sets.
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static class TzDataSetException extends Exception {
+
+ /** Creates an instance with a message. */
+ public TzDataSetException(String message) {
+ super(message);
+ }
+
+ /** Creates an instance with a message and a cause. */
+ public TzDataSetException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+
+ @NonNull
+ private final libcore.timezone.TzDataSetVersion mDelegate;
+
+ private TzDataSetVersion(@NonNull libcore.timezone.TzDataSetVersion delegate) {
+ mDelegate = Objects.requireNonNull(delegate);
+ }
+
+ /** Returns the major version number. See {@link TzDataSetVersion}. */
+ public int getFormatMajorVersion() {
+ return mDelegate.formatMajorVersion;
+ }
+
+ /** Returns the minor version number. See {@link TzDataSetVersion}. */
+ public int getFormatMinorVersion() {
+ return mDelegate.formatMinorVersion;
+ }
+
+ /** Returns the tzdb version string. See {@link TzDataSetVersion}. */
+ @NonNull
+ public String getRulesVersion() {
+ return mDelegate.rulesVersion;
+ }
+
+ /** Returns the Android revision. See {@link TzDataSetVersion}. */
+ public int getRevision() {
+ return mDelegate.revision;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TzDataSetVersion that = (TzDataSetVersion) o;
+ return mDelegate.equals(that.mDelegate);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mDelegate);
+ }
+
+ @Override
+ public String toString() {
+ return mDelegate.toString();
+ }
+}
diff --git a/core/java/android/timezone/ZoneInfoDb.java b/core/java/android/timezone/ZoneInfoDb.java
new file mode 100644
index 0000000..eb191e8
--- /dev/null
+++ b/core/java/android/timezone/ZoneInfoDb.java
@@ -0,0 +1,66 @@
+/*
+ * 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.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.Objects;
+
+/**
+ * Android's internal factory for java.util.TimeZone objects. Provides access to core library time
+ * zone metadata not available via {@link java.util.TimeZone}.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class ZoneInfoDb {
+
+ private static Object sLock = new Object();
+ @GuardedBy("sLock")
+ private static ZoneInfoDb sInstance;
+
+ /**
+ * Obtains the singleton instance.
+ */
+ @NonNull
+ public static ZoneInfoDb getInstance() {
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new ZoneInfoDb(libcore.timezone.ZoneInfoDB.getInstance());
+ }
+ }
+ return sInstance;
+ }
+
+ @NonNull
+ private final libcore.timezone.ZoneInfoDB mDelegate;
+
+ private ZoneInfoDb(libcore.timezone.ZoneInfoDB delegate) {
+ mDelegate = Objects.requireNonNull(delegate);
+ }
+
+ /**
+ * Returns the tzdb version in use.
+ */
+ @NonNull
+ public String getVersion() {
+ return mDelegate.getVersion();
+ }
+}
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index de182da..59a05ac 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -22,7 +22,7 @@
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.RectEvaluator;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
diff --git a/core/java/android/transition/Scene.java b/core/java/android/transition/Scene.java
index 8d4db54..52a97e3 100644
--- a/core/java/android/transition/Scene.java
+++ b/core/java/android/transition/Scene.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.util.SparseArray;
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 0feab4d..e511584 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -20,7 +20,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Path;
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 0e5252e..1b0612e 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -17,7 +17,7 @@
package android.transition;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.ArrayMap;
import android.util.Log;
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index d899dde..5643d5a 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index d6a35e1..489d579 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -18,7 +18,7 @@
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import libcore.util.EmptyArray;
diff --git a/core/java/android/util/Base64.java b/core/java/android/util/Base64.java
index ecc0c9c..92abd7c 100644
--- a/core/java/android/util/Base64.java
+++ b/core/java/android/util/Base64.java
@@ -16,7 +16,8 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.UnsupportedEncodingException;
/**
diff --git a/core/java/android/util/Base64OutputStream.java b/core/java/android/util/Base64OutputStream.java
index 230a3a5..48fadeb 100644
--- a/core/java/android/util/Base64OutputStream.java
+++ b/core/java/android/util/Base64OutputStream.java
@@ -16,7 +16,8 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
index 55d114b..1b4905a 100644
--- a/core/java/android/util/DebugUtils.java
+++ b/core/java/android/util/DebugUtils.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import java.io.PrintWriter;
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 7c7223c..4c08b59 100755
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.SystemProperties;
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 65d825a..c9dc05b 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -17,7 +17,7 @@
package android.util;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.BufferedReader;
import java.io.FileReader;
diff --git a/core/java/android/util/IconDrawableFactory.java b/core/java/android/util/IconDrawableFactory.java
index d90b65e..be10d94 100644
--- a/core/java/android/util/IconDrawableFactory.java
+++ b/core/java/android/util/IconDrawableFactory.java
@@ -15,8 +15,8 @@
*/
package android.util;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index 0203430..63fe61f 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.SystemClock;
import java.io.FileDescriptor;
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 50779031..3077b79 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.DeadSystemException;
import com.android.internal.os.RuntimeInit;
@@ -387,6 +387,25 @@
public static native int println_native(int bufID, int priority, String tag, String msg);
/**
+ * Send a log message to the "radio" log buffer, which can be dumped with
+ * {@code adb logcat -b radio}.
+ *
+ * <p>Only the telephony mainline module should use it.
+ *
+ * <p>Note ART will protect {@code MODULE_LIBRARIES} system APIs from regular app code.
+ *
+ * @param priority Log priority.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param message The message you would like logged.
+ * @hide
+ */
+ public static int logToRadioBuffer(@Level int priority, @Nullable String tag,
+ @Nullable String message) {
+ return println_native(LOG_ID_RADIO, priority, tag, message);
+ }
+
+ /**
* Return the maximum payload the log daemon accepts without truncation.
* @return LOGGER_ENTRY_MAX_PAYLOAD.
*/
diff --git a/core/java/android/util/LogWriter.java b/core/java/android/util/LogWriter.java
index b062ace..a674ae1 100644
--- a/core/java/android/util/LogWriter.java
+++ b/core/java/android/util/LogWriter.java
@@ -16,7 +16,8 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.Writer;
/** @hide */
diff --git a/core/java/android/util/LongArray.java b/core/java/android/util/LongArray.java
index 6f4aa52..93bcd6b 100644
--- a/core/java/android/util/LongArray.java
+++ b/core/java/android/util/LongArray.java
@@ -17,7 +17,7 @@
package android.util;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index 7b7eea0..75f4135 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
diff --git a/core/java/android/util/LruCache.java b/core/java/android/util/LruCache.java
index f04e7cb..d35c82b 100644
--- a/core/java/android/util/LruCache.java
+++ b/core/java/android/util/LruCache.java
@@ -16,7 +16,8 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.LinkedHashMap;
import java.util.Map;
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index 0eeef70..971e161 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
/**
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index da566c9..0892c94 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -16,7 +16,9 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
@@ -28,151 +30,267 @@
import android.provider.Settings;
import android.text.TextUtils;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.Objects;
+import java.util.function.Supplier;
+
/**
- * {@link TrustedTime} that connects with a remote NTP server as its trusted
- * time source.
+ * A singleton that connects with a remote NTP server as its trusted time source. This class
+ * is thread-safe. The {@link #forceRefresh()} method is synchronous, i.e. it may occupy the
+ * current thread while performing an NTP request. All other threads calling {@link #forceRefresh()}
+ * will block during that request.
*
* @hide
*/
public class NtpTrustedTime implements TrustedTime {
+
+ /**
+ * The result of a successful NTP query.
+ *
+ * @hide
+ */
+ public static class TimeResult {
+ private final long mTimeMillis;
+ private final long mElapsedRealtimeMillis;
+ private final long mCertaintyMillis;
+
+ public TimeResult(long timeMillis, long elapsedRealtimeMillis, long certaintyMillis) {
+ mTimeMillis = timeMillis;
+ mElapsedRealtimeMillis = elapsedRealtimeMillis;
+ mCertaintyMillis = certaintyMillis;
+ }
+
+ public long getTimeMillis() {
+ return mTimeMillis;
+ }
+
+ public long getElapsedRealtimeMillis() {
+ return mElapsedRealtimeMillis;
+ }
+
+ public long getCertaintyMillis() {
+ return mCertaintyMillis;
+ }
+
+ /** Calculates and returns the current time accounting for the age of this result. */
+ public long currentTimeMillis() {
+ return mTimeMillis + getAgeMillis();
+ }
+
+ /** Calculates and returns the age of this result. */
+ public long getAgeMillis() {
+ return SystemClock.elapsedRealtime() - mElapsedRealtimeMillis;
+ }
+
+ @Override
+ public String toString() {
+ return "TimeResult{"
+ + "mTimeMillis=" + mTimeMillis
+ + ", mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
+ + ", mCertaintyMillis=" + mCertaintyMillis
+ + '}';
+ }
+ }
+
private static final String TAG = "NtpTrustedTime";
private static final boolean LOGD = false;
private static NtpTrustedTime sSingleton;
- private static Context sContext;
- private final String mServer;
- private final long mTimeout;
+ @NonNull
+ private final Context mContext;
- private ConnectivityManager mCM;
+ /**
+ * A supplier that returns the ConnectivityManager. The Supplier can return null if
+ * ConnectivityService isn't running yet.
+ */
+ private final Supplier<ConnectivityManager> mConnectivityManagerSupplier =
+ new Supplier<ConnectivityManager>() {
+ private ConnectivityManager mConnectivityManager;
- private boolean mHasCache;
- private long mCachedNtpTime;
- private long mCachedNtpElapsedRealtime;
- private long mCachedNtpCertainty;
+ @Nullable
+ @Override
+ public synchronized ConnectivityManager get() {
+ // We can't do this at initialization time: ConnectivityService might not be running
+ // yet.
+ if (mConnectivityManager == null) {
+ mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+ }
+ return mConnectivityManager;
+ }
+ };
- private NtpTrustedTime(String server, long timeout) {
- if (LOGD) Log.d(TAG, "creating NtpTrustedTime using " + server);
- mServer = server;
- mTimeout = timeout;
+ // Declared volatile and accessed outside of synchronized blocks to avoid blocking reads during
+ // forceRefresh().
+ private volatile TimeResult mTimeResult;
+
+ private NtpTrustedTime(Context context) {
+ mContext = Objects.requireNonNull(context);
}
@UnsupportedAppUsage
public static synchronized NtpTrustedTime getInstance(Context context) {
if (sSingleton == null) {
- final Resources res = context.getResources();
- final ContentResolver resolver = context.getContentResolver();
-
- final String defaultServer = res.getString(
- com.android.internal.R.string.config_ntpServer);
- final long defaultTimeout = res.getInteger(
- com.android.internal.R.integer.config_ntpTimeout);
-
- final String secureServer = Settings.Global.getString(
- resolver, Settings.Global.NTP_SERVER);
- final long timeout = Settings.Global.getLong(
- resolver, Settings.Global.NTP_TIMEOUT, defaultTimeout);
-
- final String server = secureServer != null ? secureServer : defaultServer;
- sSingleton = new NtpTrustedTime(server, timeout);
- sContext = context;
+ Context appContext = context.getApplicationContext();
+ sSingleton = new NtpTrustedTime(appContext);
}
-
return sSingleton;
}
- @Override
@UnsupportedAppUsage
public boolean forceRefresh() {
- // We can't do this at initialization time: ConnectivityService might not be running yet.
synchronized (this) {
- if (mCM == null) {
- mCM = sContext.getSystemService(ConnectivityManager.class);
+ NtpConnectionInfo connectionInfo = getNtpConnectionInfo();
+ if (connectionInfo == null) {
+ // missing server config, so no trusted time available
+ if (LOGD) Log.d(TAG, "forceRefresh: invalid server config");
+ return false;
}
- }
- final Network network = mCM == null ? null : mCM.getActiveNetwork();
- return forceRefresh(network);
- }
-
- public boolean forceRefresh(Network network) {
- if (TextUtils.isEmpty(mServer)) {
- // missing server, so no trusted time available
- return false;
- }
-
- // We can't do this at initialization time: ConnectivityService might not be running yet.
- synchronized (this) {
- if (mCM == null) {
- mCM = sContext.getSystemService(ConnectivityManager.class);
+ ConnectivityManager connectivityManager = mConnectivityManagerSupplier.get();
+ if (connectivityManager == null) {
+ if (LOGD) Log.d(TAG, "forceRefresh: no ConnectivityManager");
+ return false;
}
- }
+ final Network network = connectivityManager.getActiveNetwork();
+ final NetworkInfo ni = connectivityManager.getNetworkInfo(network);
+ if (ni == null || !ni.isConnected()) {
+ if (LOGD) Log.d(TAG, "forceRefresh: no connectivity");
+ return false;
+ }
- final NetworkInfo ni = mCM == null ? null : mCM.getNetworkInfo(network);
- if (ni == null || !ni.isConnected()) {
- if (LOGD) Log.d(TAG, "forceRefresh: no connectivity");
- return false;
- }
-
-
- if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
- final SntpClient client = new SntpClient();
- if (client.requestTime(mServer, (int) mTimeout, network)) {
- mHasCache = true;
- mCachedNtpTime = client.getNtpTime();
- mCachedNtpElapsedRealtime = client.getNtpTimeReference();
- mCachedNtpCertainty = client.getRoundTripTime() / 2;
- return true;
- } else {
- return false;
+ if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
+ final SntpClient client = new SntpClient();
+ final String serverName = connectionInfo.getServer();
+ final int timeoutMillis = connectionInfo.getTimeoutMillis();
+ if (client.requestTime(serverName, timeoutMillis, network)) {
+ long ntpCertainty = client.getRoundTripTime() / 2;
+ mTimeResult = new TimeResult(
+ client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty);
+ return true;
+ } else {
+ return false;
+ }
}
}
- @Override
+ /**
+ * Only kept for UnsupportedAppUsage.
+ *
+ * @deprecated Use {@link #getCachedTimeResult()} to obtain a {@link TimeResult} atomically.
+ */
+ @Deprecated
@UnsupportedAppUsage
public boolean hasCache() {
- return mHasCache;
+ return mTimeResult != null;
}
+ /**
+ * Only kept for UnsupportedAppUsage.
+ *
+ * @deprecated Use {@link #getCachedTimeResult()} to obtain a {@link TimeResult} atomically.
+ */
+ @Deprecated
@Override
public long getCacheAge() {
- if (mHasCache) {
- return SystemClock.elapsedRealtime() - mCachedNtpElapsedRealtime;
+ TimeResult timeResult = mTimeResult;
+ if (timeResult != null) {
+ return SystemClock.elapsedRealtime() - timeResult.getElapsedRealtimeMillis();
} else {
return Long.MAX_VALUE;
}
}
- @Override
- public long getCacheCertainty() {
- if (mHasCache) {
- return mCachedNtpCertainty;
- } else {
- return Long.MAX_VALUE;
- }
- }
-
- @Override
+ /**
+ * Only kept for UnsupportedAppUsage.
+ *
+ * @deprecated Use {@link #getCachedTimeResult()} to obtain a {@link TimeResult} atomically.
+ */
+ @Deprecated
@UnsupportedAppUsage
public long currentTimeMillis() {
- if (!mHasCache) {
+ TimeResult timeResult = mTimeResult;
+ if (timeResult == null) {
throw new IllegalStateException("Missing authoritative time source");
}
if (LOGD) Log.d(TAG, "currentTimeMillis() cache hit");
// current time is age after the last ntp cache; callers who
- // want fresh values will hit makeAuthoritative() first.
- return mCachedNtpTime + getCacheAge();
+ // want fresh values will hit forceRefresh() first.
+ return timeResult.currentTimeMillis();
}
+ /**
+ * Only kept for UnsupportedAppUsage.
+ *
+ * @deprecated Use {@link #getCachedTimeResult()} to obtain a {@link TimeResult} atomically.
+ */
+ @Deprecated
@UnsupportedAppUsage
public long getCachedNtpTime() {
if (LOGD) Log.d(TAG, "getCachedNtpTime() cache hit");
- return mCachedNtpTime;
+ TimeResult timeResult = mTimeResult;
+ return timeResult == null ? 0 : timeResult.getTimeMillis();
}
+ /**
+ * Only kept for UnsupportedAppUsage.
+ *
+ * @deprecated Use {@link #getCachedTimeResult()} to obtain a {@link TimeResult} atomically.
+ */
+ @Deprecated
@UnsupportedAppUsage
public long getCachedNtpTimeReference() {
- return mCachedNtpElapsedRealtime;
+ TimeResult timeResult = mTimeResult;
+ return timeResult == null ? 0 : timeResult.getElapsedRealtimeMillis();
+ }
+
+ /**
+ * Returns an object containing the latest NTP information available. Can return {@code null} if
+ * no information is available.
+ */
+ @Nullable
+ public TimeResult getCachedTimeResult() {
+ return mTimeResult;
+ }
+
+ private static class NtpConnectionInfo {
+
+ @NonNull private final String mServer;
+ private final int mTimeoutMillis;
+
+ NtpConnectionInfo(@NonNull String server, int timeoutMillis) {
+ mServer = Objects.requireNonNull(server);
+ mTimeoutMillis = timeoutMillis;
+ }
+
+ @NonNull
+ public String getServer() {
+ return mServer;
+ }
+
+ int getTimeoutMillis() {
+ return mTimeoutMillis;
+ }
+ }
+
+ @GuardedBy("this")
+ private NtpConnectionInfo getNtpConnectionInfo() {
+ final ContentResolver resolver = mContext.getContentResolver();
+
+ final Resources res = mContext.getResources();
+ final String defaultServer = res.getString(
+ com.android.internal.R.string.config_ntpServer);
+ final int defaultTimeoutMillis = res.getInteger(
+ com.android.internal.R.integer.config_ntpTimeout);
+
+ final String secureServer = Settings.Global.getString(
+ resolver, Settings.Global.NTP_SERVER);
+ final int timeoutMillis = Settings.Global.getInt(
+ resolver, Settings.Global.NTP_TIMEOUT, defaultTimeoutMillis);
+
+ final String server = secureServer != null ? secureServer : defaultServer;
+ return TextUtils.isEmpty(server) ? null : new NtpConnectionInfo(server, timeoutMillis);
}
}
diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java
index 5342d5d..1e5ec0b 100644
--- a/core/java/android/util/PathParser.java
+++ b/core/java/android/util/PathParser.java
@@ -14,7 +14,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Path;
import dalvik.annotation.optimization.FastNative;
diff --git a/core/java/android/util/Pools.java b/core/java/android/util/Pools.java
index e242fe5..7ae32441 100644
--- a/core/java/android/util/Pools.java
+++ b/core/java/android/util/Pools.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Helper class for crating pools of objects. An example use looks like this:
diff --git a/core/java/android/util/Rational.java b/core/java/android/util/Rational.java
index 39e8b14..5930000 100644
--- a/core/java/android/util/Rational.java
+++ b/core/java/android/util/Rational.java
@@ -15,9 +15,10 @@
*/
package android.util;
-import static com.android.internal.util.Preconditions.*;
+import static com.android.internal.util.Preconditions.checkNotNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.IOException;
import java.io.InvalidObjectException;
diff --git a/core/java/android/util/RecurrenceRule.java b/core/java/android/util/RecurrenceRule.java
index 9c60228..a570e5e 100644
--- a/core/java/android/util/RecurrenceRule.java
+++ b/core/java/android/util/RecurrenceRule.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/util/Singleton.java b/core/java/android/util/Singleton.java
index 15c6b5b..92646b4 100644
--- a/core/java/android/util/Singleton.java
+++ b/core/java/android/util/Singleton.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Singleton helper class for lazily initialization.
diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java
index a85120f..2c8bbbf 100644
--- a/core/java/android/util/Slog.java
+++ b/core/java/android/util/Slog.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
/**
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 0a15db2..3a0d1f5 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index d6e0e53..846df39 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 1ca1717..d4f6685 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
diff --git a/core/java/android/util/StatsEvent.java b/core/java/android/util/StatsEvent.java
new file mode 100644
index 0000000..c765945
--- /dev/null
+++ b/core/java/android/util/StatsEvent.java
@@ -0,0 +1,829 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.SystemClock;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * StatsEvent builds and stores the buffer sent over the statsd socket.
+ * This class defines and encapsulates the socket protocol.
+ *
+ * <p>Usage:</p>
+ * <pre>
+ * // Pushed event
+ * StatsEvent statsEvent = StatsEvent.newBuilder()
+ * .setAtomId(atomId)
+ * .writeBoolean(false)
+ * .writeString("annotated String field")
+ * .addBooleanAnnotation(annotationId, true)
+ * .usePooledBuffer()
+ * .build();
+ * StatsLog.write(statsEvent);
+ *
+ * // Pulled event
+ * StatsEvent statsEvent = StatsEvent.newBuilder()
+ * .setAtomId(atomId)
+ * .writeBoolean(false)
+ * .writeString("annotated String field")
+ * .addBooleanAnnotation(annotationId, true)
+ * .build();
+ * </pre>
+ * @hide
+ **/
+public final class StatsEvent {
+ // Type Ids.
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_INT = 0x00;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_LONG = 0x01;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_STRING = 0x02;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_LIST = 0x03;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_FLOAT = 0x04;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_BOOLEAN = 0x05;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_BYTE_ARRAY = 0x06;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_OBJECT = 0x07;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_ERRORS = 0x0F;
+
+ // Error flags.
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_NO_TIMESTAMP = 0x1;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_NO_ATOM_ID = 0x2;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_OVERFLOW = 0x4;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_TOO_MANY_FIELDS = 0x200;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x1000;
+
+ // Size limits.
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_ANNOTATION_COUNT = 15;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_ATTRIBUTION_NODES = 127;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_NUM_ELEMENTS = 127;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_KEY_VALUE_PAIRS = 127;
+
+ private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;
+
+ // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag.
+ // See android_util_StatsLog.cpp.
+ private static final int MAX_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4;
+
+ private final int mAtomId;
+ private final byte[] mPayload;
+ private Buffer mBuffer;
+ private final int mNumBytes;
+
+ private StatsEvent(final int atomId, @Nullable final Buffer buffer,
+ @NonNull final byte[] payload, final int numBytes) {
+ mAtomId = atomId;
+ mBuffer = buffer;
+ mPayload = payload;
+ mNumBytes = numBytes;
+ }
+
+ /**
+ * Returns a new StatsEvent.Builder for building StatsEvent object.
+ **/
+ @NonNull
+ public static StatsEvent.Builder newBuilder() {
+ return new StatsEvent.Builder(Buffer.obtain());
+ }
+
+ /**
+ * Get the atom Id of the atom encoded in this StatsEvent object.
+ *
+ * @hide
+ **/
+ public int getAtomId() {
+ return mAtomId;
+ }
+
+ /**
+ * Get the byte array that contains the encoded payload that can be sent to statsd.
+ *
+ * @hide
+ **/
+ @NonNull
+ public byte[] getBytes() {
+ return mPayload;
+ }
+
+ /**
+ * Get the number of bytes used to encode the StatsEvent payload.
+ *
+ * @hide
+ **/
+ public int getNumBytes() {
+ return mNumBytes;
+ }
+
+ /**
+ * Recycle resources used by this StatsEvent object.
+ * No actions should be taken on this StatsEvent after release() is called.
+ **/
+ public void release() {
+ if (mBuffer != null) {
+ mBuffer.release();
+ mBuffer = null;
+ }
+ }
+
+ /**
+ * Builder for constructing a StatsEvent object.
+ *
+ * <p>This class defines and encapsulates the socket encoding for the buffer.
+ * The write methods must be called in the same order as the order of fields in the
+ * atom definition.</p>
+ *
+ * <p>setAtomId() can be called anytime before build().</p>
+ *
+ * <p>Example:</p>
+ * <pre>
+ * // Atom definition.
+ * message MyAtom {
+ * optional int32 field1 = 1;
+ * optional int64 field2 = 2;
+ * optional string field3 = 3 [(annotation1) = true];
+ * }
+ *
+ * // StatsEvent construction for pushed event.
+ * StatsEvent.newBuilder()
+ * StatsEvent statsEvent = StatsEvent.newBuilder()
+ * .setAtomId(atomId)
+ * .writeInt(3) // field1
+ * .writeLong(8L) // field2
+ * .writeString("foo") // field 3
+ * .addBooleanAnnotation(annotation1Id, true)
+ * .usePooledBuffer()
+ * .build();
+ *
+ * // StatsEvent construction for pulled event.
+ * StatsEvent.newBuilder()
+ * StatsEvent statsEvent = StatsEvent.newBuilder()
+ * .setAtomId(atomId)
+ * .writeInt(3) // field1
+ * .writeLong(8L) // field2
+ * .writeString("foo") // field 3
+ * .addBooleanAnnotation(annotation1Id, true)
+ * .build();
+ * </pre>
+ **/
+ public static final class Builder {
+ // Fixed positions.
+ private static final int POS_NUM_ELEMENTS = 1;
+ private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES;
+ private static final int POS_ATOM_ID = POS_TIMESTAMP_NS + Byte.BYTES + Long.BYTES;
+
+ private final Buffer mBuffer;
+ private long mTimestampNs;
+ private int mAtomId;
+ private byte mCurrentAnnotationCount;
+ private int mPos;
+ private int mPosLastField;
+ private byte mLastType;
+ private int mNumElements;
+ private int mErrorMask;
+ private boolean mUsePooledBuffer = false;
+
+ private Builder(final Buffer buffer) {
+ mBuffer = buffer;
+ mCurrentAnnotationCount = 0;
+ mAtomId = 0;
+ mTimestampNs = SystemClock.elapsedRealtimeNanos();
+ mNumElements = 0;
+
+ // Set mPos to 0 for writing TYPE_OBJECT at 0th position.
+ mPos = 0;
+ writeTypeId(TYPE_OBJECT);
+
+ // Set mPos to after atom id's location in the buffer.
+ // First 2 elements in the buffer are event timestamp followed by the atom id.
+ mPos = POS_ATOM_ID + Byte.BYTES + Integer.BYTES;
+ mPosLastField = 0;
+ mLastType = 0;
+ }
+
+ /**
+ * Sets the atom id for this StatsEvent.
+ **/
+ @NonNull
+ public Builder setAtomId(final int atomId) {
+ mAtomId = atomId;
+ return this;
+ }
+
+ /**
+ * Sets the timestamp in nanos for this StatsEvent.
+ **/
+ @VisibleForTesting
+ @NonNull
+ public Builder setTimestampNs(final long timestampNs) {
+ mTimestampNs = timestampNs;
+ return this;
+ }
+
+ /**
+ * Write a boolean field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeBoolean(final boolean value) {
+ // Write boolean typeId byte followed by boolean byte representation.
+ writeTypeId(TYPE_BOOLEAN);
+ mPos += mBuffer.putBoolean(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write an integer field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeInt(final int value) {
+ // Write integer typeId byte followed by 4-byte representation of value.
+ writeTypeId(TYPE_INT);
+ mPos += mBuffer.putInt(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write a long field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeLong(final long value) {
+ // Write long typeId byte followed by 8-byte representation of value.
+ writeTypeId(TYPE_LONG);
+ mPos += mBuffer.putLong(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write a float field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeFloat(final float value) {
+ // Write float typeId byte followed by 4-byte representation of value.
+ writeTypeId(TYPE_FLOAT);
+ mPos += mBuffer.putFloat(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write a String field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeString(@NonNull final String value) {
+ // Write String typeId byte, followed by 4-byte representation of number of bytes
+ // in the UTF-8 encoding, followed by the actual UTF-8 byte encoding of value.
+ final byte[] valueBytes = stringToBytes(value);
+ writeByteArray(valueBytes, TYPE_STRING);
+ return this;
+ }
+
+ /**
+ * Write a byte array field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeByteArray(@NonNull final byte[] value) {
+ // Write byte array typeId byte, followed by 4-byte representation of number of bytes
+ // in value, followed by the actual byte array.
+ writeByteArray(value, TYPE_BYTE_ARRAY);
+ return this;
+ }
+
+ private void writeByteArray(@NonNull final byte[] value, final byte typeId) {
+ writeTypeId(typeId);
+ final int numBytes = value.length;
+ mPos += mBuffer.putInt(mPos, numBytes);
+ mPos += mBuffer.putByteArray(mPos, value);
+ mNumElements++;
+ }
+
+ /**
+ * Write an attribution chain field to this StatsEvent.
+ *
+ * The sizes of uids and tags must be equal. The AttributionNode at position i is
+ * made up of uids[i] and tags[i].
+ *
+ * @param uids array of uids in the attribution nodes.
+ * @param tags array of tags in the attribution nodes.
+ **/
+ @NonNull
+ public Builder writeAttributionChain(
+ @NonNull final int[] uids, @NonNull final String[] tags) {
+ final byte numUids = (byte) uids.length;
+ final byte numTags = (byte) tags.length;
+
+ if (numUids != numTags) {
+ mErrorMask |= ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL;
+ } else if (numUids > MAX_ATTRIBUTION_NODES) {
+ mErrorMask |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG;
+ } else {
+ // Write attribution chain typeId byte, followed by 1-byte representation of
+ // number of attribution nodes, followed by encoding of each attribution node.
+ writeTypeId(TYPE_ATTRIBUTION_CHAIN);
+ mPos += mBuffer.putByte(mPos, numUids);
+ for (int i = 0; i < numUids; i++) {
+ // Each uid is encoded as 4-byte representation of its int value.
+ mPos += mBuffer.putInt(mPos, uids[i]);
+
+ // Each tag is encoded as 4-byte representation of number of bytes in its
+ // UTF-8 encoding, followed by the actual UTF-8 bytes.
+ final byte[] tagBytes = stringToBytes(tags[i]);
+ mPos += mBuffer.putInt(mPos, tagBytes.length);
+ mPos += mBuffer.putByteArray(mPos, tagBytes);
+ }
+ mNumElements++;
+ }
+ return this;
+ }
+
+ /**
+ * Write KeyValuePairsAtom entries to this StatsEvent.
+ *
+ * @param intMap Integer key-value pairs.
+ * @param longMap Long key-value pairs.
+ * @param stringMap String key-value pairs.
+ * @param floatMap Float key-value pairs.
+ **/
+ @NonNull
+ public Builder writeKeyValuePairs(
+ @NonNull final SparseIntArray intMap,
+ @NonNull final SparseLongArray longMap,
+ @NonNull final SparseArray<String> stringMap,
+ @NonNull final SparseArray<Float> floatMap) {
+ final int intMapSize = intMap.size();
+ final int longMapSize = longMap.size();
+ final int stringMapSize = stringMap.size();
+ final int floatMapSize = floatMap.size();
+ final int totalCount = intMapSize + longMapSize + stringMapSize + floatMapSize;
+
+ if (totalCount > MAX_KEY_VALUE_PAIRS) {
+ mErrorMask |= ERROR_TOO_MANY_KEY_VALUE_PAIRS;
+ } else {
+ writeTypeId(TYPE_KEY_VALUE_PAIRS);
+ mPos += mBuffer.putByte(mPos, (byte) totalCount);
+
+ for (int i = 0; i < intMapSize; i++) {
+ final int key = intMap.keyAt(i);
+ final int value = intMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_INT);
+ mPos += mBuffer.putInt(mPos, value);
+ }
+
+ for (int i = 0; i < longMapSize; i++) {
+ final int key = longMap.keyAt(i);
+ final long value = longMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_LONG);
+ mPos += mBuffer.putLong(mPos, value);
+ }
+
+ for (int i = 0; i < stringMapSize; i++) {
+ final int key = stringMap.keyAt(i);
+ final String value = stringMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_STRING);
+ final byte[] valueBytes = stringToBytes(value);
+ mPos += mBuffer.putInt(mPos, valueBytes.length);
+ mPos += mBuffer.putByteArray(mPos, valueBytes);
+ }
+
+ for (int i = 0; i < floatMapSize; i++) {
+ final int key = floatMap.keyAt(i);
+ final float value = floatMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_FLOAT);
+ mPos += mBuffer.putFloat(mPos, value);
+ }
+
+ mNumElements++;
+ }
+
+ return this;
+ }
+
+ /**
+ * Write a boolean annotation for the last field written.
+ **/
+ @NonNull
+ public Builder addBooleanAnnotation(
+ final byte annotationId, final boolean value) {
+ // Ensure there's a field written to annotate.
+ if (0 == mPosLastField) {
+ mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
+ } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
+ mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
+ } else {
+ mPos += mBuffer.putByte(mPos, annotationId);
+ mPos += mBuffer.putByte(mPos, TYPE_BOOLEAN);
+ mPos += mBuffer.putBoolean(mPos, value);
+ mCurrentAnnotationCount++;
+ writeAnnotationCount();
+ }
+ return this;
+ }
+
+ /**
+ * Write an integer annotation for the last field written.
+ **/
+ @NonNull
+ public Builder addIntAnnotation(final byte annotationId, final int value) {
+ if (0 == mPosLastField) {
+ mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
+ } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
+ mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
+ } else {
+ mPos += mBuffer.putByte(mPos, annotationId);
+ mPos += mBuffer.putByte(mPos, TYPE_INT);
+ mPos += mBuffer.putInt(mPos, value);
+ mCurrentAnnotationCount++;
+ writeAnnotationCount();
+ }
+ return this;
+ }
+
+ /**
+ * Indicates to reuse Buffer's byte array as the underlying payload in StatsEvent.
+ * This should be called for pushed events to reduce memory allocations and garbage
+ * collections.
+ **/
+ @NonNull
+ public Builder usePooledBuffer() {
+ mUsePooledBuffer = true;
+ return this;
+ }
+
+ /**
+ * Builds a StatsEvent object with values entered in this Builder.
+ **/
+ @NonNull
+ public StatsEvent build() {
+ if (0L == mTimestampNs) {
+ mErrorMask |= ERROR_NO_TIMESTAMP;
+ }
+ if (0 == mAtomId) {
+ mErrorMask |= ERROR_NO_ATOM_ID;
+ }
+ if (mBuffer.hasOverflowed()) {
+ mErrorMask |= ERROR_OVERFLOW;
+ }
+ if (mNumElements > MAX_NUM_ELEMENTS) {
+ mErrorMask |= ERROR_TOO_MANY_FIELDS;
+ }
+
+ int size = mPos;
+ mPos = POS_TIMESTAMP_NS;
+ writeLong(mTimestampNs);
+ writeInt(mAtomId);
+ if (0 == mErrorMask) {
+ mBuffer.putByte(POS_NUM_ELEMENTS, (byte) mNumElements);
+ } else {
+ mPos += mBuffer.putByte(mPos, TYPE_ERRORS);
+ mPos += mBuffer.putInt(mPos, mErrorMask);
+ mBuffer.putByte(POS_NUM_ELEMENTS, (byte) 3);
+ size = mPos;
+ }
+
+ if (mUsePooledBuffer) {
+ return new StatsEvent(mAtomId, mBuffer, mBuffer.getBytes(), size);
+ } else {
+ // Create a copy of the buffer with the required number of bytes.
+ final byte[] payload = new byte[size];
+ System.arraycopy(mBuffer.getBytes(), 0, payload, 0, size);
+
+ // Return Buffer instance to the pool.
+ mBuffer.release();
+
+ return new StatsEvent(mAtomId, null, payload, size);
+ }
+ }
+
+ private void writeTypeId(final byte typeId) {
+ mPosLastField = mPos;
+ mLastType = typeId;
+ mCurrentAnnotationCount = 0;
+ final byte encodedId = (byte) (typeId & 0x0F);
+ mPos += mBuffer.putByte(mPos, encodedId);
+ }
+
+ private void writeAnnotationCount() {
+ // Use first 4 bits for annotation count and last 4 bits for typeId.
+ final byte encodedId = (byte) ((mCurrentAnnotationCount << 4) | (mLastType & 0x0F));
+ mBuffer.putByte(mPosLastField, encodedId);
+ }
+
+ @NonNull
+ private static byte[] stringToBytes(@Nullable final String value) {
+ return (null == value ? "" : value).getBytes(UTF_8);
+ }
+ }
+
+ private static final class Buffer {
+ private static Object sLock = new Object();
+
+ @GuardedBy("sLock")
+ private static Buffer sPool;
+
+ private final byte[] mBytes = new byte[MAX_PAYLOAD_SIZE];
+ private boolean mOverflow = false;
+
+ @NonNull
+ private static Buffer obtain() {
+ final Buffer buffer;
+ synchronized (sLock) {
+ buffer = null == sPool ? new Buffer() : sPool;
+ sPool = null;
+ }
+ buffer.reset();
+ return buffer;
+ }
+
+ private Buffer() {
+ }
+
+ @NonNull
+ private byte[] getBytes() {
+ return mBytes;
+ }
+
+ private void release() {
+ synchronized (sLock) {
+ if (null == sPool) {
+ sPool = this;
+ }
+ }
+ }
+
+ private void reset() {
+ mOverflow = false;
+ }
+
+ private boolean hasOverflowed() {
+ return mOverflow;
+ }
+
+ /**
+ * Checks for available space in the byte array.
+ *
+ * @param index starting position in the buffer to start the check.
+ * @param numBytes number of bytes to check from index.
+ * @return true if space is available, false otherwise.
+ **/
+ private boolean hasEnoughSpace(final int index, final int numBytes) {
+ final boolean result = index + numBytes < MAX_PAYLOAD_SIZE;
+ if (!result) {
+ mOverflow = true;
+ }
+ return result;
+ }
+
+ /**
+ * Writes a byte into the buffer.
+ *
+ * @param index position in the buffer where the byte is written.
+ * @param value the byte to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putByte(final int index, final byte value) {
+ if (hasEnoughSpace(index, Byte.BYTES)) {
+ mBytes[index] = (byte) (value);
+ return Byte.BYTES;
+ }
+ return 0;
+ }
+
+ /**
+ * Writes a boolean into the buffer.
+ *
+ * @param index position in the buffer where the boolean is written.
+ * @param value the boolean to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putBoolean(final int index, final boolean value) {
+ return putByte(index, (byte) (value ? 1 : 0));
+ }
+
+ /**
+ * Writes an integer into the buffer.
+ *
+ * @param index position in the buffer where the integer is written.
+ * @param value the integer to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putInt(final int index, final int value) {
+ if (hasEnoughSpace(index, Integer.BYTES)) {
+ // Use little endian byte order.
+ mBytes[index] = (byte) (value);
+ mBytes[index + 1] = (byte) (value >> 8);
+ mBytes[index + 2] = (byte) (value >> 16);
+ mBytes[index + 3] = (byte) (value >> 24);
+ return Integer.BYTES;
+ }
+ return 0;
+ }
+
+ /**
+ * Writes a long into the buffer.
+ *
+ * @param index position in the buffer where the long is written.
+ * @param value the long to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putLong(final int index, final long value) {
+ if (hasEnoughSpace(index, Long.BYTES)) {
+ // Use little endian byte order.
+ mBytes[index] = (byte) (value);
+ mBytes[index + 1] = (byte) (value >> 8);
+ mBytes[index + 2] = (byte) (value >> 16);
+ mBytes[index + 3] = (byte) (value >> 24);
+ mBytes[index + 4] = (byte) (value >> 32);
+ mBytes[index + 5] = (byte) (value >> 40);
+ mBytes[index + 6] = (byte) (value >> 48);
+ mBytes[index + 7] = (byte) (value >> 56);
+ return Long.BYTES;
+ }
+ return 0;
+ }
+
+ /**
+ * Writes a float into the buffer.
+ *
+ * @param index position in the buffer where the float is written.
+ * @param value the float to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putFloat(final int index, final float value) {
+ return putInt(index, Float.floatToIntBits(value));
+ }
+
+ /**
+ * Copies a byte array into the buffer.
+ *
+ * @param index position in the buffer where the byte array is copied.
+ * @param value the byte array to copy.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putByteArray(final int index, @NonNull final byte[] value) {
+ final int numBytes = value.length;
+ if (hasEnoughSpace(index, numBytes)) {
+ System.arraycopy(value, 0, mBytes, index, numBytes);
+ return numBytes;
+ }
+ return 0;
+ }
+ }
+}
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index ae9966b..23fd4f2 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -244,6 +244,19 @@
*/
private static native void writeImpl(@NonNull byte[] buffer, int size, int atomId);
+ /**
+ * Write an event to stats log using the raw format encapsulated in StatsEvent.
+ * After writing to stats log, release() is called on the StatsEvent object.
+ * No further action should be taken on the StatsEvent object following this call.
+ *
+ * @param statsEvent The StatsEvent object containing the encoded buffer of data to write.
+ * @hide
+ */
+ public static void write(@NonNull final StatsEvent statsEvent) {
+ writeImpl(statsEvent.getBytes(), statsEvent.getNumBytes(), statsEvent.getAtomId());
+ statsEvent.release();
+ }
+
private static void enforceDumpCallingPermission(Context context) {
context.enforceCallingPermission(android.Manifest.permission.DUMP, "Need DUMP permission.");
}
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 74cff20..dbd3f69 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.SystemClock;
@@ -88,7 +88,7 @@
*
* <p>The list returned may be different from other on-device sources like
* {@link android.icu.util.TimeZone#getRegion(String)} as it can be curated to avoid
- * contentious mappings.
+ * contentious or obsolete mappings.
*
* @param countryCode the ISO 3166-1 alpha-2 code for the country as can be obtained using
* {@link java.util.Locale#getCountry()}
diff --git a/core/java/android/util/TrustedTime.java b/core/java/android/util/TrustedTime.java
index c78665d..f41fe85 100644
--- a/core/java/android/util/TrustedTime.java
+++ b/core/java/android/util/TrustedTime.java
@@ -16,46 +16,52 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Interface that provides trusted time information, possibly coming from an NTP
- * server. Implementations may cache answers until {@link #forceRefresh()}.
+ * server.
*
* @hide
+ * @deprecated Only kept for UnsupportedAppUsage. Do not use. See {@link NtpTrustedTime}
*/
public interface TrustedTime {
/**
* Force update with an external trusted time source, returning {@code true}
* when successful.
+ *
+ * @deprecated Only kept for UnsupportedAppUsage. Do not use. See {@link NtpTrustedTime}
*/
+ @Deprecated
@UnsupportedAppUsage
public boolean forceRefresh();
/**
* Check if this instance has cached a response from a trusted time source.
+ *
+ * @deprecated Only kept for UnsupportedAppUsage. Do not use. See {@link NtpTrustedTime}
*/
+ @Deprecated
@UnsupportedAppUsage
- public boolean hasCache();
+ boolean hasCache();
/**
* Return time since last trusted time source contact, or
* {@link Long#MAX_VALUE} if never contacted.
+ *
+ * @deprecated Only kept for UnsupportedAppUsage. Do not use. See {@link NtpTrustedTime}
*/
+ @Deprecated
@UnsupportedAppUsage
public long getCacheAge();
/**
- * Return certainty of cached trusted time in milliseconds, or
- * {@link Long#MAX_VALUE} if never contacted. Smaller values are more
- * precise.
- */
- public long getCacheCertainty();
-
- /**
* Return current time similar to {@link System#currentTimeMillis()},
* possibly using a cached authoritative time source.
+ *
+ * @deprecated Only kept for UnsupportedAppUsage. Do not use. See {@link NtpTrustedTime}
*/
+ @Deprecated
@UnsupportedAppUsage
- public long currentTimeMillis();
+ long currentTimeMillis();
}
diff --git a/core/java/android/util/XmlPullAttributes.java b/core/java/android/util/XmlPullAttributes.java
index 32fe16f..d83b355 100644
--- a/core/java/android/util/XmlPullAttributes.java
+++ b/core/java/android/util/XmlPullAttributes.java
@@ -16,13 +16,12 @@
package android.util;
-import org.xmlpull.v1.XmlPullParser;
-
-import android.annotation.UnsupportedAppUsage;
-import android.util.AttributeSet;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+
/**
* Provides an implementation of AttributeSet on top of an XmlPullParser.
*/
diff --git a/core/java/android/util/proto/ProtoOutputStream.java b/core/java/android/util/proto/ProtoOutputStream.java
index 6efcfbf..7b24ba9 100644
--- a/core/java/android/util/proto/ProtoOutputStream.java
+++ b/core/java/android/util/proto/ProtoOutputStream.java
@@ -16,7 +16,8 @@
package android.util.proto;
-import android.annotation.TestApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.util.Log;
import java.io.FileDescriptor;
@@ -28,19 +29,23 @@
/**
* Class to write to a protobuf stream.
*
- * Each write method takes an ID code from the protoc generated classes
- * and the value to write. To make a nested object, call #start
- * and then #end when you are done.
+ * <p>
+ * This API is not as convenient or type safe as the standard protobuf
+ * classes. If possible, the best recommended library is to use protobuf lite.
+ * However, in environements (such as the Android platform itself), a
+ * more memory efficient version is necessary.
*
- * The ID codes have type information embedded into them, so if you call
- * the incorrect function you will get an IllegalArgumentException.
+ * <p>Each write method takes an ID code from the protoc generated classes
+ * and the value to write. To make a nested object, call {@link #start(long)}
+ * and then {@link #end(long)} when you are done.
*
- * To retrieve the encoded protobuf stream, call getBytes().
+ * <p>The ID codes have type information embedded into them, so if you call
+ * the incorrect function you will get an {@link IllegalArgumentException}.
*
- * TODO: Add a constructor that takes an OutputStream and write to that
+ * <p>To retrieve the encoded protobuf stream, call {@link #getBytes()}.
+ *
* stream as the top-level objects are finished.
*
- * @hide
*/
/* IMPLEMENTATION NOTES
@@ -99,7 +104,6 @@
* correctly matched pairs of #start and #end calls, and issue
* errors if they are not matched.
*/
-@TestApi
public final class ProtoOutputStream extends ProtoStream {
/**
* @hide
@@ -124,7 +128,9 @@
/**
* An ID given to objects and returned in the token from startObject
* and stored in the buffer until endObject is called, where the two
- * are checked. Starts at -1 and becomes more negative, so the values
+ * are checked.
+ *
+ * <p>Starts at -1 and becomes more negative, so the values
* aren't likely to alias with the size it will be overwritten with,
* which tend to be small, and we will be more likely to catch when
* the caller of endObject uses a stale token that they didn't intend
@@ -133,8 +139,9 @@
private int mNextObjectId = -1;
/**
- * The object token we are expecting in endObject. If another call to
- * startObject happens, this is written to that location, which gives
+ * The object token we are expecting in endObject.
+ *
+ * <p>If another call to startObject happens, this is written to that location, which gives
* us a stack, stored in the space for the as-yet unused size fields.
*/
private long mExpectedObjectToken;
@@ -151,39 +158,45 @@
private boolean mCompacted;
/**
- * Construct a ProtoOutputStream with the default chunk size.
+ * Construct a {@link ProtoOutputStream} with the default chunk size.
+ *
+ * <p>This is for an in-memory proto. The caller should use {@link #getBytes()} for the result.
*/
public ProtoOutputStream() {
this(0);
}
/**
- * Construct a ProtoOutputStream with the given chunk size.
+ * Construct a {@link ProtoOutputStream with the given chunk size.
+ *
+ * <p>This is for an in-memory proto. The caller should use {@link #getBytes()} for the result.
*/
public ProtoOutputStream(int chunkSize) {
mBuffer = new EncodedBuffer(chunkSize);
}
/**
- * Construct a ProtoOutputStream that sits on top of an OutputStream.
- * @more
- * The {@link #flush() flush()} method must be called when done writing
- * to flush any remanining data, althought data *may* be written at intermediate
+ * Construct a {@link ProtoOutputStream} that sits on top of an {@link OutputStream}.
+ *
+ * <p>The {@link #flush()} method must be called when done writing
+ * to flush any remaining data, although data *may* be written at intermediate
* points within the writing as well.
*/
- public ProtoOutputStream(OutputStream stream) {
+ public ProtoOutputStream(@NonNull OutputStream stream) {
this();
mStream = stream;
}
/**
- * Construct a ProtoOutputStream that sits on top of a FileDescriptor.
- * @more
- * The {@link #flush() flush()} method must be called when done writing
- * to flush any remanining data, althought data *may* be written at intermediate
+ * Construct a {@link ProtoOutputStream} that sits on top of a {@link FileDescriptor}.
+ *
+ * <p>The {@link #flush()} method must be called when done writing
+ * to flush any remaining data, although data *may* be written at intermediate
* points within the writing as well.
+ *
+ * @hide
*/
- public ProtoOutputStream(FileDescriptor fd) {
+ public ProtoOutputStream(@NonNull FileDescriptor fd) {
this(new FileOutputStream(fd));
}
@@ -202,7 +215,7 @@
/**
* Write a value for the given fieldId.
*
- * Will automatically convert for the following field types, and
+ * <p>Will automatically convert for the following field types, and
* throw an exception for others: double, float, int32, int64, uint32, uint64,
* sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
*
@@ -337,7 +350,7 @@
/**
* Write a value for the given fieldId.
*
- * Will automatically convert for the following field types, and
+ * <p>Will automatically convert for the following field types, and
* throw an exception for others: double, float, int32, int64, uint32, uint64,
* sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
*
@@ -472,7 +485,7 @@
/**
* Write a value for the given fieldId.
*
- * Will automatically convert for the following field types, and
+ * <p>Will automatically convert for the following field types, and
* throw an exception for others: double, float, int32, int64, uint32, uint64,
* sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
*
@@ -607,7 +620,7 @@
/**
* Write a value for the given fieldId.
*
- * Will automatically convert for the following field types, and
+ * <p>Will automatically convert for the following field types, and
* throw an exception for others: double, float, int32, int64, uint32, uint64,
* sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum.
*
@@ -742,7 +755,7 @@
/**
* Write a boolean value for the given fieldId.
*
- * If the field is not a bool field, an exception will be thrown.
+ * <p>If the field is not a bool field, an {@link IllegalStateException} will be thrown.
*
* @param fieldId The field identifier constant from the generated class.
* @param val The value.
@@ -771,12 +784,12 @@
/**
* Write a string value for the given fieldId.
*
- * If the field is not a string field, an exception will be thrown.
+ * <p>If the field is not a string field, an exception will be thrown.
*
* @param fieldId The field identifier constant from the generated class.
* @param val The value.
*/
- public void write(long fieldId, String val) {
+ public void write(long fieldId, @Nullable String val) {
assertNotCompacted();
final int id = (int)fieldId;
@@ -800,12 +813,12 @@
/**
* Write a byte[] value for the given fieldId.
*
- * If the field is not a bytes or object field, an exception will be thrown.
+ * <p>If the field is not a bytes or object field, an exception will be thrown.
*
* @param fieldId The field identifier constant from the generated class.
* @param val The value.
*/
- public void write(long fieldId, byte[] val) {
+ public void write(long fieldId, @Nullable byte[] val) {
assertNotCompacted();
final int id = (int)fieldId;
@@ -836,6 +849,9 @@
/**
* Start a sub object.
+ *
+ * @param fieldId The field identifier constant from the generated class.
+ * @return The token to call {@link #end(long)} with.
*/
public long start(long fieldId) {
assertNotCompacted();
@@ -855,6 +871,8 @@
/**
* End the object started by start() that returned token.
+ *
+ * @param token The token returned from {@link #start(long)}
*/
public void end(long token) {
endObjectImpl(token, getRepeatedFromToken(token));
@@ -870,7 +888,8 @@
/**
* Write a single proto "double" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, double)} instead.
+ * @hide
*/
@Deprecated
public void writeDouble(long fieldId, double val) {
@@ -890,7 +909,8 @@
/**
* Write a single repeated proto "double" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, double)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedDouble(long fieldId, double val) {
@@ -908,10 +928,11 @@
/**
* Write a list of packed proto "double" type field values.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, double)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedDouble(long fieldId, double[] val) {
+ public void writePackedDouble(long fieldId, @Nullable double[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_DOUBLE);
@@ -934,7 +955,8 @@
/**
* Write a single proto "float" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, float)} instead.
+ * @hide
*/
@Deprecated
public void writeFloat(long fieldId, float val) {
@@ -954,7 +976,8 @@
/**
* Write a single repeated proto "float" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, float)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedFloat(long fieldId, float val) {
@@ -972,10 +995,11 @@
/**
* Write a list of packed proto "float" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, float)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedFloat(long fieldId, float[] val) {
+ public void writePackedFloat(long fieldId, @Nullable float[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FLOAT);
@@ -999,7 +1023,7 @@
/**
* Writes a java int as an usigned varint.
*
- * The unadorned int32 type in protobuf is unfortunate because it
+ * <p>The unadorned int32 type in protobuf is unfortunate because it
* is stored in memory as a signed value, but encodes as unsigned
* varints, which are formally always longs. So here, we encode
* negative values as 64 bits, which will get the sign-extension,
@@ -1017,11 +1041,12 @@
/**
* Write a single proto "int32" type field value.
*
- * Note that these are stored in memory as signed values and written as unsigned
+ * <p>Note that these are stored in memory as signed values and written as unsigned
* varints, which if negative, are 10 bytes long. If you know the data is likely
* to be negative, use "sint32".
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeInt32(long fieldId, int val) {
@@ -1041,11 +1066,12 @@
/**
* Write a single repeated proto "int32" type field value.
*
- * Note that these are stored in memory as signed values and written as unsigned
+ * <p>Note that these are stored in memory as signed values and written as unsigned
* varints, which if negative, are 10 bytes long. If you know the data is likely
* to be negative, use "sint32".
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedInt32(long fieldId, int val) {
@@ -1063,14 +1089,15 @@
/**
* Write a list of packed proto "int32" type field value.
*
- * Note that these are stored in memory as signed values and written as unsigned
+ * <p>Note that these are stored in memory as signed values and written as unsigned
* varints, which if negative, are 10 bytes long. If you know the data is likely
* to be negative, use "sint32".
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedInt32(long fieldId, int[] val) {
+ public void writePackedInt32(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_INT32);
@@ -1099,7 +1126,8 @@
/**
* Write a single proto "int64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeInt64(long fieldId, long val) {
@@ -1119,7 +1147,8 @@
/**
* Write a single repeated proto "int64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedInt64(long fieldId, long val) {
@@ -1137,10 +1166,11 @@
/**
* Write a list of packed proto "int64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedInt64(long fieldId, long[] val) {
+ public void writePackedInt64(long fieldId, @Nullable long[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_INT64);
@@ -1168,7 +1198,8 @@
/**
* Write a single proto "uint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeUInt32(long fieldId, int val) {
@@ -1188,7 +1219,8 @@
/**
* Write a single repeated proto "uint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedUInt32(long fieldId, int val) {
@@ -1206,10 +1238,11 @@
/**
* Write a list of packed proto "uint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedUInt32(long fieldId, int[] val) {
+ public void writePackedUInt32(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_UINT32);
@@ -1237,7 +1270,8 @@
/**
* Write a single proto "uint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeUInt64(long fieldId, long val) {
@@ -1257,7 +1291,8 @@
/**
* Write a single proto "uint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedUInt64(long fieldId, long val) {
@@ -1275,10 +1310,11 @@
/**
* Write a single proto "uint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedUInt64(long fieldId, long[] val) {
+ public void writePackedUInt64(long fieldId, @Nullable long[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_UINT64);
@@ -1306,7 +1342,8 @@
/**
* Write a single proto "sint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeSInt32(long fieldId, int val) {
@@ -1326,7 +1363,8 @@
/**
* Write a single repeated proto "sint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedSInt32(long fieldId, int val) {
@@ -1344,10 +1382,11 @@
/**
* Write a list of packed proto "sint32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedSInt32(long fieldId, int[] val) {
+ public void writePackedSInt32(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SINT32);
@@ -1375,7 +1414,8 @@
/**
* Write a single proto "sint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeSInt64(long fieldId, long val) {
@@ -1395,7 +1435,8 @@
/**
* Write a single repeated proto "sint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedSInt64(long fieldId, long val) {
@@ -1413,10 +1454,11 @@
/**
* Write a list of packed proto "sint64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedSInt64(long fieldId, long[] val) {
+ public void writePackedSInt64(long fieldId, @Nullable long[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SINT64);
@@ -1443,7 +1485,8 @@
/**
* Write a single proto "fixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeFixed32(long fieldId, int val) {
@@ -1463,7 +1506,8 @@
/**
* Write a single repeated proto "fixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedFixed32(long fieldId, int val) {
@@ -1481,10 +1525,11 @@
/**
* Write a list of packed proto "fixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedFixed32(long fieldId, int[] val) {
+ public void writePackedFixed32(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FIXED32);
@@ -1507,7 +1552,8 @@
/**
* Write a single proto "fixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeFixed64(long fieldId, long val) {
@@ -1527,7 +1573,8 @@
/**
* Write a single repeated proto "fixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedFixed64(long fieldId, long val) {
@@ -1545,10 +1592,11 @@
/**
* Write a list of packed proto "fixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedFixed64(long fieldId, long[] val) {
+ public void writePackedFixed64(long fieldId, @Nullable long[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FIXED64);
@@ -1570,7 +1618,8 @@
/**
* Write a single proto "sfixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeSFixed32(long fieldId, int val) {
@@ -1590,7 +1639,8 @@
/**
* Write a single repeated proto "sfixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedSFixed32(long fieldId, int val) {
@@ -1608,10 +1658,11 @@
/**
* Write a list of packed proto "sfixed32" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedSFixed32(long fieldId, int[] val) {
+ public void writePackedSFixed32(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SFIXED32);
@@ -1634,7 +1685,8 @@
/**
* Write a single proto "sfixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeSFixed64(long fieldId, long val) {
@@ -1654,7 +1706,8 @@
/**
* Write a single repeated proto "sfixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedSFixed64(long fieldId, long val) {
@@ -1672,10 +1725,11 @@
/**
* Write a list of packed proto "sfixed64" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, long)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedSFixed64(long fieldId, long[] val) {
+ public void writePackedSFixed64(long fieldId, @Nullable long[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SFIXED64);
@@ -1698,7 +1752,8 @@
/**
* Write a single proto "bool" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, boolean)} instead.
+ * @hide
*/
@Deprecated
public void writeBool(long fieldId, boolean val) {
@@ -1719,7 +1774,8 @@
/**
* Write a single repeated proto "bool" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, boolean)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedBool(long fieldId, boolean val) {
@@ -1737,10 +1793,11 @@
/**
* Write a list of packed proto "bool" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, boolean)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedBool(long fieldId, boolean[] val) {
+ public void writePackedBool(long fieldId, @Nullable boolean[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_BOOL);
@@ -1767,10 +1824,11 @@
/**
* Write a single proto "string" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, String)} instead.
+ * @hide
*/
@Deprecated
- public void writeString(long fieldId, String val) {
+ public void writeString(long fieldId, @Nullable String val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_STRING);
@@ -1786,10 +1844,11 @@
/**
* Write a single repeated proto "string" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, String)} instead.
+ * @hide
*/
@Deprecated
- public void writeRepeatedString(long fieldId, String val) {
+ public void writeRepeatedString(long fieldId, @Nullable String val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_STRING);
@@ -1828,10 +1887,11 @@
/**
* Write a single proto "bytes" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, byte[])} instead.
+ * @hide
*/
@Deprecated
- public void writeBytes(long fieldId, byte[] val) {
+ public void writeBytes(long fieldId, @Nullable byte[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_BYTES);
@@ -1848,10 +1908,11 @@
/**
* Write a single repeated proto "bytes" type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, byte[])} instead.
+ * @hide
*/
@Deprecated
- public void writeRepeatedBytes(long fieldId, byte[] val) {
+ public void writeRepeatedBytes(long fieldId, @Nullable byte[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BYTES);
@@ -1874,7 +1935,8 @@
/**
* Write a single proto enum type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeEnum(long fieldId, int val) {
@@ -1894,7 +1956,8 @@
/**
* Write a single repeated proto enum type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
public void writeRepeatedEnum(long fieldId, int val) {
@@ -1912,10 +1975,11 @@
/**
* Write a list of packed proto enum type field value.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, int)} instead.
+ * @hide
*/
@Deprecated
- public void writePackedEnum(long fieldId, int[] val) {
+ public void writePackedEnum(long fieldId, @Nullable int[] val) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_ENUM);
@@ -1940,7 +2004,8 @@
* Returns a token which should be passed to endObject. Calls to endObject must be
* nested properly.
*
- * @deprecated Use #start() instead.
+ * @deprecated Use {@link #start(long)} instead.
+ * @hide
*/
@Deprecated
public long startObject(long fieldId) {
@@ -1953,7 +2018,8 @@
/**
* End a child object. Pass in the token from the correspoinding startObject call.
*
- * @deprecated Use #end() instead.
+ * @deprecated Use {@link #end(long)} instead.
+ * @hide
*/
@Deprecated
public void endObject(long token) {
@@ -1968,7 +2034,8 @@
* Returns a token which should be passed to endObject. Calls to endObject must be
* nested properly.
*
- * @deprecated Use #start() instead.
+ * @deprecated Use {@link #start(long)} instead.
+ * @hide
*/
@Deprecated
public long startRepeatedObject(long fieldId) {
@@ -1981,7 +2048,8 @@
/**
* End a child object. Pass in the token from the correspoinding startRepeatedObject call.
*
- * @deprecated Use #end() instead.
+ * @deprecated Use {@link #end(long)} instead.
+ * @hide
*/
@Deprecated
public void endRepeatedObject(long token) {
@@ -2064,12 +2132,13 @@
}
/**
- * Write an object that has already been flattend.
+ * Write an object that has already been flattened.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, byte[])} instead.
+ * @hide
*/
@Deprecated
- public void writeObject(long fieldId, byte[] value) {
+ public void writeObject(long fieldId, @Nullable byte[] value) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_MESSAGE);
@@ -2084,12 +2153,13 @@
}
/**
- * Write an object that has already been flattend.
+ * Write an object that has already been flattened.
*
- * @deprecated Use #write instead.
+ * @deprecated Use {@link #write(long, byte[])} instead.
+ * @hide
*/
@Deprecated
- public void writeRepeatedObject(long fieldId, byte[] value) {
+ public void writeRepeatedObject(long fieldId, @Nullable byte[] value) {
assertNotCompacted();
final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_MESSAGE);
@@ -2115,11 +2185,11 @@
}
/**
- * Validates that the fieldId providied is of the type and count from expectedType.
+ * Validates that the fieldId provided is of the type and count from expectedType.
*
- * The type must match exactly to pass this check.
+ * <p>The type must match exactly to pass this check.
*
- * The count must match according to this truth table to pass the check:
+ * <p>The count must match according to this truth table to pass the check:
*
* expectedFlags
* UNKNOWN SINGLE REPEATED PACKED
@@ -2129,7 +2199,7 @@
* REPEATED x false true false
* PACKED x false true true
*
- * @throws IllegalArgumentException if it is not.
+ * @throws {@link IllegalArgumentException} if it is not.
*
* @return The raw ID of that field.
*/
@@ -2201,7 +2271,7 @@
}
/**
- * Write a field tage to the stream.
+ * Write a field tag to the stream.
*/
public void writeTag(int id, int wireType) {
mBuffer.writeRawVarint32((id << FIELD_ID_SHIFT) | wireType);
@@ -2239,10 +2309,10 @@
* Finish the encoding of the data, and return a byte[] with
* the protobuf formatted data.
*
- * After this call, do not call any of the write* functions. The
+ * <p>After this call, do not call any of the write* functions. The
* behavior is undefined.
*/
- public byte[] getBytes() {
+ public @NonNull byte[] getBytes() {
compactIfNecessary();
return mBuffer.getBytes(mBuffer.getReadableSize());
@@ -2289,7 +2359,7 @@
}
/**
- * First compaction pass. Iterate through the data, and fill in the
+ * First compaction pass. Iterate through the data, and fill in the
* nested object sizes so the next pass can compact them.
*/
private int editEncodedSize(int rawSize) {
@@ -2416,10 +2486,10 @@
/**
* Write remaining data to the output stream. If there is no output stream,
* this function does nothing. Any currently open objects (i.e. ones that
- * have not had endObject called for them will not be written). Whether this
+ * have not had {@link #end(long)} called for them will not be written). Whether this
* writes objects that are closed if there are remaining open objects is
* undefined (current implementation does not write it, future ones will).
- * For now, can either call getBytes() or flush(), but not both.
+ * For now, can either call {@link #getBytes()} or {@link #flush()}, but not both.
*/
public void flush() {
if (mStream == null) {
@@ -2457,7 +2527,7 @@
/**
* Dump debugging data about the buffers with the given log tag.
*/
- public void dump(String tag) {
+ public void dump(@NonNull String tag) {
Log.d(tag, mBuffer.getDebugString());
mBuffer.dumpBuffers(tag);
}
diff --git a/core/java/android/util/proto/ProtoStream.java b/core/java/android/util/proto/ProtoStream.java
index 9e2e95a..4969d8a 100644
--- a/core/java/android/util/proto/ProtoStream.java
+++ b/core/java/android/util/proto/ProtoStream.java
@@ -16,28 +16,104 @@
package android.util.proto;
-import android.annotation.TestApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
/**
- * Abstract base class for both protobuf streams.
+ * Base utility class for protobuf streams.
*
- * Contains a set of useful constants and methods used by both
- * ProtoOutputStream and ProtoInputStream
+ * Contains a set of constants and methods used in generated code for
+ * {@link ProtoOutputStream}.
*
* @hide
*/
-@TestApi
-public abstract class ProtoStream {
+public class ProtoStream {
+ /**
+ * Number of bits to shift the field number to form a tag.
+ *
+ * <pre>
+ * // Reading a field number from a tag.
+ * int fieldNumber = tag >>> FIELD_ID_SHIFT;
+ *
+ * // Building a tag from a field number and a wire type.
+ * int tag = (fieldNumber << FIELD_ID_SHIFT) | wireType;
+ * </pre>
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int FIELD_ID_SHIFT = 3;
+
+ /**
+ * Mask to select the wire type from a tag.
+ *
+ * <pre>
+ * // Reading a wire type from a tag.
+ * int wireType = tag & WIRE_TYPE_MASK;
+ *
+ * // Building a tag from a field number and a wire type.
+ * int tag = (fieldNumber << FIELD_ID_SHIFT) | wireType;
+ * </pre>
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_MASK = (1 << FIELD_ID_SHIFT) - 1;
+
+ /**
+ * Mask to select the field id from a tag.
+ * @hide (not used by anything, and not actually useful, because you also want
+ * to shift when you mask the field id).
+ */
public static final int FIELD_ID_MASK = ~WIRE_TYPE_MASK;
+ /**
+ * Varint wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_VARINT = 0;
+
+ /**
+ * Fixed64 wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_FIXED64 = 1;
+
+ /**
+ * Length delimited wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_LENGTH_DELIMITED = 2;
+
+ /**
+ * Start group wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_START_GROUP = 3;
+
+ /**
+ * End group wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_END_GROUP = 4;
+
+ /**
+ * Fixed32 wire type code.
+ *
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final int WIRE_TYPE_FIXED32 = 5;
/**
@@ -51,32 +127,147 @@
*/
public static final long FIELD_TYPE_MASK = 0x0ffL << FIELD_TYPE_SHIFT;
+ /**
+ * Not a real wire type.
+ * @hide
+ */
public static final long FIELD_TYPE_UNKNOWN = 0;
+
+ /*
+ * The FIELD_TYPE_ constants are copied from
+ * external/protobuf/src/google/protobuf/descriptor.h directly, so no
+ * extra mapping needs to be maintained in this case.
+ */
+
/**
- * The types are copied from external/protobuf/src/google/protobuf/descriptor.h directly,
- * so no extra mapping needs to be maintained in this case.
+ * Field type code for double fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, double)
+ * ProtoOutputStream.write(long, double)} method.
*/
public static final long FIELD_TYPE_DOUBLE = 1L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for float fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, float)
+ * ProtoOutputStream.write(long, float)} method.
+ */
public static final long FIELD_TYPE_FLOAT = 2L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for int64 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, long)
+ * ProtoOutputStream.write(long, long)} method.
+ */
public static final long FIELD_TYPE_INT64 = 3L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for uint64 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, long)
+ * ProtoOutputStream.write(long, long)} method.
+ */
public static final long FIELD_TYPE_UINT64 = 4L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for int32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_INT32 = 5L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for fixed64 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, long)
+ * ProtoOutputStream.write(long, long)} method.
+ */
public static final long FIELD_TYPE_FIXED64 = 6L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for fixed32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
+
+ /**
+ * Field type code for fixed32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_FIXED32 = 7L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for bool fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, boolean)
+ * ProtoOutputStream.write(long, boolean)} method.
+ */
public static final long FIELD_TYPE_BOOL = 8L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for string fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, String)
+ * ProtoOutputStream.write(long, String)} method.
+ */
public static final long FIELD_TYPE_STRING = 9L << FIELD_TYPE_SHIFT;
+
// public static final long FIELD_TYPE_GROUP = 10L << FIELD_TYPE_SHIFT; // Deprecated.
+
+ /**
+ * Field type code for message fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#start(long)
+ * ProtoOutputStream.start(long)} method.
+ */
public static final long FIELD_TYPE_MESSAGE = 11L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for bytes fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, byte[])
+ * ProtoOutputStream.write(long, byte[])} method.
+ */
public static final long FIELD_TYPE_BYTES = 12L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for uint32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_UINT32 = 13L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for enum fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_ENUM = 14L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for sfixed32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_SFIXED32 = 15L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for sfixed64 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, long)
+ * ProtoOutputStream.write(long, long)} method.
+ */
public static final long FIELD_TYPE_SFIXED64 = 16L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for sint32 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, int)
+ * ProtoOutputStream.write(long, int)} method.
+ */
public static final long FIELD_TYPE_SINT32 = 17L << FIELD_TYPE_SHIFT;
+
+ /**
+ * Field type code for sint64 fields. Used to build constants in generated
+ * code for use with the {@link ProtoOutputStream#write(long, long)
+ * ProtoOutputStream.write(long, long)} method.
+ */
public static final long FIELD_TYPE_SINT64 = 18L << FIELD_TYPE_SHIFT;
- protected static final String[] FIELD_TYPE_NAMES = new String[]{
+ private static final @NonNull String[] FIELD_TYPE_NAMES = new String[]{
"Double",
"Float",
"Int64",
@@ -100,19 +291,94 @@
//
// FieldId flags for whether the field is single, repeated or packed.
//
+ /**
+ * Bit offset for building a field id to be used with a
+ * <code>{@link ProtoOutputStream}.write(...)</code>.
+ *
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_UNKNOWN
+ * @see #FIELD_COUNT_SINGLE
+ * @see #FIELD_COUNT_REPEATED
+ * @see #FIELD_COUNT_PACKED
+ */
public static final int FIELD_COUNT_SHIFT = 40;
+
+ /**
+ * Bit mask for selecting the field count when reading a field id that
+ * is used with a <code>{@link ProtoOutputStream}.write(...)</code> method.
+ *
+ * @see #FIELD_COUNT_SHIFT
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_UNKNOWN
+ * @see #FIELD_COUNT_SINGLE
+ * @see #FIELD_COUNT_REPEATED
+ * @see #FIELD_COUNT_PACKED
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final long FIELD_COUNT_MASK = 0x0fL << FIELD_COUNT_SHIFT;
+ /**
+ * Unknown field count, encoded into a field id used with a
+ * <code>{@link ProtoOutputStream}.write(...)</code> method.
+ *
+ * @see #FIELD_COUNT_SHIFT
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_SINGLE
+ * @see #FIELD_COUNT_REPEATED
+ * @see #FIELD_COUNT_PACKED
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final long FIELD_COUNT_UNKNOWN = 0;
+
+ /**
+ * Single field count, encoded into a field id used with a
+ * <code>{@link ProtoOutputStream}.write(...)</code> method.
+ *
+ * @see #FIELD_COUNT_SHIFT
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_UNKNOWN
+ * @see #FIELD_COUNT_REPEATED
+ * @see #FIELD_COUNT_PACKED
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final long FIELD_COUNT_SINGLE = 1L << FIELD_COUNT_SHIFT;
+
+ /**
+ * Repeated field count, encoded into a field id used with a
+ * <code>{@link ProtoOutputStream}.write(...)</code> method.
+ *
+ * @see #FIELD_COUNT_SHIFT
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_UNKNOWN
+ * @see #FIELD_COUNT_SINGLE
+ * @see #FIELD_COUNT_PACKED
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final long FIELD_COUNT_REPEATED = 2L << FIELD_COUNT_SHIFT;
+
+ /**
+ * Repeated packed field count, encoded into a field id used with a
+ * <code>{@link ProtoOutputStream}.write(...)</code> method.
+ *
+ * @see #FIELD_COUNT_SHIFT
+ * @see #FIELD_COUNT_MASK
+ * @see #FIELD_COUNT_UNKNOWN
+ * @see #FIELD_COUNT_SINGLE
+ * @see #FIELD_COUNT_REPEATED
+ * @see <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf
+ * Encoding</a>
+ */
public static final long FIELD_COUNT_PACKED = 5L << FIELD_COUNT_SHIFT;
/**
* Get the developer-usable name of a field type.
*/
- public static String getFieldTypeString(long fieldType) {
+ public static @Nullable String getFieldTypeString(long fieldType) {
int index = ((int) ((fieldType & FIELD_TYPE_MASK) >>> FIELD_TYPE_SHIFT)) - 1;
if (index >= 0 && index < FIELD_TYPE_NAMES.length) {
return FIELD_TYPE_NAMES[index];
@@ -124,7 +390,7 @@
/**
* Get the developer-usable name of a field count.
*/
- public static String getFieldCountString(long fieldCount) {
+ public static @Nullable String getFieldCountString(long fieldCount) {
if (fieldCount == FIELD_COUNT_SINGLE) {
return "";
} else if (fieldCount == FIELD_COUNT_REPEATED) {
@@ -139,7 +405,7 @@
/**
* Get the developer-usable name of a wire type.
*/
- public static String getWireTypeString(int wireType) {
+ public static @Nullable String getWireTypeString(int wireType) {
switch (wireType) {
case WIRE_TYPE_VARINT:
return "Varint";
@@ -161,7 +427,7 @@
/**
* Get a debug string for a fieldId.
*/
- public static String getFieldIdString(long fieldId) {
+ public static @NonNull String getFieldIdString(long fieldId) {
final long fieldCount = fieldId & FIELD_COUNT_MASK;
String countString = getFieldCountString(fieldCount);
if (countString == null) {
@@ -218,29 +484,39 @@
/**
* Get the encoded tag size from the token.
+ *
+ * @hide
*/
public static int getTagSizeFromToken(long token) {
return (int) (0x7 & (token >> 61));
}
/**
- * Get whether this is a call to startObject (false) or startRepeatedObject (true).
+ * Get whether the token has the repeated bit set to true or false
+ *
+ * @hide
*/
public static boolean getRepeatedFromToken(long token) {
return (0x1 & (token >> 60)) != 0;
}
/**
- * Get the nesting depth of startObject calls from the token.
+ * Get the nesting depth from the token.
+ *
+ * @hide
*/
public static int getDepthFromToken(long token) {
return (int) (0x01ff & (token >> 51));
}
/**
- * Get the object ID from the token. The object ID is a serial number for the
+ * Get the object ID from the token.
+ *
+ * <p>The object ID is a serial number for the
* startObject calls that have happened on this object. The values are truncated
* to 9 bits, but that is sufficient for error checking.
+ *
+ * @hide
*/
public static int getObjectIdFromToken(long token) {
return (int) (0x07ffff & (token >> 32));
@@ -248,6 +524,8 @@
/**
* Get the location of the offset recorded in the token.
+ *
+ * @hide
*/
public static int getOffsetFromToken(long token) {
return (int) token;
@@ -255,8 +533,11 @@
/**
* Convert the object ID to the ordinal value -- the n-th call to startObject.
- * The object IDs start at -1 and count backwards, so that the value is unlikely
+ *
+ * <p>The object IDs start at -1 and count backwards, so that the value is unlikely
* to alias with an actual size field that had been written.
+ *
+ * @hide
*/
public static int convertObjectIdToOrdinal(int objectId) {
return (-1 & 0x07ffff) - objectId;
@@ -265,7 +546,7 @@
/**
* Return a debugging string of a token.
*/
- public static String token2String(long token) {
+ public static @NonNull String token2String(long token) {
if (token == 0L) {
return "Token(0)";
} else {
@@ -277,4 +558,9 @@
+ ')';
}
}
+
+ /**
+ * @hide
+ */
+ protected ProtoStream() {}
}
diff --git a/core/java/android/util/proto/ProtoUtils.java b/core/java/android/util/proto/ProtoUtils.java
index 03bf590..a71561b 100644
--- a/core/java/android/util/proto/ProtoUtils.java
+++ b/core/java/android/util/proto/ProtoUtils.java
@@ -24,12 +24,12 @@
/**
* This class contains a list of helper functions to write common proto in
* //frameworks/base/core/proto/android/base directory
+ * @hide
*/
public class ProtoUtils {
/**
* Dump AggStats to ProtoOutputStream
- * @hide
*/
public static void toAggStatsProto(ProtoOutputStream proto, long fieldId,
long min, long average, long max) {
@@ -42,7 +42,6 @@
/**
* Dump Duration to ProtoOutputStream
- * @hide
*/
public static void toDuration(ProtoOutputStream proto, long fieldId, long startMs, long endMs) {
final long token = proto.start(fieldId);
@@ -53,7 +52,6 @@
/**
* Helper function to write bit-wise flags to proto as repeated enums
- * @hide
*/
public static void writeBitWiseFlagsToProtoEnum(ProtoOutputStream proto, long fieldId,
int flags, int[] origEnums, int[] protoEnums) {
diff --git a/core/java/android/util/proto/package.html b/core/java/android/util/proto/package.html
index a636bd4..ef1125b 100644
--- a/core/java/android/util/proto/package.html
+++ b/core/java/android/util/proto/package.html
@@ -1,5 +1,5 @@
+<html>
<body>
Provides utility classes to export protocol buffers from the system.
-
-{@hide}
</body>
+</html>
\ No newline at end of file
diff --git a/core/java/android/view/AccessibilityIterators.java b/core/java/android/view/AccessibilityIterators.java
index 5f9bf39..bee04f4 100644
--- a/core/java/android/view/AccessibilityIterators.java
+++ b/core/java/android/view/AccessibilityIterators.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Configuration;
import java.text.BreakIterator;
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index 6b200e1..d9f9d03 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -19,10 +19,9 @@
import android.annotation.StringRes;
import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
/**
* Represents a contextual mode of the user interface. Action modes can be used to provide
* alternative interaction modes and replace parts of the normal UI until finished.
diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java
index cd7e67e..e1be0fe 100644
--- a/core/java/android/view/ActionProvider.java
+++ b/core/java/android/view/ActionProvider.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.Log;
diff --git a/core/java/android/view/AppTransitionAnimationSpec.java b/core/java/android/view/AppTransitionAnimationSpec.java
index 4c0ed52..330061f 100644
--- a/core/java/android/view/AppTransitionAnimationSpec.java
+++ b/core/java/android/view/AppTransitionAnimationSpec.java
@@ -1,6 +1,6 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.os.Parcel;
diff --git a/core/java/android/view/BatchedInputEventReceiver.java b/core/java/android/view/BatchedInputEventReceiver.java
index 61ccac9..95b2c70 100644
--- a/core/java/android/view/BatchedInputEventReceiver.java
+++ b/core/java/android/view/BatchedInputEventReceiver.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
/**
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 28eb79a..5b4ff52 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -16,12 +16,11 @@
package android.view;
-import static android.view.DisplayEventReceiver.CONFIG_CHANGED_EVENT_SUPPRESS;
import static android.view.DisplayEventReceiver.VSYNC_SOURCE_APP;
import static android.view.DisplayEventReceiver.VSYNC_SOURCE_SURFACE_FLINGER;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.FrameInfo;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Build;
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index 696e048..876331b 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -18,7 +18,7 @@
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.AssetManager;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index b3d98b8..7a818ce 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -22,8 +22,8 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java
index da4d92fa..834dd7b 100644
--- a/core/java/android/view/DisplayAdjustments.java
+++ b/core/java/android/view/DisplayAdjustments.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 91acc46..eaf297c 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 2efebf6..f3b2800 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -23,7 +23,7 @@
import static android.view.DisplayInfoProto.NAME;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 8e6e99a..6035cbe 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.BaseRecordingCanvas;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index 2a43bcc..35af0f2 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ClipDescription;
import android.os.Parcel;
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index dcdef3e..de4112c 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -17,7 +17,7 @@
package android.view;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
index 0f38e84..e4197ab 100644
--- a/core/java/android/view/FrameMetricsObserver.java
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -17,7 +17,7 @@
package android.view;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
import android.os.MessageQueue;
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index 8fbbcf4..0fdbc9c 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -23,7 +23,7 @@
import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index 3286bd6..a728327 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -15,7 +15,7 @@
*/
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RecordingCanvas;
diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java
index ecb727c..67c8b15 100644
--- a/core/java/android/view/InputChannel.java
+++ b/core/java/android/view/InputChannel.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index e723f91..360dedd 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -18,7 +18,7 @@
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
diff --git a/core/java/android/view/InputEvent.java b/core/java/android/view/InputEvent.java
index 4b88a6a..5f9c480 100644
--- a/core/java/android/view/InputEvent.java
+++ b/core/java/android/view/InputEvent.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/InputEventConsistencyVerifier.java b/core/java/android/view/InputEventConsistencyVerifier.java
index e4b1a8d..c0a3cec 100644
--- a/core/java/android/view/InputEventConsistencyVerifier.java
+++ b/core/java/android/view/InputEventConsistencyVerifier.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.util.Log;
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 7260a65..cab8bc5 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
diff --git a/core/java/android/view/InputEventSender.java b/core/java/android/view/InputEventSender.java
index c5f4c23..86a309e 100644
--- a/core/java/android/view/InputEventSender.java
+++ b/core/java/android/view/InputEventSender.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
diff --git a/core/java/android/view/InputFilter.java b/core/java/android/view/InputFilter.java
index 3aaf31e..36d5586 100644
--- a/core/java/android/view/InputFilter.java
+++ b/core/java/android/view/InputFilter.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
diff --git a/core/java/android/view/InputQueue.java b/core/java/android/view/InputQueue.java
index 69ebc46..74ce6ac 100644
--- a/core/java/android/view/InputQueue.java
+++ b/core/java/android/view/InputQueue.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.LongSparseArray;
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index bd03348..90e0f3f 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.input.InputManager;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 60db6a5..c638717 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 1fc7f0e..bf646c7 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
@@ -31,10 +31,7 @@
import android.os.Build;
import android.os.Handler;
import android.os.Message;
-import android.os.SystemProperties;
import android.os.Trace;
-import android.provider.DeviceConfig;
-import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 833e78f..70873d7 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -22,7 +22,7 @@
import android.annotation.IntDef;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Matrix;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index b2f3f5e..232e0f6 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -17,9 +17,9 @@
package android.view;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppOpsManager;
import android.app.Notification;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index dfe34c8..18d0d7b 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -17,8 +17,8 @@
package android.view;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
diff --git a/core/java/android/view/RemoteAnimationAdapter.java b/core/java/android/view/RemoteAnimationAdapter.java
index c686440..166d3ba 100644
--- a/core/java/android/view/RemoteAnimationAdapter.java
+++ b/core/java/android/view/RemoteAnimationAdapter.java
@@ -16,8 +16,8 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityOptions;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
index da599ef..c9bd92a 100644
--- a/core/java/android/view/RemoteAnimationDefinition.java
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -19,9 +19,9 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.ActivityType;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index ae3e1d0..2249966 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -30,8 +30,8 @@
import static android.view.RemoteAnimationTargetProto.WINDOW_CONFIGURATION;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
import android.app.WindowConfiguration;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Parcel;
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 93f52a0..06cb519 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -19,7 +19,7 @@
import android.animation.Animator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
import android.graphics.RecordingCanvas;
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 1d72151..346f76c 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 17f07b5..3a6c8dd 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas;
import android.graphics.ColorSpace;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 2313b13..2c48af0 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -32,7 +32,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java
index 361ac93..0f851c1 100644
--- a/core/java/android/view/SurfaceSession.java
+++ b/core/java/android/view/SurfaceSession.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An instance of this class represents a connection to the surface
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index d11548d..ec2ab6a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -20,7 +20,7 @@
import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER;
import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.CompatibilityInfo.Translator;
import android.graphics.BlendMode;
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 0175ba2..2062bb0 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -17,7 +17,7 @@
package android.view;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
diff --git a/core/java/android/view/TouchDelegate.java b/core/java/android/view/TouchDelegate.java
index 2ea95e9..de0f9e5 100644
--- a/core/java/android/view/TouchDelegate.java
+++ b/core/java/android/view/TouchDelegate.java
@@ -17,7 +17,7 @@
package android.view;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.ArrayMap;
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 7154f2b..a56633e 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Pools.SynchronizedPool;
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9d2040c..3313537 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -43,7 +43,7 @@
import android.annotation.StyleRes;
import android.annotation.TestApi;
import android.annotation.UiThread;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.AutofillOptions;
import android.content.ClipData;
import android.content.Context;
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 9e914d4..774a2de 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -18,8 +18,8 @@
import android.annotation.FloatRange;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 8a1fd62..dda7b26 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -870,6 +870,94 @@
return null;
}
+ private static class StreamingPictureCallbackHandler implements AutoCloseable,
+ HardwareRenderer.PictureCapturedCallback, Runnable {
+ private final HardwareRenderer mRenderer;
+ private final Callable<OutputStream> mCallback;
+ private final Executor mExecutor;
+ private final ReentrantLock mLock = new ReentrantLock(false);
+ private final ArrayDeque<byte[]> mQueue = new ArrayDeque<>(3);
+ private final ByteArrayOutputStream mByteStream = new ByteArrayOutputStream();
+ private boolean mStopListening;
+ private Thread mRenderThread;
+
+ private StreamingPictureCallbackHandler(HardwareRenderer renderer,
+ Callable<OutputStream> callback, Executor executor) {
+ mRenderer = renderer;
+ mCallback = callback;
+ mExecutor = executor;
+ mRenderer.setPictureCaptureCallback(this);
+ }
+
+ @Override
+ public void close() {
+ mLock.lock();
+ mStopListening = true;
+ mLock.unlock();
+ mRenderer.setPictureCaptureCallback(null);
+ }
+
+ @Override
+ public void onPictureCaptured(Picture picture) {
+ mLock.lock();
+ if (mStopListening) {
+ mLock.unlock();
+ mRenderer.setPictureCaptureCallback(null);
+ return;
+ }
+ if (mRenderThread == null) {
+ mRenderThread = Thread.currentThread();
+ }
+ boolean needsInvoke = true;
+ if (mQueue.size() == 3) {
+ mQueue.removeLast();
+ needsInvoke = false;
+ }
+ picture.writeToStream(mByteStream);
+ mQueue.add(mByteStream.toByteArray());
+ mByteStream.reset();
+ mLock.unlock();
+
+ if (needsInvoke) {
+ mExecutor.execute(this);
+ }
+ }
+
+ @Override
+ public void run() {
+ mLock.lock();
+ final byte[] picture = mQueue.poll();
+ final boolean isStopped = mStopListening;
+ mLock.unlock();
+ if (Thread.currentThread() == mRenderThread) {
+ close();
+ throw new IllegalStateException(
+ "ViewDebug#startRenderingCommandsCapture must be given an executor that "
+ + "invokes asynchronously");
+ }
+ if (isStopped) {
+ return;
+ }
+ OutputStream stream = null;
+ try {
+ stream = mCallback.call();
+ } catch (Exception ex) {
+ Log.w("ViewDebug", "Aborting rendering commands capture "
+ + "because callback threw exception", ex);
+ }
+ if (stream != null) {
+ try {
+ stream.write(picture);
+ } catch (IOException ex) {
+ Log.w("ViewDebug", "Aborting rendering commands capture "
+ + "due to IOException writing to output stream", ex);
+ }
+ } else {
+ close();
+ }
+ }
+ }
+
/**
* Begins capturing the entire rendering commands for the view tree referenced by the given
* view. The view passed may be any View in the tree as long as it is attached. That is,
@@ -915,18 +1003,7 @@
}
final HardwareRenderer renderer = attachInfo.mThreadedRenderer;
if (renderer != null) {
- return new PictureCallbackHandler(renderer, (picture -> {
- try {
- OutputStream stream = callback.call();
- if (stream != null) {
- picture.writeToStream(stream);
- return true;
- }
- } catch (Exception ex) {
- // fall through
- }
- return false;
- }), executor);
+ return new StreamingPictureCallbackHandler(renderer, callback, executor);
}
return null;
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 937bd1b..6125aad 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -24,7 +24,7 @@
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.annotation.UiThread;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/view/ViewHierarchyEncoder.java b/core/java/android/view/ViewHierarchyEncoder.java
index d5716bf..b0e0524 100644
--- a/core/java/android/view/ViewHierarchyEncoder.java
+++ b/core/java/android/view/ViewHierarchyEncoder.java
@@ -2,7 +2,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index e23c687..7830c57 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -17,7 +17,7 @@
import android.animation.LayoutTransition;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 57a01a3..1ab3d3a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -32,10 +32,10 @@
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ResourcesManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index c72baca..d7b0afc 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.Region;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 73e0e4b..cdafa47 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -26,8 +26,8 @@
import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.WindowConfiguration;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
diff --git a/core/java/android/view/WindowAnimationFrameStats.java b/core/java/android/view/WindowAnimationFrameStats.java
index 399dfba..dfc4f0c 100644
--- a/core/java/android/view/WindowAnimationFrameStats.java
+++ b/core/java/android/view/WindowAnimationFrameStats.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/WindowContentFrameStats.java b/core/java/android/view/WindowContentFrameStats.java
index 9fa5a00..217197c 100644
--- a/core/java/android/view/WindowContentFrameStats.java
+++ b/core/java/android/view/WindowContentFrameStats.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index bcc6a55..87bc534 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -34,7 +34,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.graphics.Insets;
import android.graphics.Rect;
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 7433b6c..d9d9278 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -50,9 +50,9 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
import android.app.Presentation;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 379acbe..a930abe 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -18,8 +18,8 @@
import android.animation.ValueAnimator;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.pm.ApplicationInfo;
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index c349443..cdeeaa4 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -17,7 +17,7 @@
package android.view;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Region;
import android.os.Bundle;
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 2ac44d2..2ba9f94 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -17,7 +17,7 @@
package android.view.accessibility;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 4db6f4f..723da77 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -17,7 +17,7 @@
package android.view.accessibility;
import android.accessibilityservice.IAccessibilityServiceConnection;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 2e9d881..747bd70 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -29,7 +29,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 3b310fc..8e61a5e 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -26,7 +26,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index b382a18..37c3a13 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -19,7 +19,7 @@
import static com.android.internal.util.CollectionUtils.isEmpty;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcelable;
import android.view.View;
diff --git a/core/java/android/view/accessibility/CaptioningManager.java b/core/java/android/view/accessibility/CaptioningManager.java
index c42e9fe..3d68692 100644
--- a/core/java/android/view/accessibility/CaptioningManager.java
+++ b/core/java/android/view/accessibility/CaptioningManager.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 3b60aee..43dcafc 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -19,7 +19,7 @@
import android.annotation.AnimRes;
import android.annotation.ColorInt;
import android.annotation.InterpolatorRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.RectF;
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index c877b9c..075b0ab 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -19,7 +19,7 @@
import android.annotation.AnimRes;
import android.annotation.InterpolatorRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java
index 58da04d..cfc6e39 100644
--- a/core/java/android/view/animation/Transformation.java
+++ b/core/java/android/view/animation/Transformation.java
@@ -17,7 +17,7 @@
package android.view.animation;
import android.annotation.FloatRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Matrix;
import android.graphics.Rect;
diff --git a/core/java/android/view/animation/TranslateAnimation.java b/core/java/android/view/animation/TranslateAnimation.java
index 6c040d4..ec55a02 100644
--- a/core/java/android/view/animation/TranslateAnimation.java
+++ b/core/java/android/view/animation/TranslateAnimation.java
@@ -16,7 +16,7 @@
package android.view.animation;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
diff --git a/core/java/android/view/animation/TranslateYAnimation.java b/core/java/android/view/animation/TranslateYAnimation.java
index a6e0ccb..1a1dfbf 100644
--- a/core/java/android/view/animation/TranslateYAnimation.java
+++ b/core/java/android/view/animation/TranslateYAnimation.java
@@ -16,7 +16,7 @@
package android.view.animation;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Matrix;
/**
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index fe07fee..34005ac 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -17,7 +17,7 @@
package android.view.inputmethod;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 032af1c..d395f52 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -26,9 +26,9 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -2830,7 +2830,7 @@
}
/**
- * This is kept due to {@link android.annotation.UnsupportedAppUsage}.
+ * This is kept due to {@link android.compat.annotation.UnsupportedAppUsage}.
*
* <p>TODO(Bug 113914148): Check if we can remove this. We have accidentally exposed
* WindowManagerInternal#getInputMethodWindowVisibleHeight to app developers and some of them
diff --git a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
index 8dd0dcd..50e95c8 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
@@ -16,7 +16,7 @@
package android.view.inputmethod;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.util.Slog;
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index 95ca9de..526ac6f 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -19,8 +19,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.database.ContentObserver;
import android.os.ServiceManager;
diff --git a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
index b530ddf..05d12ce 100644
--- a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
+++ b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.metrics.LogMaker;
import android.util.Log;
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index f553ca5..afddaa2 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -16,7 +16,7 @@
package android.view.textservice;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 9ff64d9..acb35d6 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 7e06719..fafe813 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -17,7 +17,7 @@
package android.webkit;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.File;
import java.io.IOException;
diff --git a/core/java/android/webkit/ConsoleMessage.java b/core/java/android/webkit/ConsoleMessage.java
index e548497..5474557 100644
--- a/core/java/android/webkit/ConsoleMessage.java
+++ b/core/java/android/webkit/ConsoleMessage.java
@@ -16,7 +16,7 @@
package android.webkit;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
/**
diff --git a/core/java/android/webkit/JsResult.java b/core/java/android/webkit/JsResult.java
index 5bf6aab..448db58e 100644
--- a/core/java/android/webkit/JsResult.java
+++ b/core/java/android/webkit/JsResult.java
@@ -17,7 +17,7 @@
package android.webkit;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An instance of this class is passed as a parameter in various {@link WebChromeClient} action
diff --git a/core/java/android/webkit/PluginData.java b/core/java/android/webkit/PluginData.java
index 8aeeb1c..c9a1960 100644
--- a/core/java/android/webkit/PluginData.java
+++ b/core/java/android/webkit/PluginData.java
@@ -16,7 +16,8 @@
package android.webkit;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.InputStream;
import java.util.Map;
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
index 5d704cb0..844b156 100644
--- a/core/java/android/webkit/URLUtil.java
+++ b/core/java/android/webkit/URLUtil.java
@@ -17,7 +17,7 @@
package android.webkit;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.ParseException;
import android.net.Uri;
import android.net.WebAddress;
diff --git a/core/java/android/webkit/UrlInterceptHandler.java b/core/java/android/webkit/UrlInterceptHandler.java
index f23aae6..a48e107 100644
--- a/core/java/android/webkit/UrlInterceptHandler.java
+++ b/core/java/android/webkit/UrlInterceptHandler.java
@@ -17,9 +17,8 @@
package android.webkit;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.webkit.CacheManager.CacheResult;
-import android.webkit.PluginData;
import java.util.Map;
diff --git a/core/java/android/webkit/UrlInterceptRegistry.java b/core/java/android/webkit/UrlInterceptRegistry.java
index eeb28d7..c9dee00 100644
--- a/core/java/android/webkit/UrlInterceptRegistry.java
+++ b/core/java/android/webkit/UrlInterceptRegistry.java
@@ -17,10 +17,8 @@
package android.webkit;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.webkit.CacheManager.CacheResult;
-import android.webkit.PluginData;
-import android.webkit.UrlInterceptHandler;
import java.util.Iterator;
import java.util.LinkedList;
diff --git a/core/java/android/webkit/WebResourceResponse.java b/core/java/android/webkit/WebResourceResponse.java
index 7c8f33e..219523b 100644
--- a/core/java/android/webkit/WebResourceResponse.java
+++ b/core/java/android/webkit/WebResourceResponse.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.InputStream;
import java.io.StringBufferInputStream;
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 7282008..8a5b64d 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import java.lang.annotation.ElementType;
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
index e44d6eb..7046c51 100644
--- a/core/java/android/webkit/WebSyncManager.java
+++ b/core/java/android/webkit/WebSyncManager.java
@@ -16,7 +16,7 @@
package android.webkit;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 721ac2d..271d5be 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -21,8 +21,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index f5657df..df86926 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -19,10 +19,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.Application;
import android.app.ResourcesManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 678a252..941af6e 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -17,10 +17,10 @@
package android.webkit;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.Application;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java
index 7e00cde..6629fdc4 100644
--- a/core/java/android/webkit/WebViewProviderInfo.java
+++ b/core/java/android/webkit/WebViewProviderInfo.java
@@ -17,7 +17,7 @@
package android.webkit;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.Signature;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/webkit/WebViewProviderResponse.java b/core/java/android/webkit/WebViewProviderResponse.java
index 5622abe..b58cc4bb 100644
--- a/core/java/android/webkit/WebViewProviderResponse.java
+++ b/core/java/android/webkit/WebViewProviderResponse.java
@@ -16,7 +16,7 @@
package android.webkit;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageInfo;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/webkit/WebViewUpdateService.java b/core/java/android/webkit/WebViewUpdateService.java
index 12d3221..9152b43 100644
--- a/core/java/android/webkit/WebViewUpdateService.java
+++ b/core/java/android/webkit/WebViewUpdateService.java
@@ -17,7 +17,7 @@
package android.webkit;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.RemoteException;
/**
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 85e9e49..2d99eab 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -20,7 +20,7 @@
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index bbcba2e..11a6acf 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index cfb93ec..aa3590a 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -22,7 +22,7 @@
import android.animation.PropertyValuesHolder;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 7e58622..3a74356 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index f5bf759..d87bdf4 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -16,8 +16,8 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 89ea074..aa18d57 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -17,7 +17,7 @@
package android.widget;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index c55f7d6..5265840 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.database.DataSetObserver;
import android.os.Build;
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 67a70b4..d165bd0 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index 2bf1ba5..6c38c8b 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -21,7 +21,7 @@
import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 8785251..8d9ae58 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -18,7 +18,7 @@
import android.annotation.DrawableRes;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/BaseAdapter.java b/core/java/android/widget/BaseAdapter.java
index 7b9365b..27cf9a6 100644
--- a/core/java/android/widget/BaseAdapter.java
+++ b/core/java/android/widget/BaseAdapter.java
@@ -17,7 +17,7 @@
package android.widget;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.view.View;
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index b552aa6..4b2f738 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -23,8 +23,8 @@
import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 8b70f41..422d2d3 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -19,7 +19,7 @@
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 2674ca4..52e983e 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -19,7 +19,7 @@
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/CursorAdapter.java b/core/java/android/widget/CursorAdapter.java
index e250f63..600a34c 100644
--- a/core/java/android/widget/CursorAdapter.java
+++ b/core/java/android/widget/CursorAdapter.java
@@ -16,8 +16,8 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 0c593be..c1c1a6e 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -19,8 +19,8 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
index 5f15110..096e6ea 100644
--- a/core/java/android/widget/DatePickerSpinnerDelegate.java
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java
index 2864ad0..20a53c0 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -21,8 +21,8 @@
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.YEAR_IN_MILLIS;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index fa0af78..32f3acd 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -18,7 +18,7 @@
import android.annotation.ColorInt;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.BlendMode;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index cac75cfd..b6338f7 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -21,10 +21,10 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.app.RemoteAction;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ClipData.Item;
import android.content.Context;
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index cae91fc..bdfb550 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -18,7 +18,7 @@
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 2c09185..0c0b349 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -23,7 +23,7 @@
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/Filter.java b/core/java/android/widget/Filter.java
index 16f4ee2..06e6a5a 100644
--- a/core/java/android/widget/Filter.java
+++ b/core/java/android/widget/Filter.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 69da911..92e9a96 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 64192aa..8c0061d 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -17,8 +17,8 @@
package android.widget;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 8cda47d..f132197 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -31,7 +31,7 @@
import static java.lang.Math.min;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 4e39a55..4a5e95e 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/HeaderViewListAdapter.java b/core/java/android/widget/HeaderViewListAdapter.java
index 10d50b8..eda7580 100644
--- a/core/java/android/widget/HeaderViewListAdapter.java
+++ b/core/java/android/widget/HeaderViewListAdapter.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 5921feb..f5f64c0 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -18,7 +18,7 @@
import android.annotation.ColorInt;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index d62b979..c2077384 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.ColorStateList;
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index a83e826..a796ba5 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 16b903d..001eb27 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 2f44d6e..7260344 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -19,7 +19,7 @@
import android.annotation.IdRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 65925b4..9c9baf3 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.PixelFormat;
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index b385534..b2fedf7 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -23,8 +23,8 @@
import android.annotation.IntRange;
import android.annotation.Px;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index e7a96be..1c33d80 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.hardware.SensorManager;
import android.util.Log;
diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java
index b0c0c12..0ce9646 100644
--- a/core/java/android/widget/PopupMenu.java
+++ b/core/java/android/widget/PopupMenu.java
@@ -18,7 +18,7 @@
import android.annotation.MenuRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.view.Gravity;
import android.view.Menu;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 3779779..bf696f5 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -18,13 +18,12 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.WindowManager.LayoutParams
- .PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 2e95743..9cbb035 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -21,7 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Px;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index c1a217c..ea39f6d 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index c62c16c..69c3cda 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -18,7 +18,7 @@
import android.annotation.IdRes;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java
index 3cf3d91..f946fe6 100644
--- a/core/java/android/widget/RatingBar.java
+++ b/core/java/android/widget/RatingBar.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.shapes.RectShape;
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index b9da307..521922d 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -19,7 +19,7 @@
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.ResourceId;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 86cec5e..82e03e2 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -22,7 +22,6 @@
import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.ActivityThread;
@@ -30,6 +29,7 @@
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.appwidget.AppWidgetHostView;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index efc5eb3..e58f08a 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -19,11 +19,11 @@
import static android.widget.RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID;
import static android.widget.RemoteViews.EXTRA_REMOTEADAPTER_ON_LIGHT_BACKGROUND;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
import android.app.IServiceConnection;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java
index a5d3e45..80e17b5 100644
--- a/core/java/android/widget/ScrollBarDrawable.java
+++ b/core/java/android/widget/ScrollBarDrawable.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 51b0950..6c2e7a9 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -18,7 +18,7 @@
import android.annotation.ColorInt;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java
index 229eaf0..6ed5b7e 100644
--- a/core/java/android/widget/Scroller.java
+++ b/core/java/android/widget/Scroller.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.hardware.SensorManager;
import android.os.Build;
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 89d9e97..15959c2 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -19,10 +19,10 @@
import static android.widget.SuggestionsAdapter.getColumnString;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.app.SearchableInfo;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
index e8cf1e8..5676881 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityNodeInfo;
diff --git a/core/java/android/widget/SimpleAdapter.java b/core/java/android/widget/SimpleAdapter.java
index 15e1ffa..404b817 100644
--- a/core/java/android/widget/SimpleAdapter.java
+++ b/core/java/android/widget/SimpleAdapter.java
@@ -18,7 +18,7 @@
import android.annotation.IdRes;
import android.annotation.LayoutRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.net.Uri;
diff --git a/core/java/android/widget/SimpleCursorAdapter.java b/core/java/android/widget/SimpleCursorAdapter.java
index 77fe5d1..6277d5b 100644
--- a/core/java/android/widget/SimpleCursorAdapter.java
+++ b/core/java/android/widget/SimpleCursorAdapter.java
@@ -16,7 +16,7 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java
index 2ab2b24..9a4cfa1 100644
--- a/core/java/android/widget/SlidingDrawer.java
+++ b/core/java/android/widget/SlidingDrawer.java
@@ -17,7 +17,7 @@
package android.widget;
import android.R;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 92fcea3..46fc09f 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -19,9 +19,9 @@
import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
import android.app.AlertDialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index d57b3bc..f1f3939 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -21,7 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 481704c..fd8dbf5 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.LocalActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 4c67b08..945cef3 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -18,7 +18,7 @@
import android.annotation.DrawableRes;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index b7dd88b..88a6762 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -21,8 +21,8 @@
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0918c5f..6f697cd 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -36,11 +36,11 @@
import android.annotation.Size;
import android.annotation.StringRes;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.assist.AssistStructure;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ClipboardManager;
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 8a5d531..51b1847 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -20,8 +20,8 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.icu.util.Calendar;
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index d037337..e6dcd9e 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -20,9 +20,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
import android.app.INotificationManager;
import android.app.ITransientNotification;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index a21fb41..ea3f06b 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -24,8 +24,8 @@
import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActionBar;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 40b0f13..36dafd5 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -17,8 +17,8 @@
package android.widget;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlertDialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java
index 80ea363..909404b 100644
--- a/core/java/android/widget/ViewAnimator.java
+++ b/core/java/android/widget/ViewAnimator.java
@@ -18,7 +18,7 @@
import android.annotation.AnimRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
index b962298..2df9a78 100644
--- a/core/java/android/widget/ViewFlipper.java
+++ b/core/java/android/widget/ViewFlipper.java
@@ -17,7 +17,7 @@
package android.widget;
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java
index 7a5b7e8..f435533 100644
--- a/core/java/android/widget/ZoomControls.java
+++ b/core/java/android/widget/ZoomControls.java
@@ -16,8 +16,8 @@
package android.widget;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
diff --git a/core/java/com/android/ims/internal/uce/common/CapInfo.java b/core/java/com/android/ims/internal/uce/common/CapInfo.java
index a9847ba..2bb3f1f 100644
--- a/core/java/com/android/ims/internal/uce/common/CapInfo.java
+++ b/core/java/com/android/ims/internal/uce/common/CapInfo.java
@@ -16,10 +16,9 @@
package com.android.ims.internal.uce.common;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
/** Class for capability discovery information.
* @hide */
@@ -65,6 +64,20 @@
private boolean mRcsIpVideoCallSupported = false;
/** RCS IP Video call support . */
private boolean mRcsIpVideoOnlyCallSupported = false;
+ /** IP Geo location Push using SMS. */
+ private boolean mGeoSmsSupported = false;
+ /** RCS call composer support. */
+ private boolean mCallComposerSupported = false;
+ /** RCS post-call support. */
+ private boolean mPostCallSupported = false;
+ /** Shared map support. */
+ private boolean mSharedMapSupported = false;
+ /** Shared Sketch supported. */
+ private boolean mSharedSketchSupported = false;
+ /** Chatbot communication support. */
+ private boolean mChatbotSupported = false;
+ /** Chatbot role support. */
+ private boolean mChatbotRoleSupported = false;
/** List of supported extensions. */
private String[] mExts = new String[10];
/** Time used to compute when to query again. */
@@ -387,6 +400,104 @@
this.mRcsIpVideoOnlyCallSupported = rcsIpVideoOnlyCallSupported;
}
+ /**
+ * Checks whether Geo Push via SMS is supported.
+ */
+ public boolean isGeoSmsSupported() {
+ return mGeoSmsSupported;
+ }
+
+ /**
+ * Sets Geolocation Push via SMS as supported or not supported.
+ */
+ public void setGeoSmsSupported(boolean geoSmsSupported) {
+ this.mGeoSmsSupported = geoSmsSupported;
+ }
+
+ /**
+ * Checks whether RCS call composer is supported.
+ */
+ public boolean isCallComposerSupported() {
+ return mCallComposerSupported;
+ }
+
+ /**
+ * Sets call composer as supported or not supported.
+ */
+ public void setCallComposerSupported(boolean callComposerSupported) {
+ this.mCallComposerSupported = callComposerSupported;
+ }
+
+ /**
+ * Checks whether post call is supported.
+ */
+ public boolean isPostCallSupported(){
+ return mPostCallSupported;
+ }
+
+ /**
+ * Sets post call as supported or not supported.
+ */
+ public void setPostCallSupported(boolean postCallSupported) {
+ this.mPostCallSupported = postCallSupported;
+ }
+
+ /**
+ * Checks whether shared map is supported.
+ */
+ public boolean isSharedMapSupported() {
+ return mSharedMapSupported;
+ }
+
+ /**
+ * Sets shared map as supported or not supported.
+ */
+ public void setSharedMapSupported(boolean sharedMapSupported) {
+ this.mSharedMapSupported = sharedMapSupported;
+ }
+
+ /**
+ * Checks whether shared sketch is supported.
+ */
+ public boolean isSharedSketchSupported() {
+ return mSharedSketchSupported;
+ }
+
+ /**
+ * Sets shared sketch as supported or not supported.
+ */
+ public void setSharedSketchSupported(boolean sharedSketchSupported) {
+ this.mSharedSketchSupported = sharedSketchSupported;
+ }
+
+ /**
+ * Checks whether chatbot communication is supported.
+ */
+ public boolean isChatbotSupported() {
+ return mChatbotSupported;
+ }
+
+ /**
+ * Sets chatbot communication as supported or not supported.
+ */
+ public void setChatbotSupported(boolean chatbotSupported) {
+ this.mChatbotSupported = chatbotSupported;
+ }
+
+ /**
+ * Checks whether chatbot role is supported.
+ */
+ public boolean isChatbotRoleSupported() {
+ return mChatbotRoleSupported;
+ }
+
+ /**
+ * Sets chatbot role as supported or not supported.
+ */
+ public void setChatbotRoleSupported(boolean chatbotRoleSupported) {
+ this.mChatbotRoleSupported = chatbotRoleSupported;
+ }
+
/** Gets the list of supported extensions. */
public String[] getExts() {
return mExts;
@@ -435,6 +546,13 @@
dest.writeInt(mGeoPushSupported ? 1 : 0);
dest.writeInt(mSmSupported ? 1 : 0);
dest.writeInt(mFullSnFGroupChatSupported ? 1 : 0);
+ dest.writeInt(mGeoSmsSupported ? 1 : 0);
+ dest.writeInt(mCallComposerSupported ? 1 : 0);
+ dest.writeInt(mPostCallSupported ? 1 : 0);
+ dest.writeInt(mSharedMapSupported ? 1 : 0);
+ dest.writeInt(mSharedSketchSupported ? 1 : 0);
+ dest.writeInt(mChatbotSupported ? 1 : 0);
+ dest.writeInt(mChatbotRoleSupported ? 1 : 0);
dest.writeInt(mRcsIpVoiceCallSupported ? 1 : 0);
dest.writeInt(mRcsIpVideoCallSupported ? 1 : 0);
@@ -477,6 +595,13 @@
mGeoPushSupported = (source.readInt() == 0) ? false : true;
mSmSupported = (source.readInt() == 0) ? false : true;
mFullSnFGroupChatSupported = (source.readInt() == 0) ? false : true;
+ mGeoSmsSupported = (source.readInt() == 0) ? false : true;
+ mCallComposerSupported = (source.readInt() == 0) ? false : true;
+ mPostCallSupported = (source.readInt() == 0) ? false : true;
+ mSharedMapSupported = (source.readInt() == 0) ? false : true;
+ mSharedSketchSupported = (source.readInt() == 0) ? false : true;
+ mChatbotSupported = (source.readInt() == 0) ? false : true;
+ mChatbotRoleSupported = (source.readInt() == 0) ? false : true;
mRcsIpVoiceCallSupported = (source.readInt() == 0) ? false : true;
mRcsIpVideoCallSupported = (source.readInt() == 0) ? false : true;
diff --git a/core/java/com/android/ims/internal/uce/common/StatusCode.java b/core/java/com/android/ims/internal/uce/common/StatusCode.java
index 7250eee..7f69493 100644
--- a/core/java/com/android/ims/internal/uce/common/StatusCode.java
+++ b/core/java/com/android/ims/internal/uce/common/StatusCode.java
@@ -16,10 +16,9 @@
package com.android.ims.internal.uce.common;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
/** Class for UCE status codes.
diff --git a/core/java/com/android/ims/internal/uce/common/UceLong.java b/core/java/com/android/ims/internal/uce/common/UceLong.java
index 7207899..bf51447 100644
--- a/core/java/com/android/ims/internal/uce/common/UceLong.java
+++ b/core/java/com/android/ims/internal/uce/common/UceLong.java
@@ -16,10 +16,9 @@
package com.android.ims.internal.uce.common;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
/** Simple object wrapper for a long type.
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java b/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
index bcb9f2d..1da5a24 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
@@ -15,11 +15,11 @@
*/
package com.android.ims.internal.uce.options;
-import android.annotation.UnsupportedAppUsage;
-import com.android.ims.internal.uce.common.CapInfo;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
+
+import com.android.ims.internal.uce.common.CapInfo;
/** @hide */
public class OptionsCapInfo implements Parcelable {
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsCmdId.java b/core/java/com/android/ims/internal/uce/options/OptionsCmdId.java
index 14c64ac..401ca2f 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsCmdId.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsCmdId.java
@@ -17,7 +17,7 @@
package com.android.ims.internal.uce.options;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java b/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
index 4af3e6e..70a7a84 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
@@ -16,13 +16,13 @@
package com.android.ims.internal.uce.options;
-import com.android.ims.internal.uce.common.StatusCode;
-import com.android.ims.internal.uce.common.CapInfo;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.ims.internal.uce.common.CapInfo;
+import com.android.ims.internal.uce.common.StatusCode;
+
/** @hide */
public class OptionsCmdStatus implements Parcelable {
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java b/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
index c5f333d..5afddf0 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.options;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java b/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
index 745df5b..1a3a028 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
@@ -16,12 +16,12 @@
package com.android.ims.internal.uce.presence;
-import com.android.ims.internal.uce.common.CapInfo;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.ims.internal.uce.common.CapInfo;
+
/** @hide */
public class PresCapInfo implements Parcelable {
diff --git a/core/java/com/android/ims/internal/uce/presence/PresCmdId.java b/core/java/com/android/ims/internal/uce/presence/PresCmdId.java
index 41020ec..fba0c77 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresCmdId.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresCmdId.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java b/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
index ff8069c..fbc64b8 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
@@ -16,12 +16,12 @@
package com.android.ims.internal.uce.presence;
-import com.android.ims.internal.uce.common.StatusCode;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.ims.internal.uce.common.StatusCode;
+
/** @hide */
public class PresCmdStatus implements Parcelable{
diff --git a/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java b/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
index 87193e3..fdff86f 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -47,6 +47,10 @@
public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_IWLAN = 8;
/** Trigger is unknown. */
public static final int UCE_PRES_PUBLISH_TRIGGER_UNKNOWN = 9;
+ /** Move to 5G NR with VoPS disabled. */
+ public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10;
+ /** Move to 5G NR with VoPS enabled. */
+ public static final int UCE_PRES_PUBLISH_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11;
@@ -113,4 +117,4 @@
public void readFromParcel(Parcel source) {
mPublishTriggerType = source.readInt();
}
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/ims/internal/uce/presence/PresResInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
index 237c999..af9b056 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
index 29699ea..9f37251 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
@@ -16,9 +16,10 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+
import java.util.Arrays;
/** @hide */
diff --git a/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java b/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
index ab46e4b..65b9fdb 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java b/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
index 83ba722..5eafa0f 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java b/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
index 5e42592..45b02f3 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java b/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
index bee928c..ab1e17c 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java b/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
index 7a47786..3608eb6a 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java b/core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
index 4b0b098..9aee879f 100644
--- a/core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
+++ b/core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
@@ -18,16 +18,9 @@
import android.content.Context;
import android.content.Intent;
-
-import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IBinder;
-import android.os.Message;
-import android.os.ServiceManager;
import android.os.RemoteException;
-
-import java.util.HashMap;
-import android.util.Log;
+import android.os.ServiceManager;
/**
* ImsUceManager Declaration
@@ -49,55 +42,25 @@
private IUceService mUceService = null;
private UceServiceDeathRecipient mDeathReceipient = new UceServiceDeathRecipient();
private Context mContext;
- private int mPhoneId;
- /**
- * Stores the UceManager instaces of Clients identified by
- * phoneId
- * @hide
- */
- private static HashMap<Integer, ImsUceManager> sUceManagerInstances =
- new HashMap<Integer, ImsUceManager>();
+ private static final Object sLock = new Object();
+ private static ImsUceManager sUceManager;
public static final String ACTION_UCE_SERVICE_UP =
"com.android.ims.internal.uce.UCE_SERVICE_UP";
public static final String ACTION_UCE_SERVICE_DOWN =
"com.android.ims.internal.uce.UCE_SERVICE_DOWN";
- /** Uce Service status received in IUceListener.setStatus()
- * callback
- * @hide
- */
- public static final int UCE_SERVICE_STATUS_FAILURE = 0;
- /** indicate UI to call Presence/Options API. */
- public static final int UCE_SERVICE_STATUS_ON = 1;
- /** Indicate UI destroy Presence/Options */
- public static final int UCE_SERVICE_STATUS_CLOSED = 2;
- /** Service up and trying to register for network events */
- public static final int UCE_SERVICE_STATUS_READY = 3;
-
- /**
- * Part of the ACTION_UCE_SERVICE_UP or _DOWN intents. A long
- * value; the phone ID corresponding to the IMS service coming up or down.
- * Internal use only.
- * @hide
- */
- public static final String EXTRA_PHONE_ID = "android:phone_id";
-
/**
* Gets the instance of UCE Manager
* @hide
*/
- public static ImsUceManager getInstance(Context context, int phoneId) {
- //if (DBG) Log.d (LOG_TAG, "GetInstance Called");
- synchronized (sUceManagerInstances) {
- if (sUceManagerInstances.containsKey(phoneId)) {
- return sUceManagerInstances.get(phoneId);
- } else {
- ImsUceManager uceMgr = new ImsUceManager(context, phoneId);
- sUceManagerInstances.put(phoneId, uceMgr);
- return uceMgr;
+ public static ImsUceManager getInstance(Context context) {
+ synchronized (sLock) {
+ if (sUceManager == null && context != null) {
+ sUceManager = new ImsUceManager(context);
}
+ return sUceManager;
}
}
@@ -105,10 +68,9 @@
* Constructor
* @hide
*/
- private ImsUceManager(Context context, int phoneId) {
+ private ImsUceManager(Context context) {
//if (DBG) Log.d (LOG_TAG, "Constructor");
mContext = context;
- mPhoneId = phoneId;
createUceService(true);
}
@@ -129,7 +91,7 @@
* Gets the UCE service name
* @hide
*/
- private String getUceServiceName(int phoneId) {
+ private String getUceServiceName() {
return UCE_SERVICE;
}
@@ -143,14 +105,14 @@
public void createUceService(boolean checkService) {
//if (DBG) Log.d (LOG_TAG, "CreateUceService Called");
if (checkService) {
- IBinder binder = ServiceManager.checkService(getUceServiceName(mPhoneId));
+ IBinder binder = ServiceManager.checkService(getUceServiceName());
if (binder == null) {
//if (DBG)Log.d (LOG_TAG, "Unable to find IBinder");
return;
}
}
- IBinder b = ServiceManager.getService(getUceServiceName(mPhoneId));
+ IBinder b = ServiceManager.getService(getUceServiceName());
if (b != null) {
try {
@@ -174,12 +136,10 @@
private class UceServiceDeathRecipient implements IBinder.DeathRecipient {
@Override
public void binderDied() {
- //if (DBG) Log.d (LOG_TAG, "found IBinder/IUceService Service Died");
mUceService = null;
if (mContext != null) {
Intent intent = new Intent(ACTION_UCE_SERVICE_DOWN);
- intent.putExtra(EXTRA_PHONE_ID, mPhoneId);
mContext.sendBroadcast(new Intent(intent));
}
}
diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java
index 7307de5..cfbb273 100644
--- a/core/java/com/android/internal/app/AlertActivity.java
+++ b/core/java/com/android/internal/app/AlertActivity.java
@@ -16,9 +16,9 @@
package com.android.internal.app;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.Dialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.KeyEvent;
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 3462e08..a08bf99 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -18,14 +18,11 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import com.android.internal.R;
-
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlertDialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
@@ -33,7 +30,6 @@
import android.os.Message;
import android.text.Layout;
import android.text.TextUtils;
-import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod;
import android.util.AttributeSet;
import android.util.TypedValue;
@@ -46,7 +42,6 @@
import android.view.ViewParent;
import android.view.ViewStub;
import android.view.Window;
-import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
@@ -63,6 +58,8 @@
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
+import com.android.internal.R;
+
import java.lang.ref.WeakReference;
public class AlertController {
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index f848309..22a2564 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -17,7 +17,7 @@
package com.android.internal.app;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 102ba5c..c0c9dd3 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -26,7 +26,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.prediction.AppPredictionContext;
@@ -34,6 +33,7 @@
import android.app.prediction.AppPredictor;
import android.app.prediction.AppTarget;
import android.app.prediction.AppTargetEvent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ComponentName;
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index a5f055f..9488e4f 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -20,12 +20,12 @@
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.ActivityTaskManager;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.IPackageManager;
diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java
index e3d07aa..d418770e 100644
--- a/core/java/com/android/internal/app/LocaleHelper.java
+++ b/core/java/com/android/internal/app/LocaleHelper.java
@@ -17,7 +17,7 @@
package com.android.internal.app;
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.icu.text.ListFormatter;
import android.icu.util.ULocale;
import android.os.LocaleList;
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index 7517424..3343593f 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -16,13 +16,11 @@
package com.android.internal.app;
-import com.android.internal.R;
-
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.ListFragment;
import android.app.backup.BackupManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -38,11 +36,13 @@
import android.widget.ListView;
import android.widget.TextView;
+import com.android.internal.R;
+
import java.text.Collator;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
-import java.util.ArrayList;
public class LocalePicker extends ListFragment {
private static final String TAG = "LocalePicker";
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index 49f77e1..1c5ca59 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -16,7 +16,7 @@
package com.android.internal.app;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.LocaleList;
import android.provider.Settings;
diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java
index 9a802a9..89aa770 100644
--- a/core/java/com/android/internal/app/NetInitiatedActivity.java
+++ b/core/java/com/android/internal/app/NetInitiatedActivity.java
@@ -16,19 +16,19 @@
package com.android.internal.app;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlertDialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.widget.Toast;
import android.util.Log;
-import android.location.LocationManager;
+import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.location.GpsNetInitiatedHandler;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 7d19eb6..871e4f8 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -21,7 +21,6 @@
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.UiThread;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
@@ -29,6 +28,7 @@
import android.app.VoiceInteractor.PickOptionRequest;
import android.app.VoiceInteractor.PickOptionRequest.Option;
import android.app.VoiceInteractor.Prompt;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index e71ee66..0cd1202 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -16,28 +16,17 @@
package com.android.internal.app;
-import com.android.internal.R;
-import com.android.internal.view.ActionBarPolicy;
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuPopupHelper;
-import com.android.internal.view.menu.SubMenuBuilder;
-import com.android.internal.widget.ActionBarContainer;
-import com.android.internal.widget.ActionBarContextView;
-import com.android.internal.widget.ActionBarOverlayLayout;
-import com.android.internal.widget.DecorToolbar;
-import com.android.internal.widget.ScrollingTabContainerView;
-
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActionBar;
import android.app.Activity;
import android.app.Dialog;
import android.app.FragmentTransaction;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -58,6 +47,17 @@
import android.widget.SpinnerAdapter;
import android.widget.Toolbar;
+import com.android.internal.R;
+import com.android.internal.view.ActionBarPolicy;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuPopupHelper;
+import com.android.internal.view.menu.SubMenuBuilder;
+import com.android.internal.widget.ActionBarContainer;
+import com.android.internal.widget.ActionBarContextView;
+import com.android.internal.widget.ActionBarOverlayLayout;
+import com.android.internal.widget.DecorToolbar;
+import com.android.internal.widget.ScrollingTabContainerView;
+
import java.lang.ref.WeakReference;
import java.util.ArrayList;
diff --git a/core/java/com/android/internal/compat/AndroidBuildClassifier.java b/core/java/com/android/internal/compat/AndroidBuildClassifier.java
new file mode 100644
index 0000000..0b937fa
--- /dev/null
+++ b/core/java/com/android/internal/compat/AndroidBuildClassifier.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.compat;
+
+import android.os.Build;
+
+/**
+ * Platform private class for determining the type of Android build installed.
+ *
+ */
+public class AndroidBuildClassifier {
+
+ public boolean isDebuggableBuild() {
+ return Build.IS_DEBUGGABLE;
+ }
+
+ public boolean isFinalBuild() {
+ return "REL".equals(Build.VERSION.CODENAME);
+ }
+}
diff --git a/core/java/com/android/internal/compat/IOverrideValidator.aidl b/core/java/com/android/internal/compat/IOverrideValidator.aidl
new file mode 100644
index 0000000..add4708
--- /dev/null
+++ b/core/java/com/android/internal/compat/IOverrideValidator.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.compat;
+
+import android.content.pm.ApplicationInfo;
+
+import com.android.internal.compat.OverrideAllowedState;
+
+/**
+ * Platform private API for determining whether a changeId can be overridden.
+ *
+ * {@hide}
+ */
+interface IOverrideValidator
+{
+ /**
+ * Validation function.
+ * @param changeId id of the change to be toggled on or off.
+ * @param packageName package of the app for which the change should be overridden.
+ * @return {@link OverrideAllowedState} specifying whether the change can be overridden for
+ * the given package or a reason why not.
+ */
+ OverrideAllowedState getOverrideAllowedState(long changeId, String packageName);
+}
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index 7dcb12c..4c203d3 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -17,6 +17,7 @@
package com.android.internal.compat;
import android.content.pm.ApplicationInfo;
+import com.android.internal.compat.IOverrideValidator;
import java.util.Map;
parcelable CompatibilityChangeConfig;
@@ -195,4 +196,9 @@
* @return An array of {@link CompatChangeInfo} known to the service.
*/
CompatibilityChangeInfo[] listAllChanges();
+
+ /**
+ * Get an instance that can determine whether a changeid can be overridden for a package name.
+ */
+ IOverrideValidator getOverrideValidator();
}
diff --git a/core/java/android/net/NetworkMisc.aidl b/core/java/com/android/internal/compat/OverrideAllowedState.aidl
similarity index 81%
copy from core/java/android/net/NetworkMisc.aidl
copy to core/java/com/android/internal/compat/OverrideAllowedState.aidl
index c65583f..10ceac7 100644
--- a/core/java/android/net/NetworkMisc.aidl
+++ b/core/java/com/android/internal/compat/OverrideAllowedState.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.net;
+package com.android.internal.compat;
-parcelable NetworkMisc;
+parcelable OverrideAllowedState;
\ No newline at end of file
diff --git a/core/java/com/android/internal/compat/OverrideAllowedState.java b/core/java/com/android/internal/compat/OverrideAllowedState.java
new file mode 100644
index 0000000..56216c2
--- /dev/null
+++ b/core/java/com/android/internal/compat/OverrideAllowedState.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.compat;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class contains all the possible override allowed states.
+ */
+public final class OverrideAllowedState implements Parcelable {
+ @IntDef({
+ ALLOWED,
+ DISABLED_NOT_DEBUGGABLE,
+ DISABLED_NON_TARGET_SDK,
+ DISABLED_TARGET_SDK_TOO_HIGH,
+ PACKAGE_DOES_NOT_EXIST
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface State {
+ }
+
+ /**
+ * Change can be overridden.
+ */
+ public static final int ALLOWED = 0;
+ /**
+ * Change cannot be overridden, due to the app not being debuggable.
+ */
+ public static final int DISABLED_NOT_DEBUGGABLE = 1;
+ /**
+ * Change cannot be overridden, due to the build being non-debuggable and the change being
+ * non-targetSdk.
+ */
+ public static final int DISABLED_NON_TARGET_SDK = 2;
+ /**
+ * Change cannot be overridden, due to the app's targetSdk being above the change's targetSdk.
+ */
+ public static final int DISABLED_TARGET_SDK_TOO_HIGH = 3;
+ /**
+ * Package does not exist.
+ */
+ public static final int PACKAGE_DOES_NOT_EXIST = 4;
+
+ @State
+ public final int state;
+ public final int appTargetSdk;
+ public final int changeIdTargetSdk;
+
+ private OverrideAllowedState(Parcel parcel) {
+ state = parcel.readInt();
+ appTargetSdk = parcel.readInt();
+ changeIdTargetSdk = parcel.readInt();
+ }
+
+ public OverrideAllowedState(@State int state, int appTargetSdk, int changeIdTargetSdk) {
+ this.state = state;
+ this.appTargetSdk = appTargetSdk;
+ this.changeIdTargetSdk = changeIdTargetSdk;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(state);
+ out.writeInt(appTargetSdk);
+ out.writeInt(changeIdTargetSdk);
+ }
+
+ /**
+ * Enforces the policy for overriding compat changes.
+ *
+ * @param changeId the change id that was attempted to be overridden.
+ * @param packageName the package for which the attempt was made.
+ * @throws SecurityException if the policy forbids this operation.
+ */
+ public void enforce(long changeId, String packageName)
+ throws SecurityException {
+ switch (state) {
+ case ALLOWED:
+ return;
+ case DISABLED_NOT_DEBUGGABLE:
+ throw new SecurityException(
+ "Cannot override a change on a non-debuggable app and user build.");
+ case DISABLED_NON_TARGET_SDK:
+ throw new SecurityException(
+ "Cannot override a default enabled/disabled change on a user build.");
+ case DISABLED_TARGET_SDK_TOO_HIGH:
+ throw new SecurityException(String.format(
+ "Cannot override %1$d for %2$s because the app's targetSdk (%3$d) is "
+ + "above the change's targetSdk threshold (%4$d)",
+ changeId, packageName, appTargetSdk, changeIdTargetSdk));
+ case PACKAGE_DOES_NOT_EXIST:
+ throw new SecurityException(String.format(
+ "Cannot override %1$d for %2$s because the package does not exist, and "
+ + "the change is targetSdk gated.",
+ changeId, packageName));
+ }
+ }
+
+ public static final @NonNull
+ Parcelable.Creator<OverrideAllowedState> CREATOR =
+ new Parcelable.Creator<OverrideAllowedState>() {
+ public OverrideAllowedState createFromParcel(Parcel parcel) {
+ OverrideAllowedState info = new OverrideAllowedState(parcel);
+ return info;
+ }
+
+ public OverrideAllowedState[] newArray(int size) {
+ return new OverrideAllowedState[size];
+ }
+ };
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OverrideAllowedState)) {
+ return false;
+ }
+ OverrideAllowedState otherState = (OverrideAllowedState) obj;
+ return state == otherState.state
+ && appTargetSdk == otherState.appTargetSdk
+ && changeIdTargetSdk == otherState.changeIdTargetSdk;
+ }
+}
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 5d7d3af..9baa6fb 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -16,8 +16,8 @@
package com.android.internal.content;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
diff --git a/core/java/com/android/internal/content/ReferrerIntent.java b/core/java/com/android/internal/content/ReferrerIntent.java
index 6d05f7e..6af03dd 100644
--- a/core/java/com/android/internal/content/ReferrerIntent.java
+++ b/core/java/com/android/internal/content/ReferrerIntent.java
@@ -16,7 +16,7 @@
package com.android.internal.content;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Parcel;
diff --git a/core/java/com/android/internal/database/SortCursor.java b/core/java/com/android/internal/database/SortCursor.java
index 7fe809e..230a9b87 100644
--- a/core/java/com/android/internal/database/SortCursor.java
+++ b/core/java/com/android/internal/database/SortCursor.java
@@ -16,7 +16,7 @@
package com.android.internal.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.AbstractCursor;
import android.database.Cursor;
import android.database.DataSetObserver;
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index f916cf6..ed04fd8 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -15,7 +15,7 @@
*/
package com.android.internal.logging;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.metrics.LogMaker;
import android.os.Build;
diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java
index 2ad9759..4eb7ded 100644
--- a/core/java/com/android/internal/net/LegacyVpnInfo.java
+++ b/core/java/com/android/internal/net/LegacyVpnInfo.java
@@ -16,8 +16,8 @@
package com.android.internal.net;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.NetworkInfo;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index e6be549..f5a19fe 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -16,8 +16,8 @@
package com.android.internal.net;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index 940cc36..4bb012a 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -16,10 +16,9 @@
package com.android.internal.net;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Build;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.ProxyInfo;
-import android.net.Uri;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/core/java/com/android/internal/os/AndroidPrintStream.java b/core/java/com/android/internal/os/AndroidPrintStream.java
index fe23411..a6e41ff 100644
--- a/core/java/com/android/internal/os/AndroidPrintStream.java
+++ b/core/java/com/android/internal/os/AndroidPrintStream.java
@@ -16,7 +16,7 @@
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
/**
diff --git a/core/java/com/android/internal/os/AtomicFile.java b/core/java/com/android/internal/os/AtomicFile.java
index a72a2f5..80b3314 100644
--- a/core/java/com/android/internal/os/AtomicFile.java
+++ b/core/java/com/android/internal/os/AtomicFile.java
@@ -16,7 +16,7 @@
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.FileUtils;
import android.util.Log;
diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java
index 5ba6629..db87f51 100644
--- a/core/java/com/android/internal/os/BaseCommand.java
+++ b/core/java/com/android/internal/os/BaseCommand.java
@@ -17,7 +17,7 @@
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ShellCommand;
import java.io.PrintStream;
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
index b1fc369..b3ea118 100644
--- a/core/java/com/android/internal/os/BatterySipper.java
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -15,7 +15,7 @@
*/
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.BatteryStats.Uid;
import java.util.List;
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index e85508e..b131ab8 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -16,7 +16,7 @@
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 3bd0fd2..183c0fb 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -18,10 +18,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.UidTraffic;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java
index 4901e1f..95c36ca 100644
--- a/core/java/com/android/internal/os/BinderInternal.java
+++ b/core/java/com/android/internal/os/BinderInternal.java
@@ -17,7 +17,7 @@
package com.android.internal.os;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java
index d323498..a18943c 100644
--- a/core/java/com/android/internal/os/ClassLoaderFactory.java
+++ b/core/java/com/android/internal/os/ClassLoaderFactory.java
@@ -16,7 +16,7 @@
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Trace;
import dalvik.system.DelegateLastClassLoader;
diff --git a/core/java/com/android/internal/os/FuseAppLoop.java b/core/java/com/android/internal/os/FuseAppLoop.java
index d08930b..f8f9fa9 100644
--- a/core/java/com/android/internal/os/FuseAppLoop.java
+++ b/core/java/com/android/internal/os/FuseAppLoop.java
@@ -18,17 +18,19 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
-import android.os.ProxyFileDescriptorCallback;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
+import android.os.ProxyFileDescriptorCallback;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.util.Log;
import android.util.SparseArray;
+
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
+
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index c8bfa1b..a11c815 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -16,7 +16,7 @@
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 8338d78..d3fe582 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -17,7 +17,7 @@
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index dcf8d28..f7b7742 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -16,9 +16,14 @@
package com.android.internal.os;
-import static android.os.Process.*;
+import static android.os.Process.PROC_COMBINE;
+import static android.os.Process.PROC_OUT_FLOAT;
+import static android.os.Process.PROC_OUT_LONG;
+import static android.os.Process.PROC_OUT_STRING;
+import static android.os.Process.PROC_PARENS;
+import static android.os.Process.PROC_SPACE_TERM;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Process;
import android.os.StrictMode;
import android.os.SystemClock;
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index fa823c4..13d0c5c 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -16,10 +16,10 @@
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ApplicationErrorReport;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.type.DefaultMimeMapFactory;
import android.os.Build;
import android.os.DeadObjectException;
@@ -35,6 +35,7 @@
import com.android.server.NetworkManagementSocketTagger;
import dalvik.system.RuntimeHooks;
+import dalvik.system.ThreadPrioritySetter;
import dalvik.system.VMRuntime;
import libcore.content.type.MimeMap;
@@ -204,6 +205,7 @@
*/
public static void preForkInit() {
if (DEBUG) Slog.d(TAG, "Entered preForkInit.");
+ RuntimeHooks.setThreadPrioritySetter(new RuntimeThreadPrioritySetter());
RuntimeInit.enableDdms();
// TODO(b/142019040#comment13): Decide whether to load the default instance eagerly, i.e.
// MimeMap.setDefault(DefaultMimeMapFactory.create());
@@ -216,6 +218,35 @@
MimeMap.setDefaultSupplier(DefaultMimeMapFactory::create);
}
+ private static class RuntimeThreadPrioritySetter implements ThreadPrioritySetter {
+ // Should remain consistent with kNiceValues[] in system/libartpalette/palette_android.cc
+ private static final int[] NICE_VALUES = {
+ Process.THREAD_PRIORITY_LOWEST, // 1 (MIN_PRIORITY)
+ Process.THREAD_PRIORITY_BACKGROUND + 6,
+ Process.THREAD_PRIORITY_BACKGROUND + 3,
+ Process.THREAD_PRIORITY_BACKGROUND,
+ Process.THREAD_PRIORITY_DEFAULT, // 5 (NORM_PRIORITY)
+ Process.THREAD_PRIORITY_DEFAULT - 2,
+ Process.THREAD_PRIORITY_DEFAULT - 4,
+ Process.THREAD_PRIORITY_URGENT_DISPLAY + 3,
+ Process.THREAD_PRIORITY_URGENT_DISPLAY + 2,
+ Process.THREAD_PRIORITY_URGENT_DISPLAY // 10 (MAX_PRIORITY)
+ };
+
+ @Override
+ public void setPriority(int nativeTid, int priority) {
+ // Check NICE_VALUES[] length first.
+ if (NICE_VALUES.length != (1 + Thread.MAX_PRIORITY - Thread.MIN_PRIORITY)) {
+ throw new AssertionError("Unexpected NICE_VALUES.length=" + NICE_VALUES.length);
+ }
+ // Priority should be in the range of MIN_PRIORITY (1) to MAX_PRIORITY (10).
+ if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
+ throw new IllegalArgumentException("Priority out of range: " + priority);
+ }
+ Process.setThreadPriority(nativeTid, NICE_VALUES[priority - Thread.MIN_PRIORITY]);
+ }
+ }
+
@UnsupportedAppUsage
protected static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
index d78bfac..003f610 100644
--- a/core/java/com/android/internal/os/SomeArgs.java
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -16,7 +16,7 @@
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Helper class for passing more arguments though a message
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 33adec1..c1c74dc 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -35,6 +35,7 @@
import android.system.Os;
import android.util.Log;
+import dalvik.annotation.optimization.FastNative;
import dalvik.system.ZygoteHooks;
import libcore.io.IoUtils;
@@ -49,9 +50,9 @@
/** @hide */
public final class Zygote {
/*
- * Bit values for "runtimeFlags" argument. The definitions are duplicated
- * in the native code.
- */
+ * Bit values for "runtimeFlags" argument. The definitions are duplicated
+ * in the native code.
+ */
/** enable debugging over JDWP */
public static final int DEBUG_ENABLE_JDWP = 1;
@@ -187,6 +188,11 @@
*/
public static final int SOCKET_BUFFER_SIZE = 256;
+ /**
+ * @hide for internal use only
+ */
+ private static final int PRIORITY_MAX = -20;
+
/** a prototype instance for a future List.toArray() */
protected static final int[][] INT_ARRAY_2D = new int[0][0];
@@ -251,8 +257,7 @@
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
int targetSdkVersion) {
ZygoteHooks.preFork();
- // Resets nice priority for zygote process.
- resetNicePriority();
+
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir);
@@ -264,6 +269,10 @@
// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
}
+
+ // Set the Java Language thread priority to the default value for new apps.
+ Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
+
ZygoteHooks.postForkCommon();
return pid;
}
@@ -298,7 +307,7 @@
int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir) {
nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
- niceName, startChildZygote, instructionSet, appDataDir);
+ niceName, startChildZygote, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
Trace.setTracingEnabled(true, runtimeFlags);
@@ -306,6 +315,9 @@
// Note that this event ends at the end of handleChildProc.
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
+ // Set the Java Language thread priority to the default value for new apps.
+ Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
+
/*
* This is called here (instead of after the fork but before the specialize) to maintain
* consistancy with the code paths for forkAndSpecialize.
@@ -350,15 +362,19 @@
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();
- // Resets nice priority for zygote process.
- resetNicePriority();
+
int pid = nativeForkSystemServer(
uid, gid, gids, runtimeFlags, rlimits,
permittedCapabilities, effectiveCapabilities);
+
// Enable tracing as soon as we enter the system_server.
if (pid == 0) {
Trace.setTracingEnabled(true, runtimeFlags);
}
+
+ // Set the Java Language thread priority to the default value for new apps.
+ Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
+
ZygoteHooks.postForkCommon();
return pid;
}
@@ -476,13 +492,16 @@
/**
* Fork a new unspecialized app process from the zygote
*
+ * @param usapPoolSocket The server socket the USAP will call accept on
* @param sessionSocketRawFDs Anonymous session sockets that are currently open
+ * @param isPriorityFork Value controlling the process priority level until accept is called
* @return In the Zygote process this function will always return null; in unspecialized app
* processes this function will return a Runnable object representing the new
* application that is passed up from usapMain.
*/
static Runnable forkUsap(LocalServerSocket usapPoolSocket,
- int[] sessionSocketRawFDs) {
+ int[] sessionSocketRawFDs,
+ boolean isPriorityFork) {
FileDescriptor[] pipeFDs = null;
try {
@@ -492,7 +511,8 @@
}
int pid =
- nativeForkUsap(pipeFDs[0].getInt$(), pipeFDs[1].getInt$(), sessionSocketRawFDs);
+ nativeForkUsap(pipeFDs[0].getInt$(), pipeFDs[1].getInt$(),
+ sessionSocketRawFDs, isPriorityFork);
if (pid == 0) {
IoUtils.closeQuietly(pipeFDs[0]);
@@ -506,8 +526,9 @@
}
private static native int nativeForkUsap(int readPipeFD,
- int writePipeFD,
- int[] sessionSocketRawFDs);
+ int writePipeFD,
+ int[] sessionSocketRawFDs,
+ boolean isPriorityFork);
/**
* This function is used by unspecialized app processes to wait for specialization requests from
@@ -518,7 +539,7 @@
* @return A runnable oject representing the new application.
*/
private static Runnable usapMain(LocalServerSocket usapPoolSocket,
- FileDescriptor writePipe) {
+ FileDescriptor writePipe) {
final int pid = Process.myPid();
Process.setArgV0(Process.is64Bit() ? "usap64" : "usap32");
@@ -527,6 +548,11 @@
Credentials peerCredentials = null;
ZygoteArguments args = null;
+ // Change the priority to max before calling accept so we can respond to new specialization
+ // requests as quickly as possible. This will be reverted to the default priority in the
+ // native specialization code.
+ boostUsapPriority();
+
while (true) {
try {
sessionSocket = usapPoolSocket.accept();
@@ -568,6 +594,7 @@
try {
// SIGTERM is blocked on loop exit. This prevents a USAP that is specializing from
// being killed during a pool flush.
+ setAppProcessName(args, "USAP");
applyUidSecurityPolicy(args, peerCredentials);
applyDebuggerSystemProperty(args);
@@ -628,23 +655,18 @@
}
specializeAppProcess(args.mUid, args.mGid, args.mGids,
- args.mRuntimeFlags, rlimits, args.mMountExternal,
- args.mSeInfo, args.mNiceName, args.mStartChildZygote,
- args.mInstructionSet, args.mAppDataDir);
+ args.mRuntimeFlags, rlimits, args.mMountExternal,
+ args.mSeInfo, args.mNiceName, args.mStartChildZygote,
+ args.mInstructionSet, args.mAppDataDir);
disableExecuteOnly(args.mTargetSdkVersion);
- if (args.mNiceName != null) {
- Process.setArgV0(args.mNiceName);
- }
-
- // End of the postFork event.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return ZygoteInit.zygoteInit(args.mTargetSdkVersion,
- args.mDisabledCompatChanges,
- args.mRemainingArgs,
- null /* classLoader */);
+ args.mDisabledCompatChanges,
+ args.mRemainingArgs,
+ null /* classLoader */);
} finally {
// Unblock SIGTERM to restore the process to default behavior.
unblockSigTerm();
@@ -663,6 +685,22 @@
private static native void nativeUnblockSigTerm();
+ private static void boostUsapPriority() {
+ nativeBoostUsapPriority();
+ }
+
+ private static native void nativeBoostUsapPriority();
+
+ static void setAppProcessName(ZygoteArguments args, String loggingTag) {
+ if (args.mNiceName != null) {
+ Process.setArgV0(args.mNiceName);
+ } else if (args.mPackageName != null) {
+ Process.setArgV0(args.mPackageName);
+ } else {
+ Log.w(loggingTag, "Unable to set package name.");
+ }
+ }
+
private static final String USAP_ERROR_PREFIX = "Invalid command to USAP: ";
/**
@@ -685,7 +723,7 @@
throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--start-child-zygote");
} else if (args.mApiBlacklistExemptions != null) {
throw new IllegalArgumentException(
- USAP_ERROR_PREFIX + "--set-api-blacklist-exemptions");
+ USAP_ERROR_PREFIX + "--set-api-blacklist-exemptions");
} else if (args.mHiddenApiAccessLogSampleRate != -1) {
throw new IllegalArgumentException(
USAP_ERROR_PREFIX + "--hidden-api-log-sampling-rate=");
@@ -696,8 +734,8 @@
throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--invoke-with");
} else if (args.mPermittedCapabilities != 0 || args.mEffectiveCapabilities != 0) {
throw new ZygoteSecurityException("Client may not specify capabilities: "
- + "permitted=0x" + Long.toHexString(args.mPermittedCapabilities)
- + ", effective=0x" + Long.toHexString(args.mEffectiveCapabilities));
+ + "permitted=0x" + Long.toHexString(args.mPermittedCapabilities)
+ + ", effective=0x" + Long.toHexString(args.mEffectiveCapabilities));
}
}
@@ -754,7 +792,7 @@
if (uidRestricted && args.mUidSpecified && (args.mUid < Process.SYSTEM_UID)) {
throw new ZygoteSecurityException(
"System UID may not launch process with UID < "
- + Process.SYSTEM_UID);
+ + Process.SYSTEM_UID);
}
}
@@ -804,8 +842,8 @@
if (args.mInvokeWith != null && peerUid != 0
&& (args.mRuntimeFlags & Zygote.DEBUG_ENABLE_JDWP) == 0) {
throw new ZygoteSecurityException("Peer is permitted to specify an "
- + "explicit invoke-with wrapper command only for debuggable "
- + "applications.");
+ + "explicit invoke-with wrapper command only for debuggable "
+ + "applications.");
}
}
@@ -888,7 +926,7 @@
return new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
- "Error building socket from file descriptor: " + fileDesc, ex);
+ "Error building socket from file descriptor: " + fileDesc, ex);
}
}
@@ -903,15 +941,6 @@
}
/**
- * Resets the calling thread priority to the default value (Thread.NORM_PRIORITY
- * or nice value 0). This updates both the priority value in java.lang.Thread and
- * the nice value (setpriority).
- */
- static void resetNicePriority() {
- Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
- }
-
- /**
* Executes "/system/bin/sh -c <command>" using the exec() system call.
* This method throws a runtime exception if exec() failed, otherwise, this
* method never returns.
@@ -941,4 +970,19 @@
command.append(" '").append(arg.replace("'", "'\\''")).append("'");
}
}
+
+ /**
+ * Parse the given unsolicited zygote message as type SIGCHLD,
+ * extract the payload information into the given output buffer.
+ *
+ * @param in The unsolicited zygote message to be parsed
+ * @param length The number of bytes in the message
+ * @param out The output buffer where the payload information will be placed
+ * @return Number of elements being place into output buffer, or -1 if
+ * either the message is malformed or not the type as expected here.
+ *
+ * @hide
+ */
+ @FastNative
+ public static native int nativeParseSigChld(byte[] in, int length, int[] out);
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 4c37591..2666d52 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -23,7 +23,7 @@
import static com.android.internal.os.ZygoteConnectionConstants.CONNECTION_TIMEOUT_MILLIS;
import static com.android.internal.os.ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.net.Credentials;
import android.net.LocalSocket;
@@ -346,7 +346,7 @@
if (zygoteServer.isUsapPoolEnabled()) {
Runnable fpResult =
zygoteServer.fillUsapPool(
- new int[]{mSocket.getFileDescriptor().getInt$()});
+ new int[]{mSocket.getFileDescriptor().getInt$()}, false);
if (fpResult != null) {
zygoteServer.setForkChild();
@@ -485,9 +485,7 @@
closeSocket();
- if (parsedArgs.mNiceName != null) {
- Process.setArgV0(parsedArgs.mNiceName);
- }
+ Zygote.setAppProcessName(parsedArgs, TAG);
// End of the postFork event.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 7b77a92..348262e 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -19,8 +19,8 @@
import static android.system.OsConstants.S_IRWXG;
import static android.system.OsConstants.S_IRWXO;
-import android.annotation.UnsupportedAppUsage;
import android.app.ApplicationLoaders;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.SharedLibraryInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -825,6 +825,18 @@
return result;
}
+ /**
+ * This is the entry point for a Zygote process. It creates the Zygote server, loads resources,
+ * and handles other tasks related to preparing the process for forking into applications.
+ *
+ * This process is started with a nice value of -20 (highest priority). All paths that flow
+ * into new processes are required to either set the priority to the default value or terminate
+ * before executing any non-system code. The native side of this occurs in SpecializeCommon,
+ * while the Java Language priority is changed in ZygoteInit.handleSystemServerProcess,
+ * ZygoteConnection.handleChildProc, and Zygote.usapMain.
+ *
+ * @param argv Command line arguments used to specify the Zygote's configuration.
+ */
@UnsupportedAppUsage
public static void main(String argv[]) {
ZygoteServer zygoteServer = null;
@@ -888,8 +900,6 @@
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
- } else {
- Zygote.resetNicePriority();
}
// Do an initial gc to clean up after startup
diff --git a/core/java/com/android/internal/os/ZygoteSecurityException.java b/core/java/com/android/internal/os/ZygoteSecurityException.java
index 7e50cb8..8111483 100644
--- a/core/java/com/android/internal/os/ZygoteSecurityException.java
+++ b/core/java/com/android/internal/os/ZygoteSecurityException.java
@@ -16,7 +16,7 @@
package com.android.internal.os;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Exception thrown when a security policy is violated.
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 1fd6e26..8d281b7 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -66,6 +66,12 @@
/** The default value used for the USAP_POOL_SIZE_MIN device property */
private static final String USAP_POOL_SIZE_MIN_DEFAULT = "1";
+ /** The default value used for the USAP_REFILL_DELAY_MS device property */
+ private static final String USAP_POOL_REFILL_DELAY_MS_DEFAULT = "3000";
+
+ /** The "not a timestamp" value for the refill delay timestamp mechanism. */
+ private static final int INVALID_TIMESTAMP = -1;
+
/**
* Indicates if this Zygote server can support a unspecialized app process pool. Currently this
* should only be true for the primary and secondary Zygotes, and not the App Zygotes or the
@@ -131,6 +137,24 @@
*/
private int mUsapPoolRefillThreshold = 0;
+ /**
+ * Number of milliseconds to delay before refilling the pool if it hasn't reached its
+ * minimum value.
+ */
+ private int mUsapPoolRefillDelayMs = -1;
+
+ /**
+ * If and when we should refill the USAP pool.
+ */
+ private UsapPoolRefillAction mUsapPoolRefillAction;
+ private long mUsapPoolRefillTriggerTimestamp;
+
+ private enum UsapPoolRefillAction {
+ DELAYED,
+ IMMEDIATE,
+ NONE
+ }
+
ZygoteServer() {
mUsapPoolEventFD = null;
mZygoteSocket = null;
@@ -160,9 +184,8 @@
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
- fetchUsapPoolPolicyProps();
-
mUsapPoolSupported = true;
+ fetchUsapPoolPolicyProps();
}
void setForkChild() {
@@ -267,6 +290,13 @@
mUsapPoolSizeMax);
}
+ final String usapPoolRefillDelayMsPropString = Zygote.getConfigurationProperty(
+ ZygoteConfig.USAP_POOL_REFILL_DELAY_MS, USAP_POOL_REFILL_DELAY_MS_DEFAULT);
+
+ if (!usapPoolRefillDelayMsPropString.isEmpty()) {
+ mUsapPoolRefillDelayMs = Integer.parseInt(usapPoolRefillDelayMsPropString);
+ }
+
// Sanity check
if (mUsapPoolSizeMin >= mUsapPoolSizeMax) {
Log.w(TAG, "The max size of the USAP pool must be greater than the minimum size."
@@ -293,9 +323,16 @@
}
}
+ private void fetchUsapPoolPolicyPropsIfUnfetched() {
+ if (mIsFirstPropertyCheck) {
+ mIsFirstPropertyCheck = false;
+ fetchUsapPoolPolicyProps();
+ }
+ }
+
/**
- * Checks to see if the current policy says that pool should be refilled, and spawns new USAPs
- * if necessary.
+ * Refill the USAP Pool to the appropriate level, determined by whether this is a priority
+ * refill event or not.
*
* @param sessionSocketRawFDs Anonymous session sockets that are currently open
* @return In the Zygote process this function will always return null; in unspecialized app
@@ -303,39 +340,48 @@
* application that is passed up from usapMain.
*/
- Runnable fillUsapPool(int[] sessionSocketRawFDs) {
+ Runnable fillUsapPool(int[] sessionSocketRawFDs, boolean isPriorityRefill) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillUsapPool");
// Ensure that the pool properties have been fetched.
- fetchUsapPoolPolicyPropsWithMinInterval();
+ fetchUsapPoolPolicyPropsIfUnfetched();
int usapPoolCount = Zygote.getUsapPoolCount();
- int numUsapsToSpawn = mUsapPoolSizeMax - usapPoolCount;
+ int numUsapsToSpawn;
- if (usapPoolCount < mUsapPoolSizeMin
- || numUsapsToSpawn >= mUsapPoolRefillThreshold) {
-
- // Disable some VM functionality and reset some system values
- // before forking.
- ZygoteHooks.preFork();
- Zygote.resetNicePriority();
-
- while (usapPoolCount++ < mUsapPoolSizeMax) {
- Runnable caller = Zygote.forkUsap(mUsapPoolSocket, sessionSocketRawFDs);
-
- if (caller != null) {
- return caller;
- }
- }
-
- // Re-enable runtime services for the Zygote. Services for unspecialized app process
- // are re-enabled in specializeAppProcess.
- ZygoteHooks.postForkCommon();
+ if (isPriorityRefill) {
+ // Refill to min
+ numUsapsToSpawn = mUsapPoolSizeMin - usapPoolCount;
Log.i("zygote",
- "Filled the USAP pool. New USAPs: " + numUsapsToSpawn);
+ "Priority USAP Pool refill. New USAPs: " + numUsapsToSpawn);
+ } else {
+ // Refill up to max
+ numUsapsToSpawn = mUsapPoolSizeMax - usapPoolCount;
+
+ Log.i("zygote",
+ "Delayed USAP Pool refill. New USAPs: " + numUsapsToSpawn);
}
+ // Disable some VM functionality and reset some system values
+ // before forking.
+ ZygoteHooks.preFork();
+
+ while (--numUsapsToSpawn >= 0) {
+ Runnable caller =
+ Zygote.forkUsap(mUsapPoolSocket, sessionSocketRawFDs, isPriorityRefill);
+
+ if (caller != null) {
+ return caller;
+ }
+ }
+
+ // Re-enable runtime services for the Zygote. Services for unspecialized app process
+ // are re-enabled in specializeAppProcess.
+ ZygoteHooks.postForkCommon();
+
+ resetUsapRefillState();
+
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return null;
@@ -358,13 +404,18 @@
mUsapPoolEnabled = newStatus;
if (newStatus) {
- return fillUsapPool(new int[]{ sessionSocket.getFileDescriptor().getInt$() });
+ return fillUsapPool(new int[]{ sessionSocket.getFileDescriptor().getInt$() }, false);
} else {
Zygote.emptyUsapPool();
return null;
}
}
+ void resetUsapRefillState() {
+ mUsapPoolRefillAction = UsapPoolRefillAction.NONE;
+ mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
+ }
+
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
@@ -377,8 +428,11 @@
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
+ mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
+
while (true) {
fetchUsapPoolPolicyPropsWithMinInterval();
+ mUsapPoolRefillAction = UsapPoolRefillAction.NONE;
int[] usapPipeFDs = null;
StructPollfd[] pollFDs;
@@ -430,140 +484,199 @@
}
}
+ int pollTimeoutMs;
+
+ if (mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
+ pollTimeoutMs = -1;
+ } else {
+ long elapsedTimeMs = System.currentTimeMillis() - mUsapPoolRefillTriggerTimestamp;
+
+ if (elapsedTimeMs >= mUsapPoolRefillDelayMs) {
+ // Normalize the poll timeout value when the time between one poll event and the
+ // next pushes us over the delay value. This prevents poll receiving a 0
+ // timeout value, which would result in it returning immediately.
+ pollTimeoutMs = -1;
+
+ } else if (elapsedTimeMs <= 0) {
+ // This can occur if the clock used by currentTimeMillis is reset, which is
+ // possible because it is not guaranteed to be monotonic. Because we can't tell
+ // how far back the clock was set the best way to recover is to simply re-start
+ // the respawn delay countdown.
+ pollTimeoutMs = mUsapPoolRefillDelayMs;
+
+ } else {
+ pollTimeoutMs = (int) (mUsapPoolRefillDelayMs - elapsedTimeMs);
+ }
+ }
+
+ int pollReturnValue;
try {
- Os.poll(pollFDs, -1);
+ pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
- boolean usapPoolFDRead = false;
+ if (pollReturnValue == 0) {
+ // The poll timeout has been exceeded. This only occurs when we have finished the
+ // USAP pool refill delay period.
- while (--pollIndex >= 0) {
- if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
- continue;
- }
+ mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
+ mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
- if (pollIndex == 0) {
- // Zygote server socket
+ } else {
+ boolean usapPoolFDRead = false;
- ZygoteConnection newPeer = acceptCommandPeer(abiList);
- peers.add(newPeer);
- socketFDs.add(newPeer.getFileDescriptor());
-
- } else if (pollIndex < usapPoolEventFDIndex) {
- // Session socket accepted from the Zygote server socket
-
- try {
- ZygoteConnection connection = peers.get(pollIndex);
- final Runnable command = connection.processOneCommand(this);
-
- // TODO (chriswailes): Is this extra check necessary?
- if (mIsForkChild) {
- // We're in the child. We should always have a command to run at this
- // stage if processOneCommand hasn't called "exec".
- if (command == null) {
- throw new IllegalStateException("command == null");
- }
-
- return command;
- } else {
- // We're in the server - we should never have any commands to run.
- if (command != null) {
- throw new IllegalStateException("command != null");
- }
-
- // We don't know whether the remote side of the socket was closed or
- // not until we attempt to read from it from processOneCommand. This
- // shows up as a regular POLLIN event in our regular processing loop.
- if (connection.isClosedByPeer()) {
- connection.closeSocket();
- peers.remove(pollIndex);
- socketFDs.remove(pollIndex);
- }
- }
- } catch (Exception e) {
- if (!mIsForkChild) {
- // We're in the server so any exception here is one that has taken place
- // pre-fork while processing commands or reading / writing from the
- // control socket. Make a loud noise about any such exceptions so that
- // we know exactly what failed and why.
-
- Slog.e(TAG, "Exception executing zygote command: ", e);
-
- // Make sure the socket is closed so that the other end knows
- // immediately that something has gone wrong and doesn't time out
- // waiting for a response.
- ZygoteConnection conn = peers.remove(pollIndex);
- conn.closeSocket();
-
- socketFDs.remove(pollIndex);
- } else {
- // We're in the child so any exception caught here has happened post
- // fork and before we execute ActivityThread.main (or any other main()
- // method). Log the details of the exception and bring down the process.
- Log.e(TAG, "Caught post-fork exception in child process.", e);
- throw e;
- }
- } finally {
- // Reset the child flag, in the event that the child process is a child-
- // zygote. The flag will not be consulted this loop pass after the Runnable
- // is returned.
- mIsForkChild = false;
- }
- } else {
- // Either the USAP pool event FD or a USAP reporting pipe.
-
- // If this is the event FD the payload will be the number of USAPs removed.
- // If this is a reporting pipe FD the payload will be the PID of the USAP
- // that was just specialized.
- long messagePayload = -1;
-
- try {
- byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
- int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
-
- if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
- DataInputStream inputStream =
- new DataInputStream(new ByteArrayInputStream(buffer));
-
- messagePayload = inputStream.readLong();
- } else {
- Log.e(TAG, "Incomplete read from USAP management FD of size "
- + readBytes);
- continue;
- }
- } catch (Exception ex) {
- if (pollIndex == usapPoolEventFDIndex) {
- Log.e(TAG, "Failed to read from USAP pool event FD: "
- + ex.getMessage());
- } else {
- Log.e(TAG, "Failed to read from USAP reporting pipe: "
- + ex.getMessage());
- }
-
+ while (--pollIndex >= 0) {
+ if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
- if (pollIndex > usapPoolEventFDIndex) {
- Zygote.removeUsapTableEntry((int) messagePayload);
- }
+ if (pollIndex == 0) {
+ // Zygote server socket
- usapPoolFDRead = true;
+ ZygoteConnection newPeer = acceptCommandPeer(abiList);
+ peers.add(newPeer);
+ socketFDs.add(newPeer.getFileDescriptor());
+
+ } else if (pollIndex < usapPoolEventFDIndex) {
+ // Session socket accepted from the Zygote server socket
+
+ try {
+ ZygoteConnection connection = peers.get(pollIndex);
+ final Runnable command = connection.processOneCommand(this);
+
+ // TODO (chriswailes): Is this extra check necessary?
+ if (mIsForkChild) {
+ // We're in the child. We should always have a command to run at
+ // this stage if processOneCommand hasn't called "exec".
+ if (command == null) {
+ throw new IllegalStateException("command == null");
+ }
+
+ return command;
+ } else {
+ // We're in the server - we should never have any commands to run.
+ if (command != null) {
+ throw new IllegalStateException("command != null");
+ }
+
+ // We don't know whether the remote side of the socket was closed or
+ // not until we attempt to read from it from processOneCommand. This
+ // shows up as a regular POLLIN event in our regular processing
+ // loop.
+ if (connection.isClosedByPeer()) {
+ connection.closeSocket();
+ peers.remove(pollIndex);
+ socketFDs.remove(pollIndex);
+ }
+ }
+ } catch (Exception e) {
+ if (!mIsForkChild) {
+ // We're in the server so any exception here is one that has taken
+ // place pre-fork while processing commands or reading / writing
+ // from the control socket. Make a loud noise about any such
+ // exceptions so that we know exactly what failed and why.
+
+ Slog.e(TAG, "Exception executing zygote command: ", e);
+
+ // Make sure the socket is closed so that the other end knows
+ // immediately that something has gone wrong and doesn't time out
+ // waiting for a response.
+ ZygoteConnection conn = peers.remove(pollIndex);
+ conn.closeSocket();
+
+ socketFDs.remove(pollIndex);
+ } else {
+ // We're in the child so any exception caught here has happened post
+ // fork and before we execute ActivityThread.main (or any other
+ // main() method). Log the details of the exception and bring down
+ // the process.
+ Log.e(TAG, "Caught post-fork exception in child process.", e);
+ throw e;
+ }
+ } finally {
+ // Reset the child flag, in the event that the child process is a child-
+ // zygote. The flag will not be consulted this loop pass after the
+ // Runnable is returned.
+ mIsForkChild = false;
+ }
+
+ } else {
+ // Either the USAP pool event FD or a USAP reporting pipe.
+
+ // If this is the event FD the payload will be the number of USAPs removed.
+ // If this is a reporting pipe FD the payload will be the PID of the USAP
+ // that was just specialized. The `continue` statements below ensure that
+ // the messagePayload will always be valid if we complete the try block
+ // without an exception.
+ long messagePayload;
+
+ try {
+ byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
+ int readBytes =
+ Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
+
+ if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
+ DataInputStream inputStream =
+ new DataInputStream(new ByteArrayInputStream(buffer));
+
+ messagePayload = inputStream.readLong();
+ } else {
+ Log.e(TAG, "Incomplete read from USAP management FD of size "
+ + readBytes);
+ continue;
+ }
+ } catch (Exception ex) {
+ if (pollIndex == usapPoolEventFDIndex) {
+ Log.e(TAG, "Failed to read from USAP pool event FD: "
+ + ex.getMessage());
+ } else {
+ Log.e(TAG, "Failed to read from USAP reporting pipe: "
+ + ex.getMessage());
+ }
+
+ continue;
+ }
+
+ if (pollIndex > usapPoolEventFDIndex) {
+ Zygote.removeUsapTableEntry((int) messagePayload);
+ }
+
+ usapPoolFDRead = true;
+ }
+ }
+
+ if (usapPoolFDRead) {
+ int usapPoolCount = Zygote.getUsapPoolCount();
+
+ if (usapPoolCount < mUsapPoolSizeMin) {
+ // Immediate refill
+ mUsapPoolRefillAction = UsapPoolRefillAction.IMMEDIATE;
+ } else if (mUsapPoolSizeMax - usapPoolCount >= mUsapPoolRefillThreshold) {
+ // Delayed refill
+ mUsapPoolRefillTriggerTimestamp = System.currentTimeMillis();
+ }
}
}
- // Check to see if the USAP pool needs to be refilled.
- if (usapPoolFDRead) {
+ if (mUsapPoolRefillAction != UsapPoolRefillAction.NONE) {
int[] sessionSocketRawFDs =
socketFDs.subList(1, socketFDs.size())
.stream()
.mapToInt(FileDescriptor::getInt$)
.toArray();
- final Runnable command = fillUsapPool(sessionSocketRawFDs);
+ final boolean isPriorityRefill =
+ mUsapPoolRefillAction == UsapPoolRefillAction.IMMEDIATE;
+
+ final Runnable command =
+ fillUsapPool(sessionSocketRawFDs, isPriorityRefill);
if (command != null) {
return command;
+ } else if (isPriorityRefill) {
+ // Schedule a delayed refill to finish refilling the pool.
+ mUsapPoolRefillTriggerTimestamp = System.currentTimeMillis();
}
}
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 07002d7..81db441 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -46,8 +46,8 @@
import android.animation.ObjectAnimator;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.WindowConfiguration;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java
index 791c2d7..f07f667 100644
--- a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java
+++ b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java
@@ -16,9 +16,9 @@
package com.android.internal.policy;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
import android.app.SearchManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@@ -33,7 +33,6 @@
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.View;
-import com.android.internal.policy.PhoneWindow;
/**
* @hide
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index daa57e0..a785ede 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -34,10 +34,10 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.app.SearchManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
diff --git a/core/java/com/android/internal/preference/YesNoPreference.java b/core/java/com/android/internal/preference/YesNoPreference.java
index 94ef619..f878054 100644
--- a/core/java/com/android/internal/preference/YesNoPreference.java
+++ b/core/java/com/android/internal/preference/YesNoPreference.java
@@ -16,6 +16,7 @@
package com.android.internal.preference;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
@@ -23,8 +24,6 @@
import android.preference.DialogPreference;
import android.util.AttributeSet;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
/**
* The {@link YesNoPreference} is a preference to show a dialog with Yes and No
* buttons.
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index cb67309..6fd271c 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -16,8 +16,8 @@
package com.android.internal.telephony;
-import android.os.Bundle;
import android.telephony.CallAttributes;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.PhoneCapability;
@@ -37,8 +37,8 @@
void onMessageWaitingIndicatorChanged(boolean mwi);
void onCallForwardingIndicatorChanged(boolean cfi);
- // we use bundle here instead of CellLocation so it can get the right subclass
- void onCellLocationChanged(in Bundle location);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ void onCellLocationChanged(in CellIdentity location);
void onCallStateChanged(int state, String incomingNumber);
void onDataConnectionStateChanged(int state, int networkType);
void onDataActivity(int direction);
@@ -62,5 +62,6 @@
void onOutgoingEmergencySms(in EmergencyNumber sentEmergencyNumber);
void onCallDisconnectCauseChanged(in int disconnectCause, in int preciseDisconnectCause);
void onImsCallDisconnectCauseChanged(in ImsReasonInfo imsReasonInfo);
+ void onRegistrationFailed(in CellIdentity cellIdentity,
+ String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
}
-
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index b1bc2d9..64b2361 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -19,8 +19,8 @@
import android.content.Intent;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
-import android.os.Bundle;
import android.telephony.CallQuality;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.PhoneCapability;
@@ -33,16 +33,22 @@
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
interface ITelephonyRegistry {
- void addOnSubscriptionsChangedListener(String pkg,
+ void addOnSubscriptionsChangedListener(String pkg, String featureId,
IOnSubscriptionsChangedListener callback);
- void addOnOpportunisticSubscriptionsChangedListener(String pkg,
+ void addOnOpportunisticSubscriptionsChangedListener(String pkg, String featureId,
IOnSubscriptionsChangedListener callback);
void removeOnSubscriptionsChangedListener(String pkg,
IOnSubscriptionsChangedListener callback);
+ /**
+ * @deprecated Use {@link #listenWithFeature(String, String, IPhoneStateListener, int,
+ * boolean) instead
+ */
@UnsupportedAppUsage
void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
- void listenForSubscriber(in int subId, String pkg, IPhoneStateListener callback, int events,
+ void listenWithFeature(String pkg, String featureId, IPhoneStateListener callback, int events,
boolean notifyNow);
+ void listenForSubscriber(in int subId, String pkg, String featureId,
+ IPhoneStateListener callback, int events, boolean notifyNow);
@UnsupportedAppUsage
void notifyCallStateForAllSubs(int state, String incomingNumber);
void notifyCallState(in int phoneId, in int subId, int state, String incomingNumber);
@@ -61,9 +67,9 @@
@UnsupportedAppUsage
void notifyDataConnectionFailed(String apnType);
void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, String apnType);
- @UnsupportedAppUsage(maxTargetSdk = 28)
- void notifyCellLocation(in Bundle cellLocation);
- void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ void notifyCellLocation(in CellIdentity cellLocation);
+ void notifyCellLocationForSubscriber(in int subId, in CellIdentity cellLocation);
@UnsupportedAppUsage
void notifyCellInfo(in List<CellInfo> cellInfo);
void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
@@ -92,4 +98,6 @@
void notifyCallQualityChanged(in CallQuality callQuality, int phoneId, int subId,
int callNetworkType);
void notifyImsDisconnectCause(int subId, in ImsReasonInfo imsReasonInfo);
+ void notifyRegistrationFailed(int slotIndex, int subId, in CellIdentity cellIdentity,
+ String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
}
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index b73ecd1..5a91880 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArraySet;
import dalvik.system.VMRuntime;
diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java
index b0888f2..f087718 100644
--- a/core/java/com/android/internal/util/AsyncChannel.java
+++ b/core/java/com/android/internal/util/AsyncChannel.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/com/android/internal/util/BitwiseInputStream.java b/core/java/com/android/internal/util/BitwiseInputStream.java
index 6ff67e9..ffae3ce 100644
--- a/core/java/com/android/internal/util/BitwiseInputStream.java
+++ b/core/java/com/android/internal/util/BitwiseInputStream.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An object that provides bitwise incremental read access to a byte array.
diff --git a/core/java/com/android/internal/util/BitwiseOutputStream.java b/core/java/com/android/internal/util/BitwiseOutputStream.java
index cdd6f17..9f41508 100644
--- a/core/java/com/android/internal/util/BitwiseOutputStream.java
+++ b/core/java/com/android/internal/util/BitwiseOutputStream.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An object that provides bitwise incremental write access to a byte array.
diff --git a/core/java/com/android/internal/util/CharSequences.java b/core/java/com/android/internal/util/CharSequences.java
index 6b6c43c..82ef200 100644
--- a/core/java/com/android/internal/util/CharSequences.java
+++ b/core/java/com/android/internal/util/CharSequences.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* {@link CharSequence} utility methods.
diff --git a/core/java/com/android/internal/util/ConnectivityUtil.java b/core/java/com/android/internal/util/ConnectivityUtil.java
new file mode 100644
index 0000000..b1d4fa0
--- /dev/null
+++ b/core/java/com/android/internal/util/ConnectivityUtil.java
@@ -0,0 +1,202 @@
+/*
+ * 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.internal.util;
+
+import android.Manifest;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.location.LocationManager;
+import android.os.Binder;
+import android.os.Build;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+
+/**
+ * Utility methods for common functionality using by different networks.
+ *
+ * @hide
+ */
+public class ConnectivityUtil {
+
+ private static final String TAG = "ConnectivityUtil";
+
+ private final Context mContext;
+ private final AppOpsManager mAppOps;
+ private final UserManager mUserManager;
+
+ public ConnectivityUtil(Context context) {
+ mContext = context;
+ mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ }
+
+ /**
+ * API to determine if the caller has fine/coarse location permission (depending on
+ * config/targetSDK level) and the location mode is enabled for the user. SecurityException is
+ * thrown if the caller has no permission or the location mode is disabled.
+ * @param pkgName package name of the application requesting access
+ * @param featureId The feature in the package
+ * @param uid The uid of the package
+ * @param message A message describing why the permission was checked. Only needed if this is
+ * not inside of a two-way binder call from the data receiver
+ */
+ public void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid,
+ @Nullable String message)
+ throws SecurityException {
+ checkPackage(uid, pkgName);
+
+ // Location mode must be enabled
+ if (!isLocationModeEnabled()) {
+ // Location mode is disabled, scan results cannot be returned
+ throw new SecurityException("Location mode is disabled for the device");
+ }
+
+ // LocationAccess by App: caller must have Coarse/Fine Location permission to have access to
+ // location information.
+ boolean canAppPackageUseLocation = checkCallersLocationPermission(pkgName, featureId,
+ uid, /* coarseForTargetSdkLessThanQ */ true, message);
+
+ // If neither caller or app has location access, there is no need to check
+ // any other permissions. Deny access to scan results.
+ if (!canAppPackageUseLocation) {
+ throw new SecurityException("UID " + uid + " has no location permission");
+ }
+ // If the User or profile is current, permission is granted
+ // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission.
+ if (!isCurrentProfile(uid) && !checkInteractAcrossUsersFull(uid)) {
+ throw new SecurityException("UID " + uid + " profile not permitted");
+ }
+ }
+
+ /**
+ * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION or
+ * android.Manifest.permission.ACCESS_COARSE_LOCATION (depending on config/targetSDK level)
+ * and a corresponding app op is allowed for this package and uid.
+ *
+ * @param pkgName PackageName of the application requesting access
+ * @param featureId The feature in the package
+ * @param uid The uid of the package
+ * @param coarseForTargetSdkLessThanQ If true and the targetSDK < Q then will check for COARSE
+ * else (false or targetSDK >= Q) then will check for FINE
+ * @param message A message describing why the permission was checked. Only needed if this is
+ * not inside of a two-way binder call from the data receiver
+ */
+ public boolean checkCallersLocationPermission(String pkgName, @Nullable String featureId,
+ int uid, boolean coarseForTargetSdkLessThanQ, @Nullable String message) {
+ boolean isTargetSdkLessThanQ = isTargetSdkLessThan(pkgName, Build.VERSION_CODES.Q, uid);
+
+ String permissionType = Manifest.permission.ACCESS_FINE_LOCATION;
+ if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) {
+ // Having FINE permission implies having COARSE permission (but not the reverse)
+ permissionType = Manifest.permission.ACCESS_COARSE_LOCATION;
+ }
+ if (getUidPermission(permissionType, uid)
+ == PackageManager.PERMISSION_DENIED) {
+ return false;
+ }
+
+ // Always checking FINE - even if will not enforce. This will record the request for FINE
+ // so that a location request by the app is surfaced to the user.
+ boolean isFineLocationAllowed = noteAppOpAllowed(
+ AppOpsManager.OPSTR_FINE_LOCATION, pkgName, featureId, uid, message);
+ if (isFineLocationAllowed) {
+ return true;
+ }
+ if (coarseForTargetSdkLessThanQ && isTargetSdkLessThanQ) {
+ return noteAppOpAllowed(AppOpsManager.OPSTR_COARSE_LOCATION, pkgName, featureId, uid,
+ message);
+ }
+ return false;
+ }
+
+ /**
+ * Retrieves a handle to LocationManager (if not already done) and check if location is enabled.
+ */
+ public boolean isLocationModeEnabled() {
+ LocationManager locationManager =
+ (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+ try {
+ return locationManager.isLocationEnabledForUser(UserHandle.of(
+ getCurrentUser()));
+ } catch (Exception e) {
+ Log.e(TAG, "Failure to get location mode via API, falling back to settings", e);
+ return false;
+ }
+ }
+
+ private boolean isTargetSdkLessThan(String packageName, int versionCode, int callingUid) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ if (mContext.getPackageManager().getApplicationInfoAsUser(
+ packageName, 0,
+ UserHandle.getUserHandleForUid(callingUid)).targetSdkVersion
+ < versionCode) {
+ return true;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // In case of exception, assume unknown app (more strict checking)
+ // Note: This case will never happen since checkPackage is
+ // called to verify validity before checking App's version.
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ return false;
+ }
+
+ private boolean noteAppOpAllowed(String op, String pkgName, @Nullable String featureId,
+ int uid, @Nullable String message) {
+ return mAppOps.noteOp(op, uid, pkgName) == AppOpsManager.MODE_ALLOWED;
+ }
+
+ private void checkPackage(int uid, String pkgName) throws SecurityException {
+ if (pkgName == null) {
+ throw new SecurityException("Checking UID " + uid + " but Package Name is Null");
+ }
+ mAppOps.checkPackage(uid, pkgName);
+ }
+
+ private boolean isCurrentProfile(int uid) {
+ UserHandle currentUser = UserHandle.of(getCurrentUser());
+ UserHandle callingUser = UserHandle.getUserHandleForUid(uid);
+ return currentUser.equals(callingUser)
+ || mUserManager.isSameProfileGroup(
+ currentUser.getIdentifier(), callingUser.getIdentifier());
+ }
+
+ private boolean checkInteractAcrossUsersFull(int uid) {
+ return getUidPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ @VisibleForTesting
+ protected int getCurrentUser() {
+ return ActivityManager.getCurrentUser();
+ }
+
+ private int getUidPermission(String permissionType, int uid) {
+ // We don't care about pid, pass in -1
+ return mContext.checkPermission(permissionType, -1, uid);
+ }
+}
diff --git a/core/java/com/android/internal/util/FastMath.java b/core/java/com/android/internal/util/FastMath.java
index 35efe70..b7dbee5 100644
--- a/core/java/com/android/internal/util/FastMath.java
+++ b/core/java/com/android/internal/util/FastMath.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Fast and loose math routines.
diff --git a/core/java/com/android/internal/util/FastPrintWriter.java b/core/java/com/android/internal/util/FastPrintWriter.java
index 981fbaa..63124de 100644
--- a/core/java/com/android/internal/util/FastPrintWriter.java
+++ b/core/java/com/android/internal/util/FastPrintWriter.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.Printer;
diff --git a/core/java/com/android/internal/util/FastXmlSerializer.java b/core/java/com/android/internal/util/FastXmlSerializer.java
index 9f76aeb..94e07a8 100644
--- a/core/java/com/android/internal/util/FastXmlSerializer.java
+++ b/core/java/com/android/internal/util/FastXmlSerializer.java
@@ -16,9 +16,10 @@
package com.android.internal.util;
+import android.compat.annotation.UnsupportedAppUsage;
+
import org.xmlpull.v1.XmlSerializer;
-import android.annotation.UnsupportedAppUsage;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
diff --git a/core/java/com/android/internal/util/GrowingArrayUtils.java b/core/java/com/android/internal/util/GrowingArrayUtils.java
index 9f56366..597fe6b 100644
--- a/core/java/com/android/internal/util/GrowingArrayUtils.java
+++ b/core/java/com/android/internal/util/GrowingArrayUtils.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* A helper class that aims to provide comparable growth performance to ArrayList, but on primitive
diff --git a/core/java/com/android/internal/util/HexDump.java b/core/java/com/android/internal/util/HexDump.java
index 6ffc928..ad88dd6 100644
--- a/core/java/com/android/internal/util/HexDump.java
+++ b/core/java/com/android/internal/util/HexDump.java
@@ -17,7 +17,7 @@
package com.android.internal.util;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
public class HexDump
{
diff --git a/core/java/com/android/internal/util/IState.java b/core/java/com/android/internal/util/IState.java
index eb66e2c..07837bf 100644
--- a/core/java/com/android/internal/util/IState.java
+++ b/core/java/com/android/internal/util/IState.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Message;
/**
diff --git a/core/java/com/android/internal/util/IndentingPrintWriter.java b/core/java/com/android/internal/util/IndentingPrintWriter.java
index 03a555e..34c6a05 100644
--- a/core/java/com/android/internal/util/IndentingPrintWriter.java
+++ b/core/java/com/android/internal/util/IndentingPrintWriter.java
@@ -16,7 +16,8 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Arrays;
diff --git a/core/java/com/android/internal/util/JournaledFile.java b/core/java/com/android/internal/util/JournaledFile.java
index 065cc5b2..a9d8f72 100644
--- a/core/java/com/android/internal/util/JournaledFile.java
+++ b/core/java/com/android/internal/util/JournaledFile.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import java.io.File;
diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java
index 580c2fa..5de77d9 100644
--- a/core/java/com/android/internal/util/MemInfoReader.java
+++ b/core/java/com/android/internal/util/MemInfoReader.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Debug;
import android.os.StrictMode;
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index 3fff5c2..408a7a8 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -18,7 +18,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.TextUtils;
import java.util.Collection;
@@ -126,7 +126,9 @@
* @param reference an object reference
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
+ * @deprecated - use {@link java.util.Objects.requireNonNull} instead.
*/
+ @Deprecated
@UnsupportedAppUsage
public static @NonNull <T> T checkNotNull(final T reference) {
if (reference == null) {
@@ -144,7 +146,9 @@
* be converted to a string using {@link String#valueOf(Object)}
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
+ * @deprecated - use {@link java.util.Objects.requireNonNull} instead.
*/
+ @Deprecated
@UnsupportedAppUsage
public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) {
if (reference == null) {
@@ -154,26 +158,6 @@
}
/**
- * Ensures that an object reference passed as a parameter to the calling
- * method is not null.
- *
- * @param reference an object reference
- * @param messageTemplate a printf-style message template to use if the check fails; will
- * be converted to a string using {@link String#format(String, Object...)}
- * @param messageArgs arguments for {@code messageTemplate}
- * @return the non-null reference that was validated
- * @throws NullPointerException if {@code reference} is null
- */
- public static @NonNull <T> T checkNotNull(final T reference,
- final String messageTemplate,
- final Object... messageArgs) {
- if (reference == null) {
- throw new NullPointerException(String.format(messageTemplate, messageArgs));
- }
- return reference;
- }
-
- /**
* Ensures the truth of an expression involving the state of the calling
* instance, but not involving any parameters to the calling method.
*
diff --git a/core/java/com/android/internal/util/State.java b/core/java/com/android/internal/util/State.java
index 3c61e03..636378e 100644
--- a/core/java/com/android/internal/util/State.java
+++ b/core/java/com/android/internal/util/State.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Message;
/**
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 6c217e5..0c24065 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -16,7 +16,7 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 8799e3d..c1be33a 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -16,10 +16,10 @@
package com.android.internal.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
import android.net.Uri;
import android.text.TextUtils;
import android.util.ArrayMap;
diff --git a/core/java/com/android/internal/view/ActionBarPolicy.java b/core/java/com/android/internal/view/ActionBarPolicy.java
index d18c35e..d16cb43 100644
--- a/core/java/com/android/internal/view/ActionBarPolicy.java
+++ b/core/java/com/android/internal/view/ActionBarPolicy.java
@@ -16,15 +16,15 @@
package com.android.internal.view;
-import com.android.internal.R;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Build;
+import com.android.internal.R;
+
/**
* Allows components to query for various configuration policy decisions
* about how the action bar should lay out and behave on the current device.
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index f5a9fde..adf56bf 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -16,7 +16,7 @@
package com.android.internal.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.input.InputManager;
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index ececba1..6278d4a3 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index 1b133d2..a5964b5 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -20,7 +20,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 0c057ea..a41048c 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -19,7 +19,7 @@
import android.annotation.AnyThread;
import android.annotation.BinderThread;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.inputmethodservice.AbstractInputMethodService;
import android.os.Bundle;
import android.os.Handler;
diff --git a/core/java/com/android/internal/view/WindowManagerPolicyThread.java b/core/java/com/android/internal/view/WindowManagerPolicyThread.java
index b009a2d..6d691fc 100644
--- a/core/java/com/android/internal/view/WindowManagerPolicyThread.java
+++ b/core/java/com/android/internal/view/WindowManagerPolicyThread.java
@@ -16,7 +16,7 @@
package com.android.internal.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
/**
diff --git a/core/java/com/android/internal/view/menu/ActionMenu.java b/core/java/com/android/internal/view/menu/ActionMenu.java
index 977c1f6..6482629 100644
--- a/core/java/com/android/internal/view/menu/ActionMenu.java
+++ b/core/java/com/android/internal/view/menu/ActionMenu.java
@@ -16,10 +16,7 @@
package com.android.internal.view.menu;
-import java.util.ArrayList;
-import java.util.List;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -30,6 +27,9 @@
import android.view.MenuItem;
import android.view.SubMenu;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* @hide
*/
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index ed253d5..bd8bcb9 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -17,7 +17,7 @@
package com.android.internal.view.menu;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index eb94db3..7622b93 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -16,7 +16,7 @@
package com.android.internal.view.menu;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
index 3d3aceb..a9f5e47 100644
--- a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
@@ -16,7 +16,7 @@
package com.android.internal.view.menu;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.IBinder;
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index 3d888d3..539c71e 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -16,13 +16,12 @@
package com.android.internal.view.menu;
-import com.android.internal.view.menu.MenuBuilder.ItemInvoker;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.text.Layout;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
@@ -30,7 +29,8 @@
import android.view.View;
import android.view.ViewDebug;
import android.widget.TextView;
-import android.text.Layout;
+
+import com.android.internal.view.menu.MenuBuilder.ItemInvoker;
/**
* The item view for each item in the {@link IconMenuView}.
diff --git a/core/java/com/android/internal/view/menu/IconMenuView.java b/core/java/com/android/internal/view/menu/IconMenuView.java
index 6f26434..9e240db 100644
--- a/core/java/com/android/internal/view/menu/IconMenuView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuView.java
@@ -16,9 +16,7 @@
package com.android.internal.view.menu;
-import com.android.internal.view.menu.MenuBuilder.ItemInvoker;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -29,10 +27,12 @@
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.LayoutInflater;
+
+import com.android.internal.view.menu.MenuBuilder.ItemInvoker;
import java.util.ArrayList;
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index 0e07ca7..b31ae38 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/com/android/internal/view/menu/MenuDialogHelper.java b/core/java/com/android/internal/view/menu/MenuDialogHelper.java
index 88d0a03..d02b8f6 100644
--- a/core/java/com/android/internal/view/menu/MenuDialogHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuDialogHelper.java
@@ -16,9 +16,9 @@
package com.android.internal.view.menu;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlertDialog;
import android.app.Dialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.DialogInterface;
import android.os.IBinder;
import android.view.KeyEvent;
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 994a9c1..218f518 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -16,10 +16,8 @@
package com.android.internal.view.menu;
-import com.android.internal.view.menu.MenuView.ItemView;
-
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@@ -39,6 +37,8 @@
import android.view.ViewDebug;
import android.widget.LinearLayout;
+import com.android.internal.view.menu.MenuView.ItemView;
+
/**
* @hide
*/
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index d00108e..bac6025 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
diff --git a/core/java/com/android/internal/view/menu/MenuPresenter.java b/core/java/com/android/internal/view/menu/MenuPresenter.java
index c5df8ad..35b8fef 100644
--- a/core/java/com/android/internal/view/menu/MenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/MenuPresenter.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Parcelable;
import android.view.ViewGroup;
diff --git a/core/java/com/android/internal/view/menu/MenuView.java b/core/java/com/android/internal/view/menu/MenuView.java
index 67a5530..a31c820 100644
--- a/core/java/com/android/internal/view/menu/MenuView.java
+++ b/core/java/com/android/internal/view/menu/MenuView.java
@@ -16,10 +16,7 @@
package com.android.internal.view.menu;
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuItemImpl;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.drawable.Drawable;
/**
diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
index cf6d974..6eb215e 100644
--- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
@@ -16,7 +16,7 @@
package com.android.internal.view.menu;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.Menu;
diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java
index 9ccee7f..0f0c1a3 100644
--- a/core/java/com/android/internal/widget/AbsActionBarView.java
+++ b/core/java/com/android/internal/widget/AbsActionBarView.java
@@ -15,26 +15,25 @@
*/
package com.android.internal.widget;
-import com.android.internal.R;
-
-import android.util.TypedValue;
-import android.view.ContextThemeWrapper;
-import android.view.MotionEvent;
-import android.widget.ActionMenuPresenter;
-import android.widget.ActionMenuView;
-
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
+import android.widget.ActionMenuPresenter;
+import android.widget.ActionMenuView;
+
+import com.android.internal.R;
public abstract class AbsActionBarView extends ViewGroup {
private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 78ed53f..051526e 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -15,13 +15,7 @@
*/
package com.android.internal.widget;
-import com.android.internal.R;
-
-import android.widget.ActionMenuPresenter;
-import android.widget.ActionMenuView;
-import com.android.internal.view.menu.MenuBuilder;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
@@ -32,9 +26,14 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
+import android.widget.ActionMenuPresenter;
+import android.widget.ActionMenuView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.internal.R;
+import com.android.internal.view.menu.MenuBuilder;
+
/**
* @hide
*/
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index e9e3cda..aca0b71 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -18,7 +18,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -41,6 +41,7 @@
import android.view.WindowInsets;
import android.widget.OverScroller;
import android.widget.Toolbar;
+
import com.android.internal.view.menu.MenuPresenter;
/**
diff --git a/core/java/com/android/internal/widget/AlertDialogLayout.java b/core/java/com/android/internal/widget/AlertDialogLayout.java
index 7a01749..d879b6d 100644
--- a/core/java/com/android/internal/widget/AlertDialogLayout.java
+++ b/core/java/com/android/internal/widget/AlertDialogLayout.java
@@ -18,8 +18,8 @@
import android.annotation.AttrRes;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.StyleRes;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java
index 0ca6743..ff13107 100644
--- a/core/java/com/android/internal/widget/ButtonBarLayout.java
+++ b/core/java/com/android/internal/widget/ButtonBarLayout.java
@@ -16,7 +16,7 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
diff --git a/core/java/com/android/internal/widget/CachingIconView.java b/core/java/com/android/internal/widget/CachingIconView.java
index 35bff6d..74ad815 100644
--- a/core/java/com/android/internal/widget/CachingIconView.java
+++ b/core/java/com/android/internal/widget/CachingIconView.java
@@ -18,7 +18,7 @@
import android.annotation.DrawableRes;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
diff --git a/core/java/com/android/internal/widget/DialogTitle.java b/core/java/com/android/internal/widget/DialogTitle.java
index 405436c..0bfd684 100644
--- a/core/java/com/android/internal/widget/DialogTitle.java
+++ b/core/java/com/android/internal/widget/DialogTitle.java
@@ -16,7 +16,7 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.Layout;
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index 2b648e9..ff3543c8 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -16,7 +16,7 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.text.Editable;
import android.text.method.KeyListener;
diff --git a/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java b/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java
index cc7911d..9ef9f69 100644
--- a/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java
+++ b/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java
@@ -16,12 +16,12 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.view.View;
import android.view.MotionEvent;
+import android.view.View;
import android.widget.LinearLayout;
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index 09bc28c..d78b26a 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -1,6 +1,6 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.AsyncTask;
import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index dc45f78..8ecee62 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -27,11 +27,11 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.admin.DevicePolicyManager;
import android.app.admin.PasswordMetrics;
import android.app.trust.IStrongAuthTracker;
import android.app.trust.TrustManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -58,10 +58,10 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
-import com.google.android.collect.Lists;
-
import libcore.util.HexEncoding;
+import com.google.android.collect.Lists;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.security.MessageDigest;
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 3f6c4d4..591a5e8 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -19,7 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
diff --git a/core/java/com/android/internal/widget/NumericTextView.java b/core/java/com/android/internal/widget/NumericTextView.java
index d215670..c8f9011 100644
--- a/core/java/com/android/internal/widget/NumericTextView.java
+++ b/core/java/com/android/internal/widget/NumericTextView.java
@@ -16,7 +16,7 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 1f5b070..3736511 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -16,7 +16,7 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
diff --git a/core/java/com/android/internal/widget/PreferenceImageView.java b/core/java/com/android/internal/widget/PreferenceImageView.java
index 02a0b8d..43b6b5a 100644
--- a/core/java/com/android/internal/widget/PreferenceImageView.java
+++ b/core/java/com/android/internal/widget/PreferenceImageView.java
@@ -16,7 +16,7 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
diff --git a/core/java/com/android/internal/widget/RecyclerView.java b/core/java/com/android/internal/widget/RecyclerView.java
index b66a7b4..43a227a 100644
--- a/core/java/com/android/internal/widget/RecyclerView.java
+++ b/core/java/com/android/internal/widget/RecyclerView.java
@@ -20,7 +20,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.Observable;
diff --git a/core/java/com/android/internal/widget/ScrollBarUtils.java b/core/java/com/android/internal/widget/ScrollBarUtils.java
index 982e315..3e9d697 100644
--- a/core/java/com/android/internal/widget/ScrollBarUtils.java
+++ b/core/java/com/android/internal/widget/ScrollBarUtils.java
@@ -16,7 +16,7 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
public class ScrollBarUtils {
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 5d48ab9..aa0b0bb 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -15,13 +15,11 @@
*/
package com.android.internal.widget;
-import com.android.internal.view.ActionBarPolicy;
-
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActionBar;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
@@ -42,6 +40,8 @@
import android.widget.Spinner;
import android.widget.TextView;
+import com.android.internal.view.ActionBarPolicy;
+
/**
* This widget implements the dynamic action bar tab behavior that can change
* across different configurations or circumstances.
diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java
index 4b5d624..5e6f3a4 100644
--- a/core/java/com/android/internal/widget/SlidingTab.java
+++ b/core/java/com/android/internal/widget/SlidingTab.java
@@ -16,7 +16,7 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -34,12 +34,12 @@
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
-import android.view.animation.Animation.AnimationListener;
import android.widget.ImageView;
-import android.widget.TextView;
import android.widget.ImageView.ScaleType;
+import android.widget.TextView;
import com.android.internal.R;
diff --git a/core/java/com/android/internal/widget/TextViewInputDisabler.java b/core/java/com/android/internal/widget/TextViewInputDisabler.java
index 8d8f0fe..57806eb 100644
--- a/core/java/com/android/internal/widget/TextViewInputDisabler.java
+++ b/core/java/com/android/internal/widget/TextViewInputDisabler.java
@@ -16,7 +16,7 @@
package com.android.internal.widget;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.InputFilter;
import android.text.Spanned;
import android.widget.TextView;
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 7d36b02..c8a86d1 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -18,7 +18,7 @@
import android.annotation.DrawableRes;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
diff --git a/core/java/com/android/server/ResettableTimeout.java b/core/java/com/android/server/ResettableTimeout.java
index 64083f7..511af94 100644
--- a/core/java/com/android/server/ResettableTimeout.java
+++ b/core/java/com/android/server/ResettableTimeout.java
@@ -16,10 +16,9 @@
package com.android.server;
-import android.os.SystemClock;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ConditionVariable;
+import android.os.SystemClock;
/**
* Utility class that you can call on with a timeout, and get called back
diff --git a/core/java/com/android/server/net/BaseNetworkObserver.java b/core/java/com/android/server/net/BaseNetworkObserver.java
index e1a10a5..2a9c0b4 100644
--- a/core/java/com/android/server/net/BaseNetworkObserver.java
+++ b/core/java/com/android/server/net/BaseNetworkObserver.java
@@ -16,7 +16,7 @@
package com.android.server.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.INetworkManagementEventObserver;
import android.net.LinkAddress;
import android.net.RouteInfo;
diff --git a/core/java/com/android/server/net/NetlinkTracker.java b/core/java/com/android/server/net/NetlinkTracker.java
index 647fb5b..b57397f 100644
--- a/core/java/com/android/server/net/NetlinkTracker.java
+++ b/core/java/com/android/server/net/NetlinkTracker.java
@@ -16,7 +16,7 @@
package com.android.server.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.RouteInfo;
diff --git a/core/java/com/google/android/collect/Lists.java b/core/java/com/google/android/collect/Lists.java
index 8f6594a..585847d 100644
--- a/core/java/com/google/android/collect/Lists.java
+++ b/core/java/com/google/android/collect/Lists.java
@@ -16,7 +16,8 @@
package com.google.android.collect;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.ArrayList;
import java.util.Collections;
diff --git a/core/java/com/google/android/collect/Maps.java b/core/java/com/google/android/collect/Maps.java
index 6ba3320..cd4c128 100644
--- a/core/java/com/google/android/collect/Maps.java
+++ b/core/java/com/google/android/collect/Maps.java
@@ -16,7 +16,7 @@
package com.google.android.collect;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import java.util.HashMap;
diff --git a/core/java/com/google/android/collect/Sets.java b/core/java/com/google/android/collect/Sets.java
index 09b5e51..c67a88a 100644
--- a/core/java/com/google/android/collect/Sets.java
+++ b/core/java/com/google/android/collect/Sets.java
@@ -16,7 +16,7 @@
package com.google.android.collect;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArraySet;
import java.util.Collections;
diff --git a/core/java/com/google/android/util/AbstractMessageParser.java b/core/java/com/google/android/util/AbstractMessageParser.java
index 00fcb16..b41ac1f 100644
--- a/core/java/com/google/android/util/AbstractMessageParser.java
+++ b/core/java/com/google/android/util/AbstractMessageParser.java
@@ -16,7 +16,7 @@
package com.google.android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/core/java/org/apache/http/conn/ssl/AbstractVerifier.java b/core/java/org/apache/http/conn/ssl/AbstractVerifier.java
index 36d6e22..2848ad7 100644
--- a/core/java/org/apache/http/conn/ssl/AbstractVerifier.java
+++ b/core/java/org/apache/http/conn/ssl/AbstractVerifier.java
@@ -31,7 +31,7 @@
package org.apache.http.conn.ssl;
-import java.util.regex.Pattern;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.IOException;
import java.security.cert.Certificate;
@@ -43,10 +43,10 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
-import java.util.logging.Logger;
import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
-import android.annotation.UnsupportedAppUsage;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
diff --git a/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java b/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
index b2e8b5e..ffae757 100644
--- a/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
+++ b/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
@@ -31,20 +31,14 @@
package org.apache.http.conn.ssl;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Build;
+
import org.apache.http.conn.scheme.HostNameResolver;
import org.apache.http.conn.scheme.LayeredSocketFactory;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -57,6 +51,14 @@
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+
/**
* Layered socket factory for TLS/SSL connections, based on JSSE.
*.
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 08aa1d9..ba7fe7f 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -24,9 +24,7 @@
#include <linux/tcp.h>
#include <net/if.h>
#include <netinet/ether.h>
-#include <netinet/icmp6.h>
#include <netinet/ip.h>
-#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <android_runtime/AndroidRuntime.h>
@@ -102,98 +100,6 @@
}
}
-static void android_net_utils_setupRaSocket(JNIEnv *env, jobject clazz, jobject javaFd,
- jint ifIndex)
-{
- static const int kLinkLocalHopLimit = 255;
-
- int fd = jniGetFDFromFileDescriptor(env, javaFd);
-
- // Set an ICMPv6 filter that only passes Router Solicitations.
- struct icmp6_filter rs_only;
- ICMP6_FILTER_SETBLOCKALL(&rs_only);
- ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &rs_only);
- socklen_t len = sizeof(rs_only);
- if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &rs_only, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(ICMP6_FILTER): %s", strerror(errno));
- return;
- }
-
- // Most/all of the rest of these options can be set via Java code, but
- // because we're here on account of setting an icmp6_filter go ahead
- // and do it all natively for now.
- //
- // TODO: Consider moving these out to Java.
-
- // Set the multicast hoplimit to 255 (link-local only).
- int hops = kLinkLocalHopLimit;
- len = sizeof(hops);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno));
- return;
- }
-
- // Set the unicast hoplimit to 255 (link-local only).
- hops = kLinkLocalHopLimit;
- len = sizeof(hops);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno));
- return;
- }
-
- // Explicitly disable multicast loopback.
- int off = 0;
- len = sizeof(off);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_MULTICAST_LOOP): %s", strerror(errno));
- return;
- }
-
- // Specify the IPv6 interface to use for outbound multicast.
- len = sizeof(ifIndex);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_MULTICAST_IF): %s", strerror(errno));
- return;
- }
-
- // Additional options to be considered:
- // - IPV6_TCLASS
- // - IPV6_RECVPKTINFO
- // - IPV6_RECVHOPLIMIT
-
- // Bind to [::].
- const struct sockaddr_in6 sin6 = {
- .sin6_family = AF_INET6,
- .sin6_port = 0,
- .sin6_flowinfo = 0,
- .sin6_addr = IN6ADDR_ANY_INIT,
- .sin6_scope_id = 0,
- };
- auto sa = reinterpret_cast<const struct sockaddr *>(&sin6);
- len = sizeof(sin6);
- if (bind(fd, sa, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "bind(IN6ADDR_ANY): %s", strerror(errno));
- return;
- }
-
- // Join the all-routers multicast group, ff02::2%index.
- struct ipv6_mreq all_rtrs = {
- .ipv6mr_multiaddr = {{{0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2}}},
- .ipv6mr_interface = ifIndex,
- };
- len = sizeof(all_rtrs);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &all_rtrs, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_JOIN_GROUP): %s", strerror(errno));
- return;
- }
-}
static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId)
{
@@ -370,7 +276,6 @@
{ "attachDropAllBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDropAllBPFFilter },
{ "detachBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_detachBPFFilter },
{ "getTcpRepairWindow", "(Ljava/io/FileDescriptor;)Landroid/net/TcpRepairWindow;", (void*) android_net_utils_getTcpRepairWindow },
- { "setupRaSocket", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_setupRaSocket },
{ "resNetworkSend", "(I[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend },
{ "resNetworkQuery", "(ILjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery },
{ "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult },
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 52ce54b..7bf35f9 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -193,7 +193,8 @@
{
int err = memtrack_proc_get(p, pid);
if (err != 0) {
- ALOGW("failed to get memory consumption info: %d", err);
+ // The memtrack HAL may not be available, do not log to avoid flooding
+ // logcat.
return err;
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 58fd9c0..486df62 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -63,6 +63,7 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <sys/un.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -164,11 +165,26 @@
static int gUsapPoolEventFD = -1;
/**
+ * The socket file descriptor used to send notifications to the
+ * system_server.
+ */
+static int gSystemServerSocketFd = -1;
+
+/**
* The maximum value that the gUSAPPoolSizeMax variable may take. This value
* is a mirror of ZygoteServer.USAP_POOL_SIZE_MAX_LIMIT
*/
static constexpr int USAP_POOL_SIZE_MAX_LIMIT = 100;
+/** The numeric value for the maximum priority a process may possess. */
+static constexpr int PROCESS_PRIORITY_MAX = -20;
+
+/** The numeric value for the minimum priority a process may possess. */
+static constexpr int PROCESS_PRIORITY_MIN = 19;
+
+/** The numeric value for the normal priority a process should have. */
+static constexpr int PROCESS_PRIORITY_DEFAULT = 0;
+
/**
* A helper class containing accounting information for USAPs.
*/
@@ -305,6 +321,26 @@
PROFILE_FROM_SHELL = 1 << 15,
};
+enum UnsolicitedZygoteMessageTypes : uint32_t {
+ UNSOLICITED_ZYGOTE_MESSAGE_TYPE_RESERVED = 0,
+ UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD = 1,
+};
+
+struct UnsolicitedZygoteMessageSigChld {
+ struct {
+ UnsolicitedZygoteMessageTypes type;
+ } header;
+ struct {
+ pid_t pid;
+ uid_t uid;
+ int status;
+ } payload;
+};
+
+// Keep sync with services/core/java/com/android/server/am/ProcessList.java
+static constexpr struct sockaddr_un kSystemServerSockAddr =
+ {.sun_family = AF_LOCAL, .sun_path = "/data/system/unsolzygotesocket"};
+
// Forward declaration so we don't have to move the signal handler.
static bool RemoveUsapTableEntry(pid_t usap_pid);
@@ -314,8 +350,37 @@
env->FatalError(oss.str().c_str());
}
+// Create the socket which is going to be used to send unsolicited message
+// to system_server, the socket will be closed post forking a child process.
+// It's expected to be called at each zygote's initialization.
+static void initUnsolSocketToSystemServer() {
+ gSystemServerSocketFd = socket(AF_LOCAL, SOCK_DGRAM | SOCK_NONBLOCK, 0);
+ if (gSystemServerSocketFd >= 0) {
+ ALOGV("Zygote:systemServerSocketFD = %d", gSystemServerSocketFd);
+ } else {
+ ALOGE("Unable to create socket file descriptor to connect to system_server");
+ }
+}
+
+static void sendSigChildStatus(const pid_t pid, const uid_t uid, const int status) {
+ int socketFd = gSystemServerSocketFd;
+ if (socketFd >= 0) {
+ // fill the message buffer
+ struct UnsolicitedZygoteMessageSigChld data =
+ {.header = {.type = UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD},
+ .payload = {.pid = pid, .uid = uid, .status = status}};
+ if (TEMP_FAILURE_RETRY(
+ sendto(socketFd, &data, sizeof(data), 0,
+ reinterpret_cast<const struct sockaddr*>(&kSystemServerSockAddr),
+ sizeof(kSystemServerSockAddr))) == -1) {
+ async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Zygote failed to write to system_server FD: %s",
+ strerror(errno));
+ }
+ }
+}
// This signal handler is for zygote mode, since the zygote must reap its children
-static void SigChldHandler(int /*signal_number*/) {
+static void SigChldHandler(int /*signal_number*/, siginfo_t* info, void* /*ucontext*/) {
pid_t pid;
int status;
int64_t usaps_removed = 0;
@@ -329,6 +394,8 @@
int saved_errno = errno;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ // Notify system_server that we received a SIGCHLD
+ sendSigChildStatus(pid, info->si_uid, status);
// Log process-death status that we care about.
if (WIFEXITED(status)) {
async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
@@ -402,8 +469,7 @@
// This ends up being called repeatedly before each fork(), but there's
// no real harm in that.
static void SetSignalHandlers() {
- struct sigaction sig_chld = {};
- sig_chld.sa_handler = SigChldHandler;
+ struct sigaction sig_chld = {.sa_flags = SA_SIGINFO, .sa_sigaction = SigChldHandler};
if (sigaction(SIGCHLD, &sig_chld, nullptr) < 0) {
ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
@@ -903,7 +969,8 @@
// Utility routine to fork a process from the zygote.
static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
const std::vector<int>& fds_to_close,
- const std::vector<int>& fds_to_ignore) {
+ const std::vector<int>& fds_to_ignore,
+ bool is_priority_fork) {
SetSignalHandlers();
// Curry a failure function.
@@ -936,6 +1003,12 @@
pid_t pid = fork();
if (pid == 0) {
+ if (is_priority_fork) {
+ setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
+ } else {
+ setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
+ }
+
// The child process.
PreApplicationInit();
@@ -951,6 +1024,9 @@
// Turn fdsan back on.
android_fdsan_set_error_level(fdsan_error_level);
+
+ // Reset the fd to the unsolicited zygote socket
+ gSystemServerSocketFd = -1;
} else {
ALOGD("Forked child process %d", pid);
}
@@ -987,22 +1063,16 @@
DropCapabilitiesBoundingSet(fail_fn);
- bool use_native_bridge = !is_system_server &&
- instruction_set.has_value() &&
- android::NativeBridgeAvailable() &&
- android::NeedsNativeBridge(instruction_set.value().c_str());
+ bool need_pre_initialize_native_bridge =
+ !is_system_server &&
+ instruction_set.has_value() &&
+ android::NativeBridgeAvailable() &&
+ // Native bridge may be already initialized if this
+ // is an app forked from app-zygote.
+ !android::NativeBridgeInitialized() &&
+ android::NeedsNativeBridge(instruction_set.value().c_str());
- if (use_native_bridge && !app_data_dir.has_value()) {
- // The app_data_dir variable should never be empty if we need to use a
- // native bridge. In general, app_data_dir will never be empty for normal
- // applications. It can only happen in special cases (for isolated
- // processes which are not associated with any app). These are launched by
- // the framework and should not be emulated anyway.
- use_native_bridge = false;
- ALOGW("Native bridge will not be used because managed_app_data_dir == nullptr.");
- }
-
- MountEmulatedStorage(uid, mount_external, use_native_bridge, fail_fn);
+ MountEmulatedStorage(uid, mount_external, need_pre_initialize_native_bridge, fail_fn);
// If this zygote isn't root, it won't be able to create a process group,
// since the directory is owned by root.
@@ -1018,11 +1088,12 @@
SetGids(env, gids, fail_fn);
SetRLimits(env, rlimits, fail_fn);
- if (use_native_bridge) {
- // Due to the logic behind use_native_bridge we know that both app_data_dir
- // and instruction_set contain values.
- android::PreInitializeNativeBridge(app_data_dir.value().c_str(),
- instruction_set.value().c_str());
+ if (need_pre_initialize_native_bridge) {
+ // Due to the logic behind need_pre_initialize_native_bridge we know that
+ // instruction_set contains a value.
+ android::PreInitializeNativeBridge(
+ app_data_dir.has_value() ? app_data_dir.value().c_str() : nullptr,
+ instruction_set.value().c_str());
}
if (setresgid(gid, gid, gid) == -1) {
@@ -1130,9 +1201,16 @@
}
}
+ if (is_child_zygote) {
+ initUnsolSocketToSystemServer();
+ }
+
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
is_system_server, is_child_zygote, managed_instruction_set);
+ // Reset the process priority to the default value.
+ setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT);
+
if (env->ExceptionCheck()) {
fail_fn("Error calling post fork hooks.");
}
@@ -1372,7 +1450,12 @@
fds_to_ignore.push_back(gUsapPoolEventFD);
}
- pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore);
+ if (gSystemServerSocketFd != -1) {
+ fds_to_close.push_back(gSystemServerSocketFd);
+ fds_to_ignore.push_back(gSystemServerSocketFd);
+ }
+
+ pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true);
if (pid == 0) {
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
@@ -1397,9 +1480,15 @@
fds_to_ignore.push_back(gUsapPoolEventFD);
}
+ if (gSystemServerSocketFd != -1) {
+ fds_to_close.push_back(gSystemServerSocketFd);
+ fds_to_ignore.push_back(gSystemServerSocketFd);
+ }
+
pid_t pid = ForkCommon(env, true,
fds_to_close,
- fds_to_ignore);
+ fds_to_ignore,
+ true);
if (pid == 0) {
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
permitted_capabilities, effective_capabilities,
@@ -1441,13 +1530,15 @@
* zygote in managed code.
* @param managed_session_socket_fds A list of anonymous session sockets that must be ignored by
* the FD hygiene code and automatically "closed" in the new USAP.
+ * @param is_priority_fork Controls the nice level assigned to the newly created process
* @return
*/
static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env,
jclass,
jint read_pipe_fd,
jint write_pipe_fd,
- jintArray managed_session_socket_fds) {
+ jintArray managed_session_socket_fds,
+ jboolean is_priority_fork) {
std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
fds_to_ignore(fds_to_close);
@@ -1461,6 +1552,9 @@
fds_to_close.push_back(gZygoteSocketFD);
fds_to_close.push_back(gUsapPoolEventFD);
fds_to_close.insert(fds_to_close.end(), session_socket_fds.begin(), session_socket_fds.end());
+ if (gSystemServerSocketFd != -1) {
+ fds_to_close.push_back(gSystemServerSocketFd);
+ }
fds_to_ignore.push_back(gZygoteSocketFD);
fds_to_ignore.push_back(gUsapPoolSocketFD);
@@ -1468,8 +1562,12 @@
fds_to_ignore.push_back(read_pipe_fd);
fds_to_ignore.push_back(write_pipe_fd);
fds_to_ignore.insert(fds_to_ignore.end(), session_socket_fds.begin(), session_socket_fds.end());
+ if (gSystemServerSocketFd != -1) {
+ fds_to_ignore.push_back(gSystemServerSocketFd);
+ }
- pid_t usap_pid = ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore);
+ pid_t usap_pid = ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore,
+ is_priority_fork == JNI_TRUE);
if (usap_pid != 0) {
++gUsapPoolCount;
@@ -1567,6 +1665,7 @@
ALOGE("Unable to fetch USAP pool socket file descriptor");
}
+ initUnsolSocketToSystemServer();
/*
* Security Initialization
*/
@@ -1706,6 +1805,48 @@
UnblockSignal(SIGTERM, fail_fn);
}
+static void com_android_internal_os_Zygote_nativeBoostUsapPriority(JNIEnv* env, jclass) {
+ setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
+}
+
+static jint com_android_internal_os_Zygote_nativeParseSigChld(JNIEnv* env, jclass, jbyteArray in,
+ jint length, jintArray out) {
+ if (length != sizeof(struct UnsolicitedZygoteMessageSigChld)) {
+ // Apparently it's not the message we are expecting.
+ return -1;
+ }
+ if (in == nullptr || out == nullptr) {
+ // Invalid parameter
+ jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
+ return -1;
+ }
+ ScopedByteArrayRO source(env, in);
+ if (source.size() < length) {
+ // Invalid parameter
+ jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
+ return -1;
+ }
+ const struct UnsolicitedZygoteMessageSigChld* msg =
+ reinterpret_cast<const struct UnsolicitedZygoteMessageSigChld*>(source.get());
+
+ switch (msg->header.type) {
+ case UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD: {
+ ScopedIntArrayRW buf(env, out);
+ if (buf.size() != 3) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
+ return UNSOLICITED_ZYGOTE_MESSAGE_TYPE_RESERVED;
+ }
+ buf[0] = msg->payload.pid;
+ buf[1] = msg->payload.uid;
+ buf[2] = msg->payload.status;
+ return 3;
+ }
+ default:
+ break;
+ }
+ return -1;
+}
+
static const JNINativeMethod gMethods[] = {
{ "nativeForkAndSpecialize",
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
@@ -1718,7 +1859,7 @@
(void *) com_android_internal_os_Zygote_nativePreApplicationInit },
{ "nativeInstallSeccompUidGidFilter", "(II)V",
(void *) com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter },
- { "nativeForkUsap", "(II[I)I",
+ { "nativeForkUsap", "(II[IZ)I",
(void *) com_android_internal_os_Zygote_nativeForkUsap },
{ "nativeSpecializeAppProcess",
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V",
@@ -1740,7 +1881,11 @@
{ "nativeBlockSigTerm", "()V",
(void* ) com_android_internal_os_Zygote_nativeBlockSigTerm },
{ "nativeUnblockSigTerm", "()V",
- (void* ) com_android_internal_os_Zygote_nativeUnblockSigTerm }
+ (void* ) com_android_internal_os_Zygote_nativeUnblockSigTerm },
+ { "nativeBoostUsapPriority", "()V",
+ (void* ) com_android_internal_os_Zygote_nativeBoostUsapPriority },
+ {"nativeParseSigChld", "([BI[I)I",
+ (void* ) com_android_internal_os_Zygote_nativeParseSigChld},
};
int register_com_android_internal_os_Zygote(JNIEnv* env) {
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index c8e901e..1b6d622 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -33,25 +33,23 @@
// Static whitelist of open paths that the zygote is allowed to keep open.
static const char* kPathWhitelist[] = {
- "/apex/com.android.conscrypt/javalib/conscrypt.jar",
- "/apex/com.android.ipsec/javalib/ike.jar",
- "/apex/com.android.media/javalib/updatable-media.jar",
- "/apex/com.android.sdkext/javalib/framework-sdkext.jar",
- "/apex/com.android.telephony/javalib/telephony-common.jar",
- "/apex/com.android.telephony/javalib/ims-common.jar",
- "/apex/com.android.tethering/javalib/framework-tethering.jar",
- "/dev/null",
- "/dev/socket/zygote",
- "/dev/socket/zygote_secondary",
- "/dev/socket/usap_pool_primary",
- "/dev/socket/usap_pool_secondary",
- "/dev/socket/webview_zygote",
- "/dev/socket/heapprofd",
- "/sys/kernel/debug/tracing/trace_marker",
- "/system/framework/framework-res.apk",
- "/dev/urandom",
- "/dev/ion",
- "/dev/dri/renderD129", // Fixes b/31172436
+ "/apex/com.android.conscrypt/javalib/conscrypt.jar",
+ "/apex/com.android.ipsec/javalib/ike.jar",
+ "/apex/com.android.media/javalib/updatable-media.jar",
+ "/apex/com.android.sdkext/javalib/framework-sdkextensions.jar",
+ "/apex/com.android.tethering/javalib/framework-tethering.jar",
+ "/dev/null",
+ "/dev/socket/zygote",
+ "/dev/socket/zygote_secondary",
+ "/dev/socket/usap_pool_primary",
+ "/dev/socket/usap_pool_secondary",
+ "/dev/socket/webview_zygote",
+ "/dev/socket/heapprofd",
+ "/sys/kernel/debug/tracing/trace_marker",
+ "/system/framework/framework-res.apk",
+ "/dev/urandom",
+ "/dev/ion",
+ "/dev/dri/renderD129", // Fixes b/31172436
};
static const char kFdPath[] = "/proc/self/fd";
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 2873379..7452f80 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -232,6 +232,8 @@
// Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
// ready now.
optional bool skip_not_ready_jobs = 1;
+ // Whether or not TimeController will use a non-wakeup alarm for delay constraints.
+ optional bool use_non_wakeup_alarm_for_delay = 2;
}
optional TimeController time_controller = 25;
diff --git a/core/proto/android/stats/otaupdate/updateengine_enums.proto b/core/proto/android/stats/otaupdate/updateengine_enums.proto
new file mode 100644
index 0000000..a6e9919
--- /dev/null
+++ b/core/proto/android/stats/otaupdate/updateengine_enums.proto
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.stats.otaupdate;
+
+// The payload type of an OTA update attempt on A/B devices.
+enum PayloadType {
+ FULL = 10000;
+ DELTA = 10001;
+}
+
+// The attempt result reported by the update engine for an OTA update.
+enum AttemptResult {
+ UPDATE_SUCCEEDED = 10000;
+ INTERNAL_ERROR = 10001;
+ PAYLOAD_DOWNLOAD_ERROR = 10002;
+ METADATA_MALFORMED = 10003;
+ OPERATION_MALFORMED = 10004;
+ OPERATION_EXECUTION_ERROR = 10005;
+ METADATA_VERIFICATION_FAILED = 10006;
+ PAYLOAD_VERIFICATION_FAILED = 10007;
+ VERIFICATION_FAILED = 10008;
+ POSTINSTALL_FAILED = 10009;
+ ABNORMAL_TERMINATION = 10010;
+ UPDATE_CANCELED = 10011;
+ UPDATE_SUCCEEDED_NOT_ACTIVE = 10012;
+}
+
+// The error code reported by the update engine after an OTA update attempt
+// on A/B devices. More details in system/update_engine/common/error_code.h
+enum ErrorCode {
+ SUCCESS = 10000;
+ ERROR = 10001;
+ FILESYSTEM_COPIER_ERROR = 10004;
+ POST_INSTALL_RUNNER_ERROR = 10005;
+ PAYLOAD_MISMATCHED_TYPE_ERROR = 10006;
+ INSTALL_DEVICE_OPEN_ERROR = 10007;
+ KERNEL_DEVICE_OPEN_ERROR = 10008;
+ DOWNLOAD_TRANSFER_ERROR = 10009;
+ PAYLOAD_HASH_MISMATCH_ERROR = 10010;
+ PAYLOAD_SIZE_MISMATCH_ERROR = 10011;
+ DOWNLOAD_PAYLOAD_VERIFICATION_ERROR = 10012;
+ DOWNLOAD_NEW_PARTITION_INFO_ERROR = 10013;
+ DOWNLOAD_WRITE_ERROR = 10014;
+ NEW_ROOTFS_VERIFICATION_ERROR = 10015;
+ SIGNED_DELTA_PAYLOAD_EXPECTED_ERROR = 10017;
+ DOWNLOAD_PAYLOAD_PUB_KEY_VERIFICATION_ERROR = 10018;
+ DOWNLOAD_STATE_INITIALIZATION_ERROR = 10020;
+ DOWNLOAD_INVALID_METADATA_MAGIC_STRING = 10021;
+ DOWNLOAD_SIGNATURE_MISSING_IN_MANIFEST = 10022;
+ DOWNLOAD_MANIFEST_PARSE_ERROR = 10023;
+ DOWNLOAD_METADATA_SIGNATURE_ERROR = 10024;
+ DOWNLOAD_METADATA_SIGNATURE_VERIFICATION_ERROR = 10025;
+ DOWNLOAD_METADATA_SIGNATURE_MISMATCH = 10026;
+ DOWNLOAD_OPERATION_HASH_VERIFICATION_ERROR = 10027;
+ DOWNLOAD_OPERATION_EXECUTION_ERROR = 10028;
+ DOWNLOAD_OPERATION_HASH_MISMATCH = 10029;
+ DOWNLOAD_INVALID_METADATA_SIZE = 10032;
+ DOWNLOAD_INVALID_METADATA_SIGNATURE = 10033;
+ DOWNLOAD_OPERATION_HASH_MISSING_ERROR = 10038;
+ DOWNLOAD_METADATA_SIGNATURE_MISSING_ERROR = 10039;
+ UNSUPPORTED_MAJOR_PAYLOAD_VERSION = 10044;
+ UNSUPPORTED_MINOR_PAYLOAD_VERSION = 10045;
+ FILESYSTEM_VERIFIER_ERROR = 10047;
+ USER_CANCELED = 10048;
+ PAYLOAD_TIMESTAMP_ERROR = 10051;
+ UPDATED_BUT_NOT_ACTIVE = 10052;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 31ac2bc..5c204ab 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -451,7 +451,6 @@
<protected-broadcast android:name="android.intent.action.internal_sim_state_changed" />
<protected-broadcast android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<protected-broadcast android:name="android.intent.action.PRECISE_CALL_STATE" />
- <protected-broadcast android:name="android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.intent.action.SUBSCRIPTION_PHONE_STATE" />
<protected-broadcast android:name="android.intent.action.USER_INFO_CHANGED" />
<protected-broadcast android:name="android.intent.action.USER_UNLOCKED" />
@@ -557,10 +556,12 @@
<protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" />
- <protected-broadcast android:name="com.android.phone.SIP_INCOMING_CALL" />
+ <protected-broadcast android:name="android.net.sip.action.SIP_INCOMING_CALL" />
<protected-broadcast android:name="com.android.phone.SIP_ADD_PHONE" />
- <protected-broadcast android:name="com.android.phone.SIP_REMOVE_PHONE" />
- <protected-broadcast android:name="com.android.phone.SIP_CALL_OPTION_CHANGED" />
+ <protected-broadcast android:name="android.net.sip.action.SIP_REMOVE_PROFILE" />
+ <protected-broadcast android:name="android.net.sip.action.SIP_SERVICE_UP" />
+ <protected-broadcast android:name="android.net.sip.action.SIP_CALL_OPTION_CHANGED" />
+ <protected-broadcast android:name="android.net.sip.action.START_SIP" />
<protected-broadcast android:name="android.bluetooth.adapter.action.BLE_ACL_CONNECTED" />
<protected-broadcast android:name="android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED" />
@@ -634,10 +635,6 @@
<protected-broadcast android:name="android.intent.action.DEVICE_CUSTOMIZATION_READY" />
- <!-- NETWORK_SET_TIME moved from com.android.phone to system server. It should ultimately be
- removed. -->
- <protected-broadcast android:name="android.telephony.action.NETWORK_SET_TIME" />
-
<!-- For tether entitlement recheck-->
<protected-broadcast
android:name="com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM" />
@@ -721,6 +718,11 @@
<!-- ====================================================================== -->
<eat-comment />
+ <!-- @SystemApi Allows accessing the messages on ICC
+ @hide Used internally. -->
+ <permission android:name="android.permission.ACCESS_MESSAGES_ON_ICC"
+ android:protectionLevel="signature|telephony" />
+
<!-- Used for runtime permissions related to user's SMS messages. -->
<permission-group android:name="android.permission-group.SMS"
android:icon="@drawable/perm_group_sms"
@@ -1778,6 +1780,11 @@
android:label="@string/permlab_preferredPaymentInfo"
android:protectionLevel="normal" />
+ <!-- @SystemApi Allows an internal user to use privileged SecureElement APIs.
+ @hide -->
+ <permission android:name="android.permission.SECURE_ELEMENT_PRIVILEGED"
+ android:protectionLevel="signature|privileged" />
+
<!-- @deprecated This permission used to allow too broad access to sensitive methods and all its
uses have been replaced by a more appropriate permission. Most uses have been replaced with
a NETWORK_STACK or NETWORK_SETTINGS check. Please look up the documentation of the
@@ -2058,8 +2065,10 @@
android:protectionLevel="signature|privileged" />
<!-- Allows read only access to precise phone state.
- @hide Pending API council approval -->
+ Allows reading of detailed information about phone state for special-use applications
+ such as dialers, carrier applications, or ims applications. -->
<permission android:name="android.permission.READ_PRECISE_PHONE_STATE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows read access to privileged phone state.
@@ -2524,17 +2533,17 @@
<permission android:name="android.permission.READ_WALLPAPER_INTERNAL"
android:protectionLevel="signature|privileged" />
- <!-- ============================================ -->
- <!-- Permissions for changing the system clock -->
- <!-- ============================================ -->
+ <!-- ===================================================== -->
+ <!-- Permissions for changing the system clock / time zone -->
+ <!-- ===================================================== -->
<eat-comment />
- <!-- Allows applications to set the system time.
- <p>Not for use by third-party applications. -->
+ <!-- Allows applications to set the system time directly.
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_TIME"
android:protectionLevel="signature|privileged" />
- <!-- Allows applications to set the system time zone.
+ <!-- Allows applications to set the system time zone directly.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.SET_TIME_ZONE"
@@ -2542,6 +2551,20 @@
android:description="@string/permdesc_setTimeZone"
android:protectionLevel="signature|privileged" />
+ <!-- Allows telephony to suggest the time / time zone.
+ <p>Not for use by third-party applications.
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @hide
+ -->
+ <permission android:name="android.permission.SUGGEST_PHONE_TIME_AND_ZONE"
+ android:protectionLevel="signature|telephony" />
+
+ <!-- Allows applications like settings to suggest the user's manually chosen time / time zone.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.SUGGEST_MANUAL_TIME_AND_ZONE"
+ android:protectionLevel="signature" />
+
<!-- ==================================================== -->
<!-- Permissions related to changing status bar -->
<!-- ==================================================== -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a404e2e..04d1eef 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2266,9 +2266,6 @@
<!-- Number of times to try again with the shorter interval, before backing
off until the normal polling interval. A value < 0 indicates infinite. -->
<integer name="config_ntpRetry">3</integer>
- <!-- If the time difference is greater than this threshold in milliseconds,
- then update the time. -->
- <integer name="config_ntpThreshold">5000</integer>
<!-- Timeout to wait for NTP server response in milliseconds. -->
<integer name="config_ntpTimeout">5000</integer>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4aa44fc..9bc0d96 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5393,6 +5393,10 @@
<!-- Description of media type: presentation file, such as PPT. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
<string name="mime_type_presentation_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> presentation</string>
+ <!-- Strings for Bluetooth service -->
+ <!-- toast message informing user that Bluetooth stays on after airplane mode is turned on. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_airplane_mode_toast">Bluetooth will stay on during airplane mode</string>
+
<!-- Strings for car -->
<!-- String displayed when loading a user in the car [CHAR LIMIT=30] -->
<string name="car_loading_profile">Loading</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2507787..cd43e9f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -489,7 +489,6 @@
<java-symbol type="integer" name="config_ntpPollingInterval" />
<java-symbol type="integer" name="config_ntpPollingIntervalShorter" />
<java-symbol type="integer" name="config_ntpRetry" />
- <java-symbol type="integer" name="config_ntpThreshold" />
<java-symbol type="integer" name="config_ntpTimeout" />
<java-symbol type="integer" name="config_shortPressOnPowerBehavior" />
<java-symbol type="integer" name="config_toastDefaultGravity" />
@@ -3796,6 +3795,9 @@
<java-symbol type="string" name="mime_type_presentation" />
<java-symbol type="string" name="mime_type_presentation_ext" />
+ <!-- For Bluetooth service -->
+ <java-symbol type="string" name="bluetooth_airplane_mode_toast" />
+
<!-- For high refresh rate displays -->
<java-symbol type="integer" name="config_defaultPeakRefreshRate" />
<java-symbol type="integer" name="config_defaultRefreshRateInZone" />
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java
index f0a8367..a296ca2 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java
@@ -16,6 +16,7 @@
package com.android.connectivitymanagertest;
+import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
import android.net.LinkAddress;
@@ -136,7 +137,7 @@
config.enterpriseConfig.setPhase2Method(phase2);
config.enterpriseConfig.setIdentity(identity);
config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity);
- config.enterpriseConfig.setCaCertificateAlias(caCert);
+ config.enterpriseConfig.setCaCertificateAliases(new String[] {caCert});
config.enterpriseConfig.setClientCertificateAlias(clientCert);
return config;
}
@@ -147,8 +148,12 @@
private static WifiConfiguration createGenericConfig(String ssid) {
WifiConfiguration config = new WifiConfiguration();
config.SSID = quotedString(ssid);
- config.setIpAssignment(IpAssignment.DHCP);
- config.setProxySettings(ProxySettings.NONE);
+
+ IpConfiguration ipConfiguration = config.getIpConfiguration();
+ ipConfiguration.setIpAssignment(IpAssignment.DHCP);
+ ipConfiguration.setProxySettings(ProxySettings.NONE);
+ config.setIpConfiguration(ipConfiguration);
+
return config;
}
@@ -237,6 +242,7 @@
throw new IllegalArgumentException();
}
+ IpConfiguration ipConfiguration = config.getIpConfiguration();
if (jsonConfig.has("ip")) {
StaticIpConfiguration staticIpConfig = new StaticIpConfiguration();
@@ -247,13 +253,14 @@
staticIpConfig.dnsServers.add(getInetAddress(jsonConfig.getString("dns1")));
staticIpConfig.dnsServers.add(getInetAddress(jsonConfig.getString("dns2")));
- config.setIpAssignment(IpAssignment.STATIC);
- config.setStaticIpConfiguration(staticIpConfig);
+ ipConfiguration.setIpAssignment(IpAssignment.STATIC);
+ ipConfiguration.setStaticIpConfiguration(staticIpConfig);
} else {
- config.setIpAssignment(IpAssignment.DHCP);
+ ipConfiguration.setIpAssignment(IpAssignment.DHCP);
}
+ ipConfiguration.setProxySettings(ProxySettings.NONE);
+ config.setIpConfiguration(ipConfiguration);
- config.setProxySettings(ProxySettings.NONE);
return config;
}
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
index 2989df8..5d42915 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
@@ -268,7 +268,7 @@
File snd_stat = new File (root_filepath + "tcp_snd");
int tx = BandwidthTestUtil.parseIntValueFromFile(snd_stat);
NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- stats.addValues(NetworkStats.IFACE_ALL, uid, NetworkStats.SET_DEFAULT,
+ stats.addEntry(NetworkStats.IFACE_ALL, uid, NetworkStats.SET_DEFAULT,
NetworkStats.TAG_NONE, rx, 0, tx, 0, 0);
return stats;
}
diff --git a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
index 707d7b3..239f971 100644
--- a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
+++ b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
@@ -54,7 +54,7 @@
recycle.txBytes = 150000;
recycle.txPackets = 1500;
recycle.operations = 0;
- mNetworkStats.addValues(recycle);
+ mNetworkStats.addEntry(recycle);
if (recycle.set == 1) {
uid++;
}
@@ -70,7 +70,7 @@
recycle.txBytes = 180000 * mSize;
recycle.txPackets = 1200 * mSize;
recycle.operations = 0;
- mNetworkStats.addValues(recycle);
+ mNetworkStats.addEntry(recycle);
}
}
diff --git a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
index 68b9b00..f4709ff 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
@@ -33,14 +33,15 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.support.test.uiautomator.UiDevice;
import android.test.InstrumentationTestCase;
import android.util.Log;
-import libcore.io.Streams;
-
import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.MockWebServer;
+import libcore.io.Streams;
+
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
@@ -63,6 +64,7 @@
private static final String TAG = "DownloadManagerBaseTest";
protected DownloadManager mDownloadManager = null;
private MockWebServer mServer = null;
+ private UiDevice mUiDevice = null;
protected String mFileType = "text/plain";
protected Context mContext = null;
protected MultipleDownloadsCompletedReceiver mReceiver = null;
@@ -234,6 +236,7 @@
@Override
public void setUp() throws Exception {
mContext = getInstrumentation().getContext();
+ mUiDevice = UiDevice.getInstance(getInstrumentation());
mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE);
mServer = new MockWebServer();
mServer.play();
@@ -512,7 +515,7 @@
Log.i(LOG_TAG, "Setting WiFi State to: " + enable);
WifiManager manager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
- manager.setWifiEnabled(enable);
+ mUiDevice.executeShellCommand("svc wifi " + (enable ? "enable" : "disable"));
String timeoutMessage = "Timed out waiting for Wifi to be "
+ (enable ? "enabled!" : "disabled!");
diff --git a/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java
index de6f8f7..750ffa1 100644
--- a/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java
@@ -22,7 +22,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
-import android.util.TimestampedValue;
+import android.os.TimestampedValue;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.java
new file mode 100644
index 0000000..b88c36f
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.app.timedetector;
+
+import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
+import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.os.TimestampedValue;
+
+import org.junit.Test;
+
+public class NetworkTimeSuggestionTest {
+
+ private static final TimestampedValue<Long> ARBITRARY_TIME =
+ new TimestampedValue<>(1111L, 2222L);
+
+ @Test
+ public void testEquals() {
+ NetworkTimeSuggestion one = new NetworkTimeSuggestion(ARBITRARY_TIME);
+ assertEquals(one, one);
+
+ NetworkTimeSuggestion two = new NetworkTimeSuggestion(ARBITRARY_TIME);
+ assertEquals(one, two);
+ assertEquals(two, one);
+
+ TimestampedValue<Long> differentTime = new TimestampedValue<>(
+ ARBITRARY_TIME.getReferenceTimeMillis() + 1,
+ ARBITRARY_TIME.getValue());
+ NetworkTimeSuggestion three = new NetworkTimeSuggestion(differentTime);
+ assertNotEquals(one, three);
+ assertNotEquals(three, one);
+
+ // DebugInfo must not be considered in equals().
+ one.addDebugInfo("Debug info 1");
+ two.addDebugInfo("Debug info 2");
+ assertEquals(one, two);
+ }
+
+ @Test
+ public void testParcelable() {
+ NetworkTimeSuggestion suggestion = new NetworkTimeSuggestion(ARBITRARY_TIME);
+ assertRoundTripParcelable(suggestion);
+
+ // DebugInfo should also be stored (but is not checked by equals()
+ suggestion.addDebugInfo("This is debug info");
+ NetworkTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
+ assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
+ }
+}
diff --git a/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java
index bee270e..ba29a97 100644
--- a/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java
@@ -22,7 +22,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
-import android.util.TimestampedValue;
+import android.os.TimestampedValue;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/net/NetworkKeyTest.java b/core/tests/coretests/src/android/net/NetworkKeyTest.java
index c6c0b46..b13bcd1 100644
--- a/core/tests/coretests/src/android/net/NetworkKeyTest.java
+++ b/core/tests/coretests/src/android/net/NetworkKeyTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.net.wifi.ScanResult;
@@ -107,7 +108,7 @@
@Test
public void createFromScanResult_nullSsid() {
- ScanResult scanResult = new ScanResult();
+ ScanResult scanResult = mock(ScanResult.class);
scanResult.BSSID = VALID_BSSID;
assertNull(NetworkKey.createFromScanResult(scanResult));
@@ -115,7 +116,7 @@
@Test
public void createFromScanResult_emptySsid() {
- ScanResult scanResult = new ScanResult();
+ ScanResult scanResult = mock(ScanResult.class);
scanResult.SSID = "";
scanResult.BSSID = VALID_BSSID;
@@ -124,7 +125,7 @@
@Test
public void createFromScanResult_noneSsid() {
- ScanResult scanResult = new ScanResult();
+ ScanResult scanResult = mock(ScanResult.class);
scanResult.SSID = WifiManager.UNKNOWN_SSID;
scanResult.BSSID = VALID_BSSID;
@@ -133,7 +134,7 @@
@Test
public void createFromScanResult_nullBssid() {
- ScanResult scanResult = new ScanResult();
+ ScanResult scanResult = mock(ScanResult.class);
scanResult.SSID = VALID_UNQUOTED_SSID;
assertNull(NetworkKey.createFromScanResult(scanResult));
@@ -141,7 +142,7 @@
@Test
public void createFromScanResult_emptyBssid() {
- ScanResult scanResult = new ScanResult();
+ ScanResult scanResult = mock(ScanResult.class);
scanResult.SSID = VALID_UNQUOTED_SSID;
scanResult.BSSID = "";
@@ -150,7 +151,7 @@
@Test
public void createFromScanResult_invalidBssid() {
- ScanResult scanResult = new ScanResult();
+ ScanResult scanResult = mock(ScanResult.class);
scanResult.SSID = VALID_UNQUOTED_SSID;
scanResult.BSSID = INVALID_BSSID;
@@ -159,7 +160,7 @@
@Test
public void createFromScanResult_validSsid() {
- ScanResult scanResult = new ScanResult();
+ ScanResult scanResult = mock(ScanResult.class);
scanResult.SSID = VALID_UNQUOTED_SSID;
scanResult.BSSID = VALID_BSSID;
diff --git a/core/tests/coretests/src/android/util/TimestampedValueTest.java b/core/tests/coretests/src/android/os/TimestampedValueTest.java
similarity index 98%
rename from core/tests/coretests/src/android/util/TimestampedValueTest.java
rename to core/tests/coretests/src/android/os/TimestampedValueTest.java
index 6fc2400..f36d9e6 100644
--- a/core/tests/coretests/src/android/util/TimestampedValueTest.java
+++ b/core/tests/coretests/src/android/os/TimestampedValueTest.java
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-package android.util;
+package android.os;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail;
-import android.os.Parcel;
-
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
diff --git a/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java
new file mode 100644
index 0000000..b605520
--- /dev/null
+++ b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.format;
+
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TimeMigrationUtilsTest {
+
+ private static final int ONE_DAY_IN_SECONDS = 24 * 60 * 60;
+
+ private Locale mDefaultLocale;
+ private TimeZone mDefaultTimeZone;
+
+ @Before
+ public void setUp() {
+ mDefaultLocale = Locale.getDefault();
+ mDefaultTimeZone = TimeZone.getDefault();
+ }
+
+ @After
+ public void tearDown() {
+ Locale.setDefault(mDefaultLocale);
+ TimeZone.setDefault(mDefaultTimeZone);
+ }
+
+ @Test
+ public void formatMillisWithFixedFormat_fixes2038Issue() {
+ Locale.setDefault(Locale.UK);
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
+ // The following cannot be represented properly using Time because they are outside of the
+ // supported range.
+ long y2038Issue1 = (((long) Integer.MIN_VALUE) - ONE_DAY_IN_SECONDS) * 1000L;
+ assertEquals(
+ "1901-12-12 20:45:52", TimeMigrationUtils.formatMillisWithFixedFormat(y2038Issue1));
+ long y2038Issue2 = (((long) Integer.MAX_VALUE) + ONE_DAY_IN_SECONDS) * 1000L;
+ assertEquals(
+ "2038-01-20 03:14:07", TimeMigrationUtils.formatMillisWithFixedFormat(y2038Issue2));
+ }
+
+ /**
+ * Compares TimeMigrationUtils.formatSimpleDateTime() with the code it is replacing.
+ */
+ @Test
+ public void formatMillisAsDateTime_matchesOldBehavior() {
+ // A selection of interesting locales.
+ Locale[] locales = new Locale[] {
+ Locale.US,
+ Locale.UK,
+ Locale.FRANCE,
+ Locale.JAPAN,
+ Locale.CHINA,
+ // Android supports RTL locales like arabic and arabic with latin numbers.
+ Locale.forLanguageTag("ar-AE"),
+ Locale.forLanguageTag("ar-AE-u-nu-latn"),
+ };
+ // A selection of interesting time zones.
+ String[] timeZoneIds = new String[] {
+ "UTC", "Europe/London", "America/New_York", "America/Los_Angeles", "Asia/Shanghai",
+ };
+ // Some arbitrary times when the two formatters should agree.
+ long[] timesMillis = new long[] {
+ System.currentTimeMillis(),
+ 0,
+ // The Time class only works in 32-bit range, the replacement works beyond that. To
+ // avoid messing around with offsets and complicating the test, below there are a
+ // day after / before the known limits.
+ (Integer.MIN_VALUE + ONE_DAY_IN_SECONDS) * 1000L,
+ (Integer.MAX_VALUE - ONE_DAY_IN_SECONDS) * 1000L,
+ };
+
+ for (Locale locale : locales) {
+ Locale.setDefault(locale);
+ for (String timeZoneId : timeZoneIds) {
+ TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);
+ TimeZone.setDefault(timeZone);
+ for (long timeMillis : timesMillis) {
+ Time time = new Time();
+ time.set(timeMillis);
+ String oldResult = time.format("%Y-%m-%d %H:%M:%S");
+ String newResult = TimeMigrationUtils.formatMillisWithFixedFormat(timeMillis);
+ assertEquals(
+ "locale=" + locale + ", timeZoneId=" + timeZoneId
+ + ", timeMillis=" + timeMillis,
+ oldResult, newResult);
+ }
+ }
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/util/StatsEventTest.java b/core/tests/coretests/src/android/util/StatsEventTest.java
new file mode 100644
index 0000000..ac25e27
--- /dev/null
+++ b/core/tests/coretests/src/android/util/StatsEventTest.java
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.os.SystemClock;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.Range;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Internal tests for {@link StatsEvent}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StatsEventTest {
+
+ @Test
+ public void testNoFields() {
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder().usePooledBuffer().build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ final int expectedAtomId = 0;
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(3);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ assertWithMessage("Third element is not errors type")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ERRORS);
+
+ final int errorMask = buffer.getInt();
+
+ assertWithMessage("ERROR_NO_ATOM_ID should be the only error in the error mask")
+ .that(errorMask).isEqualTo(StatsEvent.ERROR_NO_ATOM_ID);
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ @Test
+ public void testIntBooleanIntInt() {
+ final int expectedAtomId = 109;
+ final int field1 = 1;
+ final boolean field2 = true;
+ final int field3 = 3;
+ final int field4 = 4;
+
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(expectedAtomId)
+ .writeInt(field1)
+ .writeBoolean(field2)
+ .writeInt(field3)
+ .writeInt(field4)
+ .usePooledBuffer()
+ .build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(6);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ assertWithMessage("First field is not Int")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect field 1")
+ .that(buffer.getInt()).isEqualTo(field1);
+
+ assertWithMessage("Second field is not Boolean")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
+
+ assertWithMessage("Incorrect field 2")
+ .that(buffer.get()).isEqualTo(1);
+
+ assertWithMessage("Third field is not Int")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect field 3")
+ .that(buffer.getInt()).isEqualTo(field3);
+
+ assertWithMessage("Fourth field is not Int")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect field 4")
+ .that(buffer.getInt()).isEqualTo(field4);
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ @Test
+ public void testStringFloatByteArray() {
+ final int expectedAtomId = 109;
+ final String field1 = "Str 1";
+ final float field2 = 9.334f;
+ final byte[] field3 = new byte[] { 56, 23, 89, -120 };
+
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(expectedAtomId)
+ .writeString(field1)
+ .writeFloat(field2)
+ .writeByteArray(field3)
+ .usePooledBuffer()
+ .build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(5);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ assertWithMessage("First field is not String")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING);
+
+ final String field1Actual = getStringFromByteBuffer(buffer);
+ assertWithMessage("Incorrect field 1")
+ .that(field1Actual).isEqualTo(field1);
+
+ assertWithMessage("Second field is not Float")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT);
+
+ assertWithMessage("Incorrect field 2")
+ .that(buffer.getFloat()).isEqualTo(field2);
+
+ assertWithMessage("Third field is not byte array")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BYTE_ARRAY);
+
+ final byte[] field3Actual = getByteArrayFromByteBuffer(buffer);
+ assertWithMessage("Incorrect field 3")
+ .that(field3Actual).isEqualTo(field3);
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ @Test
+ public void testAttributionChainLong() {
+ final int expectedAtomId = 109;
+ final int[] uids = new int[] { 1, 2, 3, 4, 5 };
+ final String[] tags = new String[] { "1", "2", "3", "4", "5" };
+ final long field2 = -230909823L;
+
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(expectedAtomId)
+ .writeAttributionChain(uids, tags)
+ .writeLong(field2)
+ .usePooledBuffer()
+ .build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(4);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ assertWithMessage("First field is not Attribution Chain")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_ATTRIBUTION_CHAIN);
+
+ assertWithMessage("Incorrect number of attribution nodes")
+ .that(buffer.get()).isEqualTo((byte) uids.length);
+
+ for (int i = 0; i < tags.length; i++) {
+ assertWithMessage("Incorrect uid in Attribution Chain")
+ .that(buffer.getInt()).isEqualTo(uids[i]);
+
+ final String tag = getStringFromByteBuffer(buffer);
+ assertWithMessage("Incorrect tag in Attribution Chain")
+ .that(tag).isEqualTo(tags[i]);
+ }
+
+ assertWithMessage("Second field is not Long")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect field 2")
+ .that(buffer.getLong()).isEqualTo(field2);
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ @Test
+ public void testKeyValuePairs() {
+ final int expectedAtomId = 109;
+ final SparseIntArray intMap = new SparseIntArray();
+ final SparseLongArray longMap = new SparseLongArray();
+ final SparseArray<String> stringMap = new SparseArray<>();
+ final SparseArray<Float> floatMap = new SparseArray<>();
+ intMap.put(1, -1);
+ intMap.put(2, -2);
+ stringMap.put(3, "abc");
+ stringMap.put(4, "2h");
+ floatMap.put(9, -234.344f);
+
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(expectedAtomId)
+ .writeKeyValuePairs(intMap, longMap, stringMap, floatMap)
+ .usePooledBuffer()
+ .build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(3);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ assertWithMessage("First field is not KeyValuePairs")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_KEY_VALUE_PAIRS);
+
+ assertWithMessage("Incorrect number of key value pairs")
+ .that(buffer.get()).isEqualTo(
+ (byte) (intMap.size() + longMap.size() + stringMap.size()
+ + floatMap.size()));
+
+ for (int i = 0; i < intMap.size(); i++) {
+ assertWithMessage("Incorrect key in intMap")
+ .that(buffer.getInt()).isEqualTo(intMap.keyAt(i));
+ assertWithMessage("The type id of the value should be TYPE_INT in intMap")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+ assertWithMessage("Incorrect value in intMap")
+ .that(buffer.getInt()).isEqualTo(intMap.valueAt(i));
+ }
+
+ for (int i = 0; i < longMap.size(); i++) {
+ assertWithMessage("Incorrect key in longMap")
+ .that(buffer.getInt()).isEqualTo(longMap.keyAt(i));
+ assertWithMessage("The type id of the value should be TYPE_LONG in longMap")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+ assertWithMessage("Incorrect value in longMap")
+ .that(buffer.getLong()).isEqualTo(longMap.valueAt(i));
+ }
+
+ for (int i = 0; i < stringMap.size(); i++) {
+ assertWithMessage("Incorrect key in stringMap")
+ .that(buffer.getInt()).isEqualTo(stringMap.keyAt(i));
+ assertWithMessage("The type id of the value should be TYPE_STRING in stringMap")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_STRING);
+ final String value = getStringFromByteBuffer(buffer);
+ assertWithMessage("Incorrect value in stringMap")
+ .that(value).isEqualTo(stringMap.valueAt(i));
+ }
+
+ for (int i = 0; i < floatMap.size(); i++) {
+ assertWithMessage("Incorrect key in floatMap")
+ .that(buffer.getInt()).isEqualTo(floatMap.keyAt(i));
+ assertWithMessage("The type id of the value should be TYPE_FLOAT in floatMap")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_FLOAT);
+ assertWithMessage("Incorrect value in floatMap")
+ .that(buffer.getFloat()).isEqualTo(floatMap.valueAt(i));
+ }
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ @Test
+ public void testSingleAnnotations() {
+ final int expectedAtomId = 109;
+ final int field1 = 1;
+ final byte field1AnnotationId = 45;
+ final boolean field1AnnotationValue = false;
+ final boolean field2 = true;
+ final byte field2AnnotationId = 1;
+ final int field2AnnotationValue = 23;
+
+ final long minTimestamp = SystemClock.elapsedRealtimeNanos();
+ final StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(expectedAtomId)
+ .writeInt(field1)
+ .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue)
+ .writeBoolean(field2)
+ .addIntAnnotation(field2AnnotationId, field2AnnotationValue)
+ .usePooledBuffer()
+ .build();
+ final long maxTimestamp = SystemClock.elapsedRealtimeNanos();
+
+ assertThat(statsEvent.getAtomId()).isEqualTo(expectedAtomId);
+
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(statsEvent.getBytes()).order(ByteOrder.LITTLE_ENDIAN);
+
+ assertWithMessage("Root element in buffer is not TYPE_OBJECT")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_OBJECT);
+
+ assertWithMessage("Incorrect number of elements in root object")
+ .that(buffer.get()).isEqualTo(4);
+
+ assertWithMessage("First element is not timestamp")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_LONG);
+
+ assertWithMessage("Incorrect timestamp")
+ .that(buffer.getLong()).isIn(Range.closed(minTimestamp, maxTimestamp));
+
+ assertWithMessage("Second element is not atom id")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+
+ assertWithMessage("Incorrect atom id")
+ .that(buffer.getInt()).isEqualTo(expectedAtomId);
+
+ final byte field1Header = buffer.get();
+ final int field1AnnotationValueCount = field1Header >> 4;
+ final byte field1Type = (byte) (field1Header & 0x0F);
+ assertWithMessage("First field is not Int")
+ .that(field1Type).isEqualTo(StatsEvent.TYPE_INT);
+ assertWithMessage("First field annotation count is wrong")
+ .that(field1AnnotationValueCount).isEqualTo(1);
+ assertWithMessage("Incorrect field 1")
+ .that(buffer.getInt()).isEqualTo(field1);
+ assertWithMessage("First field's annotation id is wrong")
+ .that(buffer.get()).isEqualTo(field1AnnotationId);
+ assertWithMessage("First field's annotation type is wrong")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_BOOLEAN);
+ assertWithMessage("First field's annotation value is wrong")
+ .that(buffer.get()).isEqualTo(field1AnnotationValue ? 1 : 0);
+
+ final byte field2Header = buffer.get();
+ final int field2AnnotationValueCount = field2Header >> 4;
+ final byte field2Type = (byte) (field2Header & 0x0F);
+ assertWithMessage("Second field is not boolean")
+ .that(field2Type).isEqualTo(StatsEvent.TYPE_BOOLEAN);
+ assertWithMessage("Second field annotation count is wrong")
+ .that(field2AnnotationValueCount).isEqualTo(1);
+ assertWithMessage("Incorrect field 2")
+ .that(buffer.get()).isEqualTo(field2 ? 1 : 0);
+ assertWithMessage("Second field's annotation id is wrong")
+ .that(buffer.get()).isEqualTo(field2AnnotationId);
+ assertWithMessage("Second field's annotation type is wrong")
+ .that(buffer.get()).isEqualTo(StatsEvent.TYPE_INT);
+ assertWithMessage("Second field's annotation value is wrong")
+ .that(buffer.getInt()).isEqualTo(field2AnnotationValue);
+
+ assertThat(statsEvent.getNumBytes()).isEqualTo(buffer.position());
+
+ statsEvent.release();
+ }
+
+ private static byte[] getByteArrayFromByteBuffer(final ByteBuffer buffer) {
+ final int numBytes = buffer.getInt();
+ byte[] bytes = new byte[numBytes];
+ buffer.get(bytes);
+ return bytes;
+ }
+
+ private static String getStringFromByteBuffer(final ByteBuffer buffer) {
+ final byte[] bytes = getByteArrayFromByteBuffer(buffer);
+ return new String(bytes, UTF_8);
+ }
+}
diff --git a/core/tests/overlaytests/host/Android.bp b/core/tests/overlaytests/host/Android.bp
new file mode 100644
index 0000000..a2fcef5
--- /dev/null
+++ b/core/tests/overlaytests/host/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+java_test_host {
+ name: "OverlayHostTests",
+ srcs: ["src/**/*.java"],
+ libs: ["tradefed"],
+ test_suites: ["general-tests"],
+ target_required: [
+ "OverlayHostTests_NonPlatformSignatureOverlay",
+ "OverlayHostTests_PlatformSignatureStaticOverlay",
+ "OverlayHostTests_PlatformSignatureOverlay",
+ "OverlayHostTests_UpdateOverlay",
+ "OverlayHostTests_FrameworkOverlayV1",
+ "OverlayHostTests_FrameworkOverlayV2",
+ "OverlayHostTests_AppOverlayV1",
+ "OverlayHostTests_AppOverlayV2",
+ ],
+}
diff --git a/core/tests/overlaytests/host/Android.mk b/core/tests/overlaytests/host/Android.mk
index e7348d5..d58d939 100644
--- a/core/tests/overlaytests/host/Android.mk
+++ b/core/tests/overlaytests/host/Android.mk
@@ -14,23 +14,6 @@
LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := OverlayHostTests
-LOCAL_JAVA_LIBRARIES := tradefed
-LOCAL_COMPATIBILITY_SUITE := general-tests
-LOCAL_TARGET_REQUIRED_MODULES := \
- OverlayHostTests_NonPlatformSignatureOverlay \
- OverlayHostTests_PlatformSignatureStaticOverlay \
- OverlayHostTests_PlatformSignatureOverlay \
- OverlayHostTests_UpdateOverlay \
- OverlayHostTests_FrameworkOverlayV1 \
- OverlayHostTests_FrameworkOverlayV2 \
- OverlayHostTests_AppOverlayV1 \
- OverlayHostTests_AppOverlayV2
-include $(BUILD_HOST_JAVA_LIBRARY)
-
# Include to build test-apps.
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/utiltests/src/com/android/internal/util/ConnectivityUtilTest.java b/core/tests/utiltests/src/com/android/internal/util/ConnectivityUtilTest.java
new file mode 100644
index 0000000..5564712
--- /dev/null
+++ b/core/tests/utiltests/src/com/android/internal/util/ConnectivityUtilTest.java
@@ -0,0 +1,286 @@
+/*
+ * 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.internal.util;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.location.LocationManager;
+import android.os.Binder;
+import android.os.Build;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.HashMap;
+
+/** Unit tests for {@link ConnectivityUtil}. */
+public class ConnectivityUtilTest {
+
+ public static final String TAG = "ConnectivityUtilTest";
+
+ // Mock objects for testing
+ @Mock private Context mMockContext;
+ @Mock private PackageManager mMockPkgMgr;
+ @Mock private ApplicationInfo mMockApplInfo;
+ @Mock private AppOpsManager mMockAppOps;
+ @Mock private UserManager mMockUserManager;
+ @Mock private LocationManager mLocationManager;
+
+ private static final String TEST_PKG_NAME = "com.google.somePackage";
+ private static final String TEST_FEATURE_ID = "com.google.someFeature";
+ private static final int MANAGED_PROFILE_UID = 1100000;
+ private static final int OTHER_USER_UID = 1200000;
+
+ private final String mInteractAcrossUsersFullPermission =
+ "android.permission.INTERACT_ACROSS_USERS_FULL";
+ private final String mManifestStringCoarse =
+ Manifest.permission.ACCESS_COARSE_LOCATION;
+ private final String mManifestStringFine =
+ Manifest.permission.ACCESS_FINE_LOCATION;
+
+ // Test variables
+ private int mWifiScanAllowApps;
+ private int mUid;
+ private int mCoarseLocationPermission;
+ private int mAllowCoarseLocationApps;
+ private int mFineLocationPermission;
+ private int mAllowFineLocationApps;
+ private int mCurrentUser;
+ private boolean mIsLocationEnabled;
+ private boolean mThrowSecurityException;
+ private Answer<Integer> mReturnPermission;
+ private HashMap<String, Integer> mPermissionsList = new HashMap<String, Integer>();
+
+ private class TestConnectivityUtil extends ConnectivityUtil {
+
+ TestConnectivityUtil(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected int getCurrentUser() {
+ return mCurrentUser;
+ }
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ initTestVars();
+ }
+
+ private void setupMocks() throws Exception {
+ when(mMockPkgMgr.getApplicationInfoAsUser(eq(TEST_PKG_NAME), eq(0), any()))
+ .thenReturn(mMockApplInfo);
+ when(mMockContext.getPackageManager()).thenReturn(mMockPkgMgr);
+ when(mMockAppOps.noteOp(AppOpsManager.OPSTR_WIFI_SCAN, mUid, TEST_PKG_NAME))
+ .thenReturn(mWifiScanAllowApps);
+ when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_COARSE_LOCATION), eq(mUid),
+ eq(TEST_PKG_NAME)))
+ .thenReturn(mAllowCoarseLocationApps);
+ when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_FINE_LOCATION), eq(mUid),
+ eq(TEST_PKG_NAME)))
+ .thenReturn(mAllowFineLocationApps);
+ if (mThrowSecurityException) {
+ doThrow(new SecurityException("Package " + TEST_PKG_NAME + " doesn't belong"
+ + " to application bound to user " + mUid))
+ .when(mMockAppOps).checkPackage(mUid, TEST_PKG_NAME);
+ }
+ when(mMockContext.getSystemService(Context.APP_OPS_SERVICE))
+ .thenReturn(mMockAppOps);
+ when(mMockContext.getSystemService(Context.USER_SERVICE))
+ .thenReturn(mMockUserManager);
+ when(mMockContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager);
+ }
+
+ private void setupTestCase() throws Exception {
+ setupMocks();
+ setupMockInterface();
+ }
+
+ private void initTestVars() {
+ mPermissionsList.clear();
+ mReturnPermission = createPermissionAnswer();
+ mWifiScanAllowApps = AppOpsManager.MODE_ERRORED;
+ mUid = OTHER_USER_UID;
+ mThrowSecurityException = true;
+ mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.M;
+ mIsLocationEnabled = false;
+ mCurrentUser = UserHandle.USER_SYSTEM;
+ mCoarseLocationPermission = PackageManager.PERMISSION_DENIED;
+ mFineLocationPermission = PackageManager.PERMISSION_DENIED;
+ mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED;
+ mAllowFineLocationApps = AppOpsManager.MODE_ERRORED;
+ }
+
+ private void setupMockInterface() {
+ Binder.restoreCallingIdentity((((long) mUid) << 32) | Binder.getCallingPid());
+ doAnswer(mReturnPermission).when(mMockContext).checkPermission(
+ anyString(), anyInt(), anyInt());
+ when(mMockUserManager.isSameProfileGroup(UserHandle.SYSTEM.getIdentifier(),
+ UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID).getIdentifier()))
+ .thenReturn(true);
+ when(mMockContext.checkPermission(mManifestStringCoarse, -1, mUid))
+ .thenReturn(mCoarseLocationPermission);
+ when(mMockContext.checkPermission(mManifestStringFine, -1, mUid))
+ .thenReturn(mFineLocationPermission);
+ when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(mIsLocationEnabled);
+ }
+
+ private Answer<Integer> createPermissionAnswer() {
+ return new Answer<Integer>() {
+ @Override
+ public Integer answer(InvocationOnMock invocation) {
+ int myUid = (int) invocation.getArguments()[1];
+ String myPermission = (String) invocation.getArguments()[0];
+ mPermissionsList.get(myPermission);
+ if (mPermissionsList.containsKey(myPermission)) {
+ int uid = mPermissionsList.get(myPermission);
+ if (myUid == uid) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
+ }
+ return PackageManager.PERMISSION_DENIED;
+ }
+ };
+ }
+
+ @Test
+ public void testEnforceLocationPermission_HasAllPermissions_BeforeQ() throws Exception {
+ mIsLocationEnabled = true;
+ mThrowSecurityException = false;
+ mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED;
+ mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED;
+ mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
+ mUid = mCurrentUser;
+ setupTestCase();
+ new TestConnectivityUtil(mMockContext)
+ .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
+ }
+
+ @Test
+ public void testEnforceLocationPermission_HasAllPermissions_AfterQ() throws Exception {
+ mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.Q;
+ mIsLocationEnabled = true;
+ mThrowSecurityException = false;
+ mUid = mCurrentUser;
+ mFineLocationPermission = PackageManager.PERMISSION_GRANTED;
+ mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED;
+ mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
+ setupTestCase();
+ new TestConnectivityUtil(mMockContext)
+ .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
+ }
+
+ @Test
+ public void testEnforceLocationPermission_PkgNameAndUidMismatch() throws Exception {
+ mThrowSecurityException = true;
+ mIsLocationEnabled = true;
+ mFineLocationPermission = PackageManager.PERMISSION_GRANTED;
+ mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED;
+ mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
+ setupTestCase();
+
+ assertThrows(SecurityException.class,
+ () -> new TestConnectivityUtil(mMockContext)
+ .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+ }
+
+ @Test
+ public void testenforceCanAccessScanResults_UserOrProfileNotCurrent() throws Exception {
+ mIsLocationEnabled = true;
+ mThrowSecurityException = false;
+ mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED;
+ mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED;
+ mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
+ setupTestCase();
+
+ assertThrows(SecurityException.class,
+ () -> new TestConnectivityUtil(mMockContext)
+ .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+ }
+
+ @Test
+ public void testenforceCanAccessScanResults_NoCoarseLocationPermission() throws Exception {
+ mThrowSecurityException = false;
+ mIsLocationEnabled = true;
+ setupTestCase();
+ assertThrows(SecurityException.class,
+ () -> new TestConnectivityUtil(mMockContext)
+ .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+ }
+
+ @Test
+ public void testenforceCanAccessScanResults_NoFineLocationPermission() throws Exception {
+ mThrowSecurityException = false;
+ mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.Q;
+ mIsLocationEnabled = true;
+ mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED;
+ mAllowFineLocationApps = AppOpsManager.MODE_ERRORED;
+ mUid = MANAGED_PROFILE_UID;
+ setupTestCase();
+
+ assertThrows(SecurityException.class,
+ () -> new TestConnectivityUtil(mMockContext)
+ .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+ verify(mMockAppOps, never()).noteOp(anyInt(), anyInt(), anyString());
+ }
+
+ @Test
+ public void testenforceCanAccessScanResults_LocationModeDisabled() throws Exception {
+ mThrowSecurityException = false;
+ mUid = MANAGED_PROFILE_UID;
+ mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
+ mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid);
+ mIsLocationEnabled = false;
+
+ setupTestCase();
+
+ assertThrows(SecurityException.class,
+ () -> new TestConnectivityUtil(mMockContext)
+ .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+ }
+
+ private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
+ try {
+ r.run();
+ Assert.fail("Expected " + exceptionClass + " to be thrown.");
+ } catch (Exception exception) {
+ assertTrue(exceptionClass.isInstance(exception));
+ }
+ }
+}
diff --git a/core/xsd/permission.xsd b/core/xsd/permission.xsd
index 9520db7..cc01a31 100644
--- a/core/xsd/permission.xsd
+++ b/core/xsd/permission.xsd
@@ -126,12 +126,12 @@
</xs:complexType>
<xs:complexType name="privapp-permissions">
<xs:sequence>
- <xs:element name="permission" maxOccurs="unbounded">
+ <xs:element name="permission" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
</xs:element>
- <xs:element name="deny-permission" maxOccurs="unbounded">
+ <xs:element name="deny-permission" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
@@ -141,12 +141,12 @@
</xs:complexType>
<xs:complexType name="oem-permissions">
<xs:sequence>
- <xs:element name="permission" maxOccurs="unbounded">
+ <xs:element name="permission" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
</xs:element>
- <xs:element name="deny-permission" maxOccurs="unbounded">
+ <xs:element name="deny-permission" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 4493f3a..0d12e1f 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -43,7 +43,7 @@
prebuilt_etc {
name: "privapp_whitelist_com.android.carrierconfig",
- product_specific: true,
+ system_ext_specific: true,
sub_dir: "permissions",
src: "com.android.carrierconfig.xml",
filename_from_src: true,
@@ -67,7 +67,7 @@
prebuilt_etc {
name: "privapp_whitelist_com.android.emergency",
- product_specific: true,
+ system_ext_specific: true,
sub_dir: "permissions",
src: "com.android.emergency.xml",
filename_from_src: true,
@@ -82,7 +82,7 @@
prebuilt_etc {
name: "privapp_whitelist_com.android.launcher3",
- product_specific: true,
+ system_ext_specific: true,
sub_dir: "permissions",
src: "com.android.launcher3.xml",
filename_from_src: true,
@@ -90,7 +90,7 @@
prebuilt_etc {
name: "privapp_whitelist_com.android.provision",
- product_specific: true,
+ system_ext_specific: true,
sub_dir: "permissions",
src: "com.android.provision.xml",
filename_from_src: true,
@@ -98,7 +98,7 @@
prebuilt_etc {
name: "privapp_whitelist_com.android.settings",
- product_specific: true,
+ system_ext_specific: true,
sub_dir: "permissions",
src: "com.android.settings.xml",
filename_from_src: true,
@@ -114,7 +114,7 @@
prebuilt_etc {
name: "privapp_whitelist_com.android.storagemanager",
- product_specific: true,
+ system_ext_specific: true,
sub_dir: "permissions",
src: "com.android.storagemanager.xml",
filename_from_src: true,
@@ -122,7 +122,7 @@
prebuilt_etc {
name: "privapp_whitelist_com.android.systemui",
- product_specific: true,
+ system_ext_specific: true,
sub_dir: "permissions",
src: "com.android.systemui.xml",
filename_from_src: true,
diff --git a/data/etc/CleanSpec.mk b/data/etc/CleanSpec.mk
new file mode 100644
index 0000000..783a7ed
--- /dev/null
+++ b/data/etc/CleanSpec.mk
@@ -0,0 +1,60 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# *****************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
+# *****************************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.android.carrierconfig.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.carrierconfig.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.android.emergency.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.emergency.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.android.provision.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.provision.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.android.settings.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.settings.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.android.launcher3.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.launcher3.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.android.systemui.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.systemui.xml)
+# ******************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
+# ******************************************************************
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index ea66ee3..70d4678 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -1 +1 @@
-per-file privapp-permissions-platform.xml = hackbod@android.com, jsharkey@android.com, svetoslavganov@google.com, toddke@google.com, yamasani@google.com, cbrubaker@google.com, jeffv@google.com, moltmann@google.com
+per-file privapp-permissions-platform.xml = hackbod@android.com, jsharkey@android.com, svetoslavganov@google.com, toddke@google.com, yamasani@google.com, cbrubaker@google.com, jeffv@google.com, moltmann@google.com, lorenzo@google.com
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index 9272ea5..7faf4cd 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -126,5 +126,5 @@
sub_dir: "permissions",
src: "com.android.car.developeroptions.xml",
filename_from_src: true,
- product_specific: true,
+ system_ext_specific: true,
}
diff --git a/data/etc/car/CleanSpec.mk b/data/etc/car/CleanSpec.mk
new file mode 100644
index 0000000..18f7d34
--- /dev/null
+++ b/data/etc/car/CleanSpec.mk
@@ -0,0 +1,50 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# *****************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
+# *****************************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/etc/permissions/com.android.car.developeroptions.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/etc/permissions/com.android.car.developeroptions.xml)
+# ******************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
+# ******************************************************************
diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml
index ba877f8..cc1ce9b 100644
--- a/data/etc/com.android.settings.xml
+++ b/data/etc/com.android.settings.xml
@@ -42,8 +42,8 @@
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.READ_SEARCH_INDEXABLES"/>
<permission name="android.permission.REBOOT"/>
- <permission name="android.permission.SET_TIME"/>
<permission name="android.permission.STATUS_BAR"/>
+ <permission name="android.permission.SUGGEST_MANUAL_TIME_AND_ZONE"/>
<permission name="android.permission.TETHER_PRIVILEGED"/>
<permission name="android.permission.USE_RESERVED_DISK"/>
<permission name="android.permission.USER_ACTIVITY"/>
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index a305d48..1d73567 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -22,7 +22,6 @@
<permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
<permission name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"/>
<permission name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
- <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
<permission name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS"/>
<permission name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"/>
<permission name="android.permission.CONTROL_VPN"/>
@@ -38,6 +37,7 @@
<permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
<permission name="android.permission.MODIFY_PHONE_STATE"/>
<permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
+ <permission name="android.permission.OBSERVE_NETWORK_POLICY"/>
<permission name="android.permission.OVERRIDE_WIFI_CONFIG"/>
<permission name="android.permission.READ_DREAM_STATE"/>
<permission name="android.permission.READ_FRAME_BUFFER"/>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c909734..eec2072 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -67,7 +67,6 @@
<privapp-permissions package="com.android.managedprovisioning">
<permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
<permission name="android.permission.CHANGE_CONFIGURATION"/>
- <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
<permission name="android.permission.CRYPT_KEEPER"/>
<permission name="android.permission.DELETE_PACKAGES"/>
<permission name="android.permission.INSTALL_PACKAGES"/>
@@ -155,12 +154,12 @@
<permission name="android.permission.REGISTER_CALL_PROVIDER"/>
<permission name="android.permission.REGISTER_SIM_SUBSCRIPTION"/>
<permission name="android.permission.SEND_RESPOND_VIA_MESSAGE"/>
- <permission name="android.permission.SET_TIME"/>
<permission name="android.permission.SET_TIME_ZONE"/>
<permission name="android.permission.SHUTDOWN"/>
<permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
<permission name="android.permission.STATUS_BAR"/>
<permission name="android.permission.STOP_APP_SWITCHES"/>
+ <permission name="android.permission.SUGGEST_PHONE_TIME_AND_ZONE"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
<permission name="android.permission.UPDATE_DEVICE_STATS"/>
<permission name="android.permission.UPDATE_LOCK"/>
@@ -238,7 +237,9 @@
<permission name="android.permission.MANAGE_USB"/>
<permission name="android.permission.MODIFY_PHONE_STATE"/>
<permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
+ <permission name="android.permission.TETHER_PRIVILEGED"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+ <permission name="android.permission.UPDATE_DEVICE_STATS"/>
</privapp-permissions>
<privapp-permissions package="com.android.server.telecom">
@@ -360,7 +361,6 @@
</privapp-permissions>
<privapp-permissions package="com.android.vpndialogs">
- <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
<permission name="android.permission.CONTROL_VPN"/>
</privapp-permissions>
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 6e7f286..bee8d5e 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -21,7 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas.VertexMode;
import android.graphics.text.MeasuredText;
import android.text.GraphicsOperations;
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 4471017..a8b7e1f 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -21,8 +21,8 @@
import android.annotation.ColorLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.ResourcesImpl;
import android.hardware.HardwareBuffer;
import android.os.Build;
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 5623a8a..bad487b 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Trace;
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index 629d8c1..34eba97 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -15,7 +15,7 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.os.Build;
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 198d1e7..edf53c4 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -17,7 +17,7 @@
package android.graphics;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Shader used to draw a bitmap as a texture. The bitmap can be repeated or
diff --git a/graphics/java/android/graphics/Camera.java b/graphics/java/android/graphics/Camera.java
index cbd4ead..80a3740 100644
--- a/graphics/java/android/graphics/Camera.java
+++ b/graphics/java/android/graphics/Camera.java
@@ -16,7 +16,7 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* A camera instance can be used to compute 3D transformations and
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 5648b85..d034728 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -22,7 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.text.MeasuredText;
import android.os.Build;
diff --git a/graphics/java/android/graphics/CanvasProperty.java b/graphics/java/android/graphics/CanvasProperty.java
index 1275e08..4263772c 100644
--- a/graphics/java/android/graphics/CanvasProperty.java
+++ b/graphics/java/android/graphics/CanvasProperty.java
@@ -16,7 +16,8 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import com.android.internal.util.VirtualRefBasePtr;
/**
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index 0f7980c..a8b18a9 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* A color filter that transforms colors through a 4x5 color matrix. This filter
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 5af0da8..2548920 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -17,7 +17,7 @@
package android.graphics;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.graphics.fonts.FontVariationAxis;
import android.text.TextUtils;
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 21cc375..c146bbd 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -16,7 +16,7 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.fonts.FontVariationAxis;
import android.text.FontConfig;
import android.util.Xml;
diff --git a/graphics/java/android/graphics/GraphicBuffer.java b/graphics/java/android/graphics/GraphicBuffer.java
index 3b1fc70..99fa5ee 100644
--- a/graphics/java/android/graphics/GraphicBuffer.java
+++ b/graphics/java/android/graphics/GraphicBuffer.java
@@ -16,7 +16,7 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 2d5babc..dbdb697 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -28,8 +28,8 @@
import android.annotation.Nullable;
import android.annotation.Px;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index 62a890f..221dfa1 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -22,7 +22,7 @@
package android.graphics;
import android.annotation.ColorInt;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* A color filter that can be used to simulate simple lighting effects.
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 12e63c0..3f3ad96 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -20,7 +20,7 @@
import android.annotation.ColorLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
public class LinearGradient extends Shader {
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index 22b6401..cf914c2 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -16,7 +16,7 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
diff --git a/graphics/java/android/graphics/Movie.java b/graphics/java/android/graphics/Movie.java
index 6f030ff..4b3924f 100644
--- a/graphics/java/android/graphics/Movie.java
+++ b/graphics/java/android/graphics/Movie.java
@@ -16,7 +16,7 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.os.Build;
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index c4c1eac..ff32393 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -16,7 +16,7 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The NinePatch class permits drawing a bitmap in nine or more sections.
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 1fc056c..91a60c3 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -19,7 +19,7 @@
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.drawable.Drawable;
import java.lang.annotation.Retention;
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index b7316ab..dcb669d 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -24,7 +24,7 @@
import android.annotation.Nullable;
import android.annotation.Px;
import android.annotation.Size;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.fonts.FontVariationAxis;
import android.os.Build;
import android.os.LocaleList;
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 7282d52..1362fd8 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index 8d12cbf..390d3d4 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -17,7 +17,7 @@
package android.graphics;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.InputStream;
import java.io.OutputStream;
diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java
index bc1f66f..1275cb9 100644
--- a/graphics/java/android/graphics/PorterDuff.java
+++ b/graphics/java/android/graphics/PorterDuff.java
@@ -16,7 +16,7 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* <p>This class contains the list of alpha compositing and blending modes
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index cc2d3a8..50ecb62 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -18,7 +18,7 @@
import android.annotation.ColorInt;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* A color filter that can be used to tint the source pixels using a single
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index acbe3da..96b7b9a 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -20,7 +20,7 @@
import android.annotation.ColorLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
public class RadialGradient extends Shader {
@UnsupportedAppUsage
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index d47f682..270725a 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -19,7 +19,7 @@
import android.annotation.CheckResult;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java
index ec7f7a0..d8d9641 100644
--- a/graphics/java/android/graphics/Region.java
+++ b/graphics/java/android/graphics/Region.java
@@ -17,7 +17,7 @@
package android.graphics;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Pools.SynchronizedPool;
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 3050d1d..5335aa4 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -20,7 +20,7 @@
import android.annotation.ColorLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import libcore.util.NativeAllocationRegistry;
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 99f440d..697daa8 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -17,7 +17,7 @@
package android.graphics;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 667f45a..0852004 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -20,7 +20,7 @@
import android.annotation.ColorLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
public class SweepGradient extends Shader {
@UnsupportedAppUsage
diff --git a/graphics/java/android/graphics/TableMaskFilter.java b/graphics/java/android/graphics/TableMaskFilter.java
index d81c491..204f970 100644
--- a/graphics/java/android/graphics/TableMaskFilter.java
+++ b/graphics/java/android/graphics/TableMaskFilter.java
@@ -16,7 +16,7 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/graphics/java/android/graphics/TemporaryBuffer.java b/graphics/java/android/graphics/TemporaryBuffer.java
index 0ae2c70..ef3f7f7 100644
--- a/graphics/java/android/graphics/TemporaryBuffer.java
+++ b/graphics/java/android/graphics/TemporaryBuffer.java
@@ -16,7 +16,8 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import com.android.internal.util.ArrayUtils;
/**
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 6d20ec3..a2dd9a8 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -25,7 +25,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.graphics.fonts.Font;
import android.graphics.fonts.FontFamily;
diff --git a/graphics/java/android/graphics/Xfermode.java b/graphics/java/android/graphics/Xfermode.java
index 6f4adfd..e79fb76 100644
--- a/graphics/java/android/graphics/Xfermode.java
+++ b/graphics/java/android/graphics/Xfermode.java
@@ -21,7 +21,7 @@
package android.graphics;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Xfermode is the base class for objects that are called to implement custom
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index 82f5870..d894600 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -19,7 +19,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index b29fd4d..686f146 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -18,23 +18,23 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.Resources.Theme;
+import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.TypedValue;
-import android.os.SystemClock;
+
+import com.android.internal.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
-import com.android.internal.R;
-
/**
* @hide
*/
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 11a46c4..06159d8 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -20,7 +20,7 @@
import android.animation.TimeInterpolator;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 66947da..1acf6c5 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -25,9 +25,9 @@
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.Application;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 57764c2..8c3fa44 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -16,20 +16,20 @@
package android.graphics.drawable;
-import com.android.internal.R;
+import android.annotation.NonNull;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.os.SystemClock;
+import android.util.AttributeSet;
-import java.io.IOException;
+import com.android.internal.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.Resources.Theme;
-import android.os.SystemClock;
-import android.util.AttributeSet;
+import java.io.IOException;
/**
* An object used to create frame-by-frame animations, defined by a series of
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index e4aa774..4e768c9 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -17,7 +17,7 @@
package android.graphics.drawable;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index 31fdb02..69ed9b4 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -16,21 +16,23 @@
package android.graphics.drawable;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.Gravity;
+
import com.android.internal.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.Resources.Theme;
-import android.graphics.*;
-import android.view.Gravity;
-import android.util.AttributeSet;
-
import java.io.IOException;
/**
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index f5fa8c5..e93e7df 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 0840986..e70529b 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -22,7 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 090d915..51b299c 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -17,7 +17,7 @@
package android.graphics.drawable;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/DrawableInflater.java b/graphics/java/android/graphics/drawable/DrawableInflater.java
index bad3791..3408b64 100644
--- a/graphics/java/android/graphics/drawable/DrawableInflater.java
+++ b/graphics/java/android/graphics/drawable/DrawableInflater.java
@@ -16,19 +16,19 @@
package android.graphics.drawable;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.util.AttributeSet;
import android.view.InflateException;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.HashMap;
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index 64fc704..e8cb42e 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index b9945cc..b50ec0d 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -22,7 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Px;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 3658f89..6366209 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -21,7 +21,7 @@
import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index bc8a4cb..005a4d1 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 760d554..fb4146f 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 8561d95..99d27ba 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 1540cc2..e5e4d45 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index db5f082..43766b6 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -16,23 +16,23 @@
package android.graphics.drawable;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.MathUtils;
+import android.util.TypedValue;
+
import com.android.internal.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.Resources.Theme;
-import android.util.MathUtils;
-import android.util.TypedValue;
-import android.util.AttributeSet;
-
import java.io.IOException;
/**
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 91ed061..af7eed4 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -16,14 +16,9 @@
package android.graphics.drawable;
-import com.android.internal.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
@@ -34,6 +29,11 @@
import android.util.TypedValue;
import android.view.Gravity;
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
/**
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index f67188c..2920acb 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index 276f366..401e05f 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -16,7 +16,7 @@
package android.graphics.drawable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.Resources;
import android.graphics.Canvas;
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index aa19b2a..e6fa866 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -16,7 +16,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.ComplexColor;
diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java
index bcee559..4e6580e 100644
--- a/graphics/java/android/graphics/fonts/FontVariationAxis.java
+++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.text.TextUtils;
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index bd1a492..54710e5 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Matrix;
@@ -29,7 +29,9 @@
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+
import com.android.internal.util.Preconditions;
+
import dalvik.system.CloseGuard;
import libcore.io.IoUtils;
diff --git a/identity/MODULE_LICENSE_APACHE2 b/identity/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/identity/MODULE_LICENSE_APACHE2
diff --git a/identity/NOTICE b/identity/NOTICE
new file mode 100644
index 0000000..64aaa8d
--- /dev/null
+++ b/identity/NOTICE
@@ -0,0 +1,190 @@
+
+ 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/identity/OWNERS b/identity/OWNERS
new file mode 100644
index 0000000..533d90b
--- /dev/null
+++ b/identity/OWNERS
@@ -0,0 +1,3 @@
+swillden@google.com
+zeuthen@google.com
+
diff --git a/identity/java/android/security/identity/AccessControlProfile.java b/identity/java/android/security/identity/AccessControlProfile.java
new file mode 100644
index 0000000..10e451c
--- /dev/null
+++ b/identity/java/android/security/identity/AccessControlProfile.java
@@ -0,0 +1,131 @@
+/*
+ * 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 android.security.identity;
+
+import android.annotation.NonNull;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * A class used to specify access controls.
+ */
+public class AccessControlProfile {
+ private AccessControlProfileId mAccessControlProfileId = new AccessControlProfileId(0);
+ private X509Certificate mReaderCertificate = null;
+ private boolean mUserAuthenticationRequired = true;
+ private long mUserAuthenticationTimeout = 0;
+
+ private AccessControlProfile() {
+ }
+
+ AccessControlProfileId getAccessControlProfileId() {
+ return mAccessControlProfileId;
+ }
+
+ long getUserAuthenticationTimeout() {
+ return mUserAuthenticationTimeout;
+ }
+
+ boolean isUserAuthenticationRequired() {
+ return mUserAuthenticationRequired;
+ }
+
+ X509Certificate getReaderCertificate() {
+ return mReaderCertificate;
+ }
+
+ /**
+ * A builder for {@link AccessControlProfile}.
+ */
+ public static final class Builder {
+ private AccessControlProfile mProfile;
+
+ /**
+ * Each access control profile has numeric identifier that must be unique within the
+ * context of a Credential and may be used to reference the profile.
+ *
+ * <p>By default, the resulting {@link AccessControlProfile} will require user
+ * authentication with a timeout of zero, thus requiring the holder to authenticate for
+ * every presentation where data elements using this access control profile is used.</p>
+ *
+ * @param accessControlProfileId the access control profile identifier.
+ */
+ public Builder(@NonNull AccessControlProfileId accessControlProfileId) {
+ mProfile = new AccessControlProfile();
+ mProfile.mAccessControlProfileId = accessControlProfileId;
+ }
+
+ /**
+ * Set whether user authentication is required.
+ *
+ * <p>This should be used sparingly since disabling user authentication on just a single
+ * data element can easily create a
+ * <a href="https://en.wikipedia.org/wiki/Relay_attack">Relay Attack</a> if the device
+ * on which the credential is stored is compromised.</p>
+ *
+ * @param userAuthenticationRequired Set to true if user authentication is required,
+ * false otherwise.
+ * @return The builder.
+ */
+ public @NonNull Builder setUserAuthenticationRequired(boolean userAuthenticationRequired) {
+ mProfile.mUserAuthenticationRequired = userAuthenticationRequired;
+ return this;
+ }
+
+ /**
+ * Sets the authentication timeout to use.
+ *
+ * <p>The authentication timeout specifies the amount of time, in milliseconds, for which a
+ * user authentication is valid, if user authentication is required (see
+ * {@link #setUserAuthenticationRequired(boolean)}).</p>
+ *
+ * <p>If the timeout is zero, then authentication is always required for each reader
+ * session.</p>
+ *
+ * @param userAuthenticationTimeoutMillis the authentication timeout, in milliseconds.
+ * @return The builder.
+ */
+ public @NonNull Builder setUserAuthenticationTimeout(long userAuthenticationTimeoutMillis) {
+ mProfile.mUserAuthenticationTimeout = userAuthenticationTimeoutMillis;
+ return this;
+ }
+
+ /**
+ * Sets the reader certificate to use when checking access control.
+ *
+ * <p>If set, this is checked against the certificate chain presented by
+ * reader. The access check is fulfilled only if one of the certificates
+ * in the chain, matches the certificate set by this method.</p>
+ *
+ * @param readerCertificate the certificate to use for the access control check.
+ * @return The builder.
+ */
+ public @NonNull Builder setReaderCertificate(@NonNull X509Certificate readerCertificate) {
+ mProfile.mReaderCertificate = readerCertificate;
+ return this;
+ }
+
+ /**
+ * Creates a new {@link AccessControlProfile} from the data supplied to the builder.
+ *
+ * @return The created {@link AccessControlProfile} object.
+ */
+ public @NonNull AccessControlProfile build() {
+ return mProfile;
+ }
+ }
+}
diff --git a/identity/java/android/security/identity/AccessControlProfileId.java b/identity/java/android/security/identity/AccessControlProfileId.java
new file mode 100644
index 0000000..3d59450
--- /dev/null
+++ b/identity/java/android/security/identity/AccessControlProfileId.java
@@ -0,0 +1,42 @@
+/*
+ * 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 android.security.identity;
+
+/**
+ * A class used to wrap an access control profile identifiers.
+ */
+public class AccessControlProfileId {
+ private int mId = 0;
+
+ /**
+ * Constructs a new object holding a numerical identifier.
+ *
+ * @param id the identifier.
+ */
+ public AccessControlProfileId(int id) {
+ this.mId = id;
+ }
+
+ /**
+ * Gets the numerical identifier wrapped by this object.
+ *
+ * @return the identifier.
+ */
+ public int getId() {
+ return this.mId;
+ }
+}
diff --git a/identity/java/android/security/identity/AlreadyPersonalizedException.java b/identity/java/android/security/identity/AlreadyPersonalizedException.java
new file mode 100644
index 0000000..1933882
--- /dev/null
+++ b/identity/java/android/security/identity/AlreadyPersonalizedException.java
@@ -0,0 +1,43 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Thrown if trying to create a credential which already exists.
+ */
+public class AlreadyPersonalizedException extends IdentityCredentialException {
+ /**
+ * Constructs a new {@link AlreadyPersonalizedException} exception.
+ *
+ * @param message the detail message.
+ */
+ public AlreadyPersonalizedException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@link AlreadyPersonalizedException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public AlreadyPersonalizedException(@NonNull String message, @NonNull Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/identity/java/android/security/identity/CipherSuiteNotSupportedException.java b/identity/java/android/security/identity/CipherSuiteNotSupportedException.java
new file mode 100644
index 0000000..e7a6c89
--- /dev/null
+++ b/identity/java/android/security/identity/CipherSuiteNotSupportedException.java
@@ -0,0 +1,43 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Thrown if trying to use a cipher suite which isn't supported.
+ */
+public class CipherSuiteNotSupportedException extends IdentityCredentialException {
+ /**
+ * Constructs a new {@link CipherSuiteNotSupportedException} exception.
+ *
+ * @param message the detail message.
+ */
+ public CipherSuiteNotSupportedException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@link CipherSuiteNotSupportedException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public CipherSuiteNotSupportedException(@NonNull String message, @NonNull Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/identity/java/android/security/identity/CredstoreIdentityCredential.java b/identity/java/android/security/identity/CredstoreIdentityCredential.java
new file mode 100644
index 0000000..c520331
--- /dev/null
+++ b/identity/java/android/security/identity/CredstoreIdentityCredential.java
@@ -0,0 +1,424 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Map;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyAgreement;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+class CredstoreIdentityCredential extends IdentityCredential {
+
+ private static final String TAG = "CredstoreIdentityCredential";
+ private String mCredentialName;
+ private @IdentityCredentialStore.Ciphersuite int mCipherSuite;
+ private Context mContext;
+ private ICredential mBinder;
+
+ CredstoreIdentityCredential(Context context, String credentialName,
+ @IdentityCredentialStore.Ciphersuite int cipherSuite,
+ ICredential binder) {
+ mContext = context;
+ mCredentialName = credentialName;
+ mCipherSuite = cipherSuite;
+ mBinder = binder;
+ }
+
+ private KeyPair mEphemeralKeyPair = null;
+ private SecretKey mSecretKey = null;
+ private SecretKey mReaderSecretKey = null;
+ private int mEphemeralCounter;
+ private int mReadersExpectedEphemeralCounter;
+
+ private void ensureEphemeralKeyPair() {
+ if (mEphemeralKeyPair != null) {
+ return;
+ }
+ try {
+ // This PKCS#12 blob is generated in credstore, using BoringSSL.
+ //
+ // The main reason for this convoluted approach and not just sending the decomposed
+ // key-pair is that this would require directly using (device-side) BouncyCastle which
+ // is tricky due to various API hiding efforts. So instead we have credstore generate
+ // this PKCS#12 blob. The blob is encrypted with no password (sadly, also, BoringSSL
+ // doesn't support not using encryption when building a PKCS#12 blob).
+ //
+ byte[] pkcs12 = mBinder.createEphemeralKeyPair();
+ String alias = "ephemeralKey";
+ char[] password = {};
+
+ KeyStore ks = KeyStore.getInstance("PKCS12");
+ ByteArrayInputStream bais = new ByteArrayInputStream(pkcs12);
+ ks.load(bais, password);
+ PrivateKey privKey = (PrivateKey) ks.getKey(alias, password);
+
+ Certificate cert = ks.getCertificate(alias);
+ PublicKey pubKey = cert.getPublicKey();
+
+ mEphemeralKeyPair = new KeyPair(pubKey, privKey);
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ } catch (KeyStoreException
+ | CertificateException
+ | UnrecoverableKeyException
+ | NoSuchAlgorithmException
+ | IOException e) {
+ throw new RuntimeException("Unexpected exception ", e);
+ }
+ }
+
+ @Override
+ public @NonNull KeyPair createEphemeralKeyPair() {
+ ensureEphemeralKeyPair();
+ return mEphemeralKeyPair;
+ }
+
+ @Override
+ public void setReaderEphemeralPublicKey(@NonNull PublicKey readerEphemeralPublicKey)
+ throws InvalidKeyException {
+ try {
+ byte[] uncompressedForm =
+ Util.publicKeyEncodeUncompressedForm(readerEphemeralPublicKey);
+ mBinder.setReaderEphemeralPublicKey(uncompressedForm);
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+
+ ensureEphemeralKeyPair();
+
+ try {
+ KeyAgreement ka = KeyAgreement.getInstance("ECDH");
+ ka.init(mEphemeralKeyPair.getPrivate());
+ ka.doPhase(readerEphemeralPublicKey, true);
+ byte[] sharedSecret = ka.generateSecret();
+
+ byte[] salt = new byte[1];
+ byte[] info = new byte[0];
+
+ salt[0] = 0x01;
+ byte[] derivedKey = Util.computeHkdf("HmacSha256", sharedSecret, salt, info, 32);
+ mSecretKey = new SecretKeySpec(derivedKey, "AES");
+
+ salt[0] = 0x00;
+ derivedKey = Util.computeHkdf("HmacSha256", sharedSecret, salt, info, 32);
+ mReaderSecretKey = new SecretKeySpec(derivedKey, "AES");
+
+ mEphemeralCounter = 0;
+ mReadersExpectedEphemeralCounter = 0;
+
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("Error performing key agreement", e);
+ }
+ }
+
+ @Override
+ public @NonNull byte[] encryptMessageToReader(@NonNull byte[] messagePlaintext) {
+ byte[] messageCiphertextAndAuthTag = null;
+ try {
+ ByteBuffer iv = ByteBuffer.allocate(12);
+ iv.putInt(0, 0x00000000);
+ iv.putInt(4, 0x00000001);
+ iv.putInt(8, mEphemeralCounter);
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ GCMParameterSpec encryptionParameterSpec = new GCMParameterSpec(128, iv.array());
+ cipher.init(Cipher.ENCRYPT_MODE, mSecretKey, encryptionParameterSpec);
+ messageCiphertextAndAuthTag = cipher.doFinal(messagePlaintext);
+ } catch (BadPaddingException
+ | IllegalBlockSizeException
+ | NoSuchPaddingException
+ | InvalidKeyException
+ | NoSuchAlgorithmException
+ | InvalidAlgorithmParameterException e) {
+ throw new RuntimeException("Error encrypting message", e);
+ }
+ mEphemeralCounter += 1;
+ return messageCiphertextAndAuthTag;
+ }
+
+ @Override
+ public @NonNull byte[] decryptMessageFromReader(@NonNull byte[] messageCiphertext)
+ throws MessageDecryptionException {
+ ByteBuffer iv = ByteBuffer.allocate(12);
+ iv.putInt(0, 0x00000000);
+ iv.putInt(4, 0x00000000);
+ iv.putInt(8, mReadersExpectedEphemeralCounter);
+ byte[] plainText = null;
+ try {
+ final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ cipher.init(Cipher.DECRYPT_MODE, mReaderSecretKey,
+ new GCMParameterSpec(128, iv.array()));
+ plainText = cipher.doFinal(messageCiphertext);
+ } catch (BadPaddingException
+ | IllegalBlockSizeException
+ | InvalidAlgorithmParameterException
+ | InvalidKeyException
+ | NoSuchAlgorithmException
+ | NoSuchPaddingException e) {
+ throw new MessageDecryptionException("Error decrypting message", e);
+ }
+ mReadersExpectedEphemeralCounter += 1;
+ return plainText;
+ }
+
+ @Override
+ public @NonNull Collection<X509Certificate> getCredentialKeyCertificateChain() {
+ try {
+ byte[] certsBlob = mBinder.getCredentialKeyCertificateChain();
+ ByteArrayInputStream bais = new ByteArrayInputStream(certsBlob);
+
+ Collection<? extends Certificate> certs = null;
+ try {
+ CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ certs = factory.generateCertificates(bais);
+ } catch (CertificateException e) {
+ throw new RuntimeException("Error decoding certificates", e);
+ }
+
+ LinkedList<X509Certificate> x509Certs = new LinkedList<>();
+ for (Certificate cert : certs) {
+ x509Certs.add((X509Certificate) cert);
+ }
+ return x509Certs;
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+
+ private boolean mAllowUsingExhaustedKeys = true;
+
+ @Override
+ public void setAllowUsingExhaustedKeys(boolean allowUsingExhaustedKeys) {
+ mAllowUsingExhaustedKeys = allowUsingExhaustedKeys;
+ }
+
+ private boolean mOperationHandleSet = false;
+ private long mOperationHandle = 0;
+
+ /**
+ * Called by android.hardware.biometrics.CryptoObject#getOpId() to get an
+ * operation handle.
+ *
+ * @hide
+ */
+ @Override
+ public long getCredstoreOperationHandle() {
+ if (!mOperationHandleSet) {
+ try {
+ mOperationHandle = mBinder.selectAuthKey(mAllowUsingExhaustedKeys);
+ mOperationHandleSet = true;
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ if (e.errorCode == ICredentialStore.ERROR_NO_AUTHENTICATION_KEY_AVAILABLE) {
+ // The NoAuthenticationKeyAvailableException will be thrown when
+ // the caller proceeds to call getEntries().
+ }
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+ return mOperationHandle;
+ }
+
+ @NonNull
+ @Override
+ public ResultData getEntries(
+ @Nullable byte[] requestMessage,
+ @NonNull Map<String, Collection<String>> entriesToRequest,
+ @Nullable byte[] sessionTranscript,
+ @Nullable byte[] readerSignature)
+ throws SessionTranscriptMismatchException, NoAuthenticationKeyAvailableException,
+ InvalidReaderSignatureException, EphemeralPublicKeyNotFoundException,
+ InvalidRequestMessageException {
+
+ RequestNamespaceParcel[] rnsParcels = new RequestNamespaceParcel[entriesToRequest.size()];
+ int n = 0;
+ for (String namespaceName : entriesToRequest.keySet()) {
+ Collection<String> entryNames = entriesToRequest.get(namespaceName);
+ rnsParcels[n] = new RequestNamespaceParcel();
+ rnsParcels[n].namespaceName = namespaceName;
+ rnsParcels[n].entries = new RequestEntryParcel[entryNames.size()];
+ int m = 0;
+ for (String entryName : entryNames) {
+ rnsParcels[n].entries[m] = new RequestEntryParcel();
+ rnsParcels[n].entries[m].name = entryName;
+ m++;
+ }
+ n++;
+ }
+
+ GetEntriesResultParcel resultParcel = null;
+ try {
+ resultParcel = mBinder.getEntries(
+ requestMessage != null ? requestMessage : new byte[0],
+ rnsParcels,
+ sessionTranscript != null ? sessionTranscript : new byte[0],
+ readerSignature != null ? readerSignature : new byte[0],
+ mAllowUsingExhaustedKeys);
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ if (e.errorCode == ICredentialStore.ERROR_EPHEMERAL_PUBLIC_KEY_NOT_FOUND) {
+ throw new EphemeralPublicKeyNotFoundException(e.getMessage(), e);
+ } else if (e.errorCode == ICredentialStore.ERROR_INVALID_READER_SIGNATURE) {
+ throw new InvalidReaderSignatureException(e.getMessage(), e);
+ } else if (e.errorCode == ICredentialStore.ERROR_NO_AUTHENTICATION_KEY_AVAILABLE) {
+ throw new NoAuthenticationKeyAvailableException(e.getMessage(), e);
+ } else if (e.errorCode == ICredentialStore.ERROR_INVALID_ITEMS_REQUEST_MESSAGE) {
+ throw new InvalidRequestMessageException(e.getMessage(), e);
+ } else if (e.errorCode == ICredentialStore.ERROR_SESSION_TRANSCRIPT_MISMATCH) {
+ throw new SessionTranscriptMismatchException(e.getMessage(), e);
+ } else {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+
+ byte[] mac = resultParcel.mac;
+ if (mac != null && mac.length == 0) {
+ mac = null;
+ }
+ CredstoreResultData.Builder resultDataBuilder = new CredstoreResultData.Builder(
+ resultParcel.staticAuthenticationData, resultParcel.deviceNameSpaces, mac);
+
+ for (ResultNamespaceParcel resultNamespaceParcel : resultParcel.resultNamespaces) {
+ for (ResultEntryParcel resultEntryParcel : resultNamespaceParcel.entries) {
+ if (resultEntryParcel.status == ICredential.STATUS_OK) {
+ resultDataBuilder.addEntry(resultNamespaceParcel.namespaceName,
+ resultEntryParcel.name, resultEntryParcel.value);
+ } else {
+ resultDataBuilder.addErrorStatus(resultNamespaceParcel.namespaceName,
+ resultEntryParcel.name,
+ resultEntryParcel.status);
+ }
+ }
+ }
+ return resultDataBuilder.build();
+ }
+
+ @Override
+ public void setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey) {
+ try {
+ mBinder.setAvailableAuthenticationKeys(keyCount, maxUsesPerKey);
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+
+ @Override
+ public @NonNull Collection<X509Certificate> getAuthKeysNeedingCertification() {
+ try {
+ AuthKeyParcel[] authKeyParcels = mBinder.getAuthKeysNeedingCertification();
+ LinkedList<X509Certificate> x509Certs = new LinkedList<>();
+ CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ for (AuthKeyParcel authKeyParcel : authKeyParcels) {
+ Collection<? extends Certificate> certs = null;
+ ByteArrayInputStream bais = new ByteArrayInputStream(authKeyParcel.x509cert);
+ certs = factory.generateCertificates(bais);
+ if (certs.size() != 1) {
+ throw new RuntimeException("Returned blob yields more than one X509 cert");
+ }
+ X509Certificate authKeyCert = (X509Certificate) certs.iterator().next();
+ x509Certs.add(authKeyCert);
+ }
+ return x509Certs;
+ } catch (CertificateException e) {
+ throw new RuntimeException("Error decoding authenticationKey", e);
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+
+ @Override
+ public void storeStaticAuthenticationData(X509Certificate authenticationKey,
+ byte[] staticAuthData)
+ throws UnknownAuthenticationKeyException {
+ try {
+ AuthKeyParcel authKeyParcel = new AuthKeyParcel();
+ authKeyParcel.x509cert = authenticationKey.getEncoded();
+ mBinder.storeStaticAuthenticationData(authKeyParcel, staticAuthData);
+ } catch (CertificateEncodingException e) {
+ throw new RuntimeException("Error encoding authenticationKey", e);
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ if (e.errorCode == ICredentialStore.ERROR_AUTHENTICATION_KEY_NOT_FOUND) {
+ throw new UnknownAuthenticationKeyException(e.getMessage(), e);
+ } else {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+ }
+
+ @Override
+ public @NonNull int[] getAuthenticationDataUsageCount() {
+ try {
+ int[] usageCount = mBinder.getAuthenticationDataUsageCount();
+ return usageCount;
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+}
diff --git a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
new file mode 100644
index 0000000..dcc6b95
--- /dev/null
+++ b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
@@ -0,0 +1,162 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.ServiceManager;
+
+class CredstoreIdentityCredentialStore extends IdentityCredentialStore {
+
+ private static final String TAG = "CredstoreIdentityCredentialStore";
+
+ private Context mContext = null;
+ private ICredentialStore mStore = null;
+
+ private CredstoreIdentityCredentialStore(@NonNull Context context, ICredentialStore store) {
+ mContext = context;
+ mStore = store;
+ }
+
+ static CredstoreIdentityCredentialStore getInstanceForType(@NonNull Context context,
+ int credentialStoreType) {
+ ICredentialStoreFactory storeFactory =
+ ICredentialStoreFactory.Stub.asInterface(
+ ServiceManager.getService("android.security.identity"));
+
+ ICredentialStore credStore = null;
+ try {
+ credStore = storeFactory.getCredentialStore(credentialStoreType);
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ if (e.errorCode == ICredentialStore.ERROR_GENERIC) {
+ return null;
+ } else {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+ if (credStore == null) {
+ return null;
+ }
+
+ return new CredstoreIdentityCredentialStore(context, credStore);
+ }
+
+ private static CredstoreIdentityCredentialStore sInstanceDefault = null;
+ private static CredstoreIdentityCredentialStore sInstanceDirectAccess = null;
+
+ public static @Nullable IdentityCredentialStore getInstance(@NonNull Context context) {
+ if (sInstanceDefault == null) {
+ sInstanceDefault = getInstanceForType(context,
+ ICredentialStoreFactory.CREDENTIAL_STORE_TYPE_DEFAULT);
+ }
+ return sInstanceDefault;
+ }
+
+ public static @Nullable IdentityCredentialStore getDirectAccessInstance(@NonNull
+ Context context) {
+ if (sInstanceDirectAccess == null) {
+ sInstanceDirectAccess = getInstanceForType(context,
+ ICredentialStoreFactory.CREDENTIAL_STORE_TYPE_DIRECT_ACCESS);
+ }
+ return sInstanceDirectAccess;
+ }
+
+ @Override
+ public @NonNull String[] getSupportedDocTypes() {
+ try {
+ SecurityHardwareInfoParcel info;
+ info = mStore.getSecurityHardwareInfo();
+ return info.supportedDocTypes;
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+
+ @Override public @NonNull WritableIdentityCredential createCredential(
+ @NonNull String credentialName,
+ @NonNull String docType) throws AlreadyPersonalizedException,
+ DocTypeNotSupportedException {
+ try {
+ IWritableCredential wc;
+ wc = mStore.createCredential(credentialName, docType);
+ return new CredstoreWritableIdentityCredential(mContext, credentialName, docType, wc);
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ if (e.errorCode == ICredentialStore.ERROR_ALREADY_PERSONALIZED) {
+ throw new AlreadyPersonalizedException(e.getMessage(), e);
+ } else if (e.errorCode == ICredentialStore.ERROR_DOCUMENT_TYPE_NOT_SUPPORTED) {
+ throw new DocTypeNotSupportedException(e.getMessage(), e);
+ } else {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+ }
+
+ @Override public @Nullable IdentityCredential getCredentialByName(
+ @NonNull String credentialName,
+ @Ciphersuite int cipherSuite) throws CipherSuiteNotSupportedException {
+ try {
+ ICredential credstoreCredential;
+ credstoreCredential = mStore.getCredentialByName(credentialName, cipherSuite);
+ return new CredstoreIdentityCredential(mContext, credentialName, cipherSuite,
+ credstoreCredential);
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ if (e.errorCode == ICredentialStore.ERROR_NO_SUCH_CREDENTIAL) {
+ return null;
+ } else if (e.errorCode == ICredentialStore.ERROR_CIPHER_SUITE_NOT_SUPPORTED) {
+ throw new CipherSuiteNotSupportedException(e.getMessage(), e);
+ } else {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+ }
+
+ @Override
+ public @Nullable byte[] deleteCredentialByName(@NonNull String credentialName) {
+ ICredential credstoreCredential = null;
+ try {
+ try {
+ credstoreCredential = mStore.getCredentialByName(credentialName,
+ CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
+ } catch (android.os.ServiceSpecificException e) {
+ if (e.errorCode == ICredentialStore.ERROR_NO_SUCH_CREDENTIAL) {
+ return null;
+ }
+ }
+ byte[] proofOfDeletion = credstoreCredential.deleteCredential();
+ return proofOfDeletion;
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+
+}
diff --git a/identity/java/android/security/identity/CredstoreResultData.java b/identity/java/android/security/identity/CredstoreResultData.java
new file mode 100644
index 0000000..ef7afca
--- /dev/null
+++ b/identity/java/android/security/identity/CredstoreResultData.java
@@ -0,0 +1,162 @@
+/*
+ * 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 android.security.identity;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+/**
+ * An object that contains the result of retrieving data from a credential. This is used to return
+ * data requested from a {@link IdentityCredential}.
+ */
+class CredstoreResultData extends ResultData {
+
+ byte[] mStaticAuthenticationData = null;
+ byte[] mAuthenticatedData = null;
+ byte[] mMessageAuthenticationCode = null;
+
+ private Map<String, Map<String, EntryData>> mData = new LinkedHashMap<>();
+
+ private static class EntryData {
+ @Status
+ int mStatus;
+ byte[] mValue;
+
+ EntryData(byte[] value, @Status int status) {
+ this.mValue = value;
+ this.mStatus = status;
+ }
+ }
+
+ CredstoreResultData() {}
+
+ @Override
+ public @NonNull byte[] getAuthenticatedData() {
+ return mAuthenticatedData;
+ }
+
+ @Override
+ public @Nullable byte[] getMessageAuthenticationCode() {
+ return mMessageAuthenticationCode;
+ }
+
+ @Override
+ public @NonNull byte[] getStaticAuthenticationData() {
+ return mStaticAuthenticationData;
+ }
+
+ @Override
+ public @NonNull Collection<String> getNamespaceNames() {
+ return Collections.unmodifiableCollection(mData.keySet());
+ }
+
+ @Override
+ public @Nullable Collection<String> getEntryNames(@NonNull String namespaceName) {
+ Map<String, EntryData> innerMap = mData.get(namespaceName);
+ if (innerMap == null) {
+ return null;
+ }
+ return Collections.unmodifiableCollection(innerMap.keySet());
+ }
+
+ @Override
+ public @Nullable Collection<String> getRetrievedEntryNames(@NonNull String namespaceName) {
+ Map<String, EntryData> innerMap = mData.get(namespaceName);
+ if (innerMap == null) {
+ return null;
+ }
+ LinkedList<String> result = new LinkedList<String>();
+ for (Map.Entry<String, EntryData> entry : innerMap.entrySet()) {
+ if (entry.getValue().mStatus == STATUS_OK) {
+ result.add(entry.getKey());
+ }
+ }
+ return result;
+ }
+
+ private EntryData getEntryData(@NonNull String namespaceName, @NonNull String name) {
+ Map<String, EntryData> innerMap = mData.get(namespaceName);
+ if (innerMap == null) {
+ return null;
+ }
+ return innerMap.get(name);
+ }
+
+ @Override
+ @Status
+ public int getStatus(@NonNull String namespaceName, @NonNull String name) {
+ EntryData value = getEntryData(namespaceName, name);
+ if (value == null) {
+ return STATUS_NOT_REQUESTED;
+ }
+ return value.mStatus;
+ }
+
+ @Override
+ public @Nullable byte[] getEntry(@NonNull String namespaceName, @NonNull String name) {
+ EntryData value = getEntryData(namespaceName, name);
+ if (value == null) {
+ return null;
+ }
+ return value.mValue;
+ }
+
+ static class Builder {
+ private CredstoreResultData mResultData;
+
+ Builder(byte[] staticAuthenticationData,
+ byte[] authenticatedData,
+ byte[] messageAuthenticationCode) {
+ this.mResultData = new CredstoreResultData();
+ this.mResultData.mStaticAuthenticationData = staticAuthenticationData;
+ this.mResultData.mAuthenticatedData = authenticatedData;
+ this.mResultData.mMessageAuthenticationCode = messageAuthenticationCode;
+ }
+
+ private Map<String, EntryData> getOrCreateInnerMap(String namespaceName) {
+ Map<String, EntryData> innerMap = mResultData.mData.get(namespaceName);
+ if (innerMap == null) {
+ innerMap = new LinkedHashMap<>();
+ mResultData.mData.put(namespaceName, innerMap);
+ }
+ return innerMap;
+ }
+
+ Builder addEntry(String namespaceName, String name, byte[] value) {
+ Map<String, EntryData> innerMap = getOrCreateInnerMap(namespaceName);
+ innerMap.put(name, new EntryData(value, STATUS_OK));
+ return this;
+ }
+
+ Builder addErrorStatus(String namespaceName, String name, @Status int status) {
+ Map<String, EntryData> innerMap = getOrCreateInnerMap(namespaceName);
+ innerMap.put(name, new EntryData(null, status));
+ return this;
+ }
+
+ CredstoreResultData build() {
+ return mResultData;
+ }
+ }
+
+}
diff --git a/identity/java/android/security/identity/CredstoreWritableIdentityCredential.java b/identity/java/android/security/identity/CredstoreWritableIdentityCredential.java
new file mode 100644
index 0000000..335636c
--- /dev/null
+++ b/identity/java/android/security/identity/CredstoreWritableIdentityCredential.java
@@ -0,0 +1,168 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.security.GateKeeper;
+
+import java.io.ByteArrayInputStream;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.LinkedList;
+
+class CredstoreWritableIdentityCredential extends WritableIdentityCredential {
+
+ private static final String TAG = "CredstoreWritableIdentityCredential";
+
+ private String mDocType;
+ private String mCredentialName;
+ private Context mContext;
+ private IWritableCredential mBinder;
+
+ CredstoreWritableIdentityCredential(Context context,
+ @NonNull String credentialName,
+ @NonNull String docType,
+ IWritableCredential binder) {
+ mContext = context;
+ mDocType = docType;
+ mCredentialName = credentialName;
+ mBinder = binder;
+ }
+
+ @NonNull @Override
+ public Collection<X509Certificate> getCredentialKeyCertificateChain(@NonNull byte[] challenge) {
+ try {
+ byte[] certsBlob = mBinder.getCredentialKeyCertificateChain(challenge);
+ ByteArrayInputStream bais = new ByteArrayInputStream(certsBlob);
+
+ Collection<? extends Certificate> certs = null;
+ try {
+ CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ certs = factory.generateCertificates(bais);
+ } catch (CertificateException e) {
+ throw new RuntimeException("Error decoding certificates", e);
+ }
+
+ LinkedList<X509Certificate> x509Certs = new LinkedList<>();
+ for (Certificate cert : certs) {
+ x509Certs.add((X509Certificate) cert);
+ }
+ return x509Certs;
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+
+ @NonNull @Override
+ public byte[] personalize(@NonNull PersonalizationData personalizationData) {
+
+ Collection<AccessControlProfile> accessControlProfiles =
+ personalizationData.getAccessControlProfiles();
+
+ AccessControlProfileParcel[] acpParcels =
+ new AccessControlProfileParcel[accessControlProfiles.size()];
+ boolean usingUserAuthentication = false;
+ int n = 0;
+ for (AccessControlProfile profile : accessControlProfiles) {
+ acpParcels[n] = new AccessControlProfileParcel();
+ acpParcels[n].id = profile.getAccessControlProfileId().getId();
+ X509Certificate cert = profile.getReaderCertificate();
+ if (cert != null) {
+ try {
+ acpParcels[n].readerCertificate = cert.getEncoded();
+ } catch (CertificateException e) {
+ throw new RuntimeException("Error encoding reader certificate", e);
+ }
+ } else {
+ acpParcels[n].readerCertificate = new byte[0];
+ }
+ acpParcels[n].userAuthenticationRequired = profile.isUserAuthenticationRequired();
+ acpParcels[n].userAuthenticationTimeoutMillis = profile.getUserAuthenticationTimeout();
+ if (profile.isUserAuthenticationRequired()) {
+ usingUserAuthentication = true;
+ }
+ n++;
+ }
+
+ Collection<String> namespaceNames = personalizationData.getNamespaceNames();
+
+ EntryNamespaceParcel[] ensParcels = new EntryNamespaceParcel[namespaceNames.size()];
+ n = 0;
+ for (String namespaceName : namespaceNames) {
+ PersonalizationData.NamespaceData nsd =
+ personalizationData.getNamespaceData(namespaceName);
+
+ ensParcels[n] = new EntryNamespaceParcel();
+ ensParcels[n].namespaceName = namespaceName;
+
+ Collection<String> entryNames = nsd.getEntryNames();
+ EntryParcel[] eParcels = new EntryParcel[entryNames.size()];
+ int m = 0;
+ for (String entryName : entryNames) {
+ eParcels[m] = new EntryParcel();
+ eParcels[m].name = entryName;
+ eParcels[m].value = nsd.getEntryValue(entryName);
+ Collection<AccessControlProfileId> acpIds =
+ nsd.getAccessControlProfileIds(entryName);
+ eParcels[m].accessControlProfileIds = new int[acpIds.size()];
+ int o = 0;
+ for (AccessControlProfileId acpId : acpIds) {
+ eParcels[m].accessControlProfileIds[o++] = acpId.getId();
+ }
+ m++;
+ }
+ ensParcels[n].entries = eParcels;
+ n++;
+ }
+
+ // Note: The value 0 is used to convey that no user-authentication is needed for this
+ // credential. This is to allow creating credentials w/o user authentication on devices
+ // where Secure lock screen is not enabled.
+ long secureUserId = 0;
+ if (usingUserAuthentication) {
+ secureUserId = getRootSid();
+ }
+ try {
+ byte[] personalizationReceipt = mBinder.personalize(acpParcels, ensParcels,
+ secureUserId);
+ return personalizationReceipt;
+ } catch (android.os.RemoteException e) {
+ throw new RuntimeException("Unexpected RemoteException ", e);
+ } catch (android.os.ServiceSpecificException e) {
+ throw new RuntimeException("Unexpected ServiceSpecificException with code "
+ + e.errorCode, e);
+ }
+ }
+
+ private static long getRootSid() {
+ long rootSid = GateKeeper.getSecureUserId();
+ if (rootSid == 0) {
+ throw new IllegalStateException("Secure lock screen must be enabled"
+ + " to create credentials requiring user authentication");
+ }
+ return rootSid;
+ }
+
+
+}
diff --git a/identity/java/android/security/identity/DocTypeNotSupportedException.java b/identity/java/android/security/identity/DocTypeNotSupportedException.java
new file mode 100644
index 0000000..754e44a
--- /dev/null
+++ b/identity/java/android/security/identity/DocTypeNotSupportedException.java
@@ -0,0 +1,43 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Thrown if trying to create a credential with an unsupported document type.
+ */
+public class DocTypeNotSupportedException extends IdentityCredentialException {
+ /**
+ * Constructs a new {@link DocTypeNotSupportedException} exception.
+ *
+ * @param message the detail message.
+ */
+ public DocTypeNotSupportedException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@link DocTypeNotSupportedException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public DocTypeNotSupportedException(@NonNull String message, @NonNull Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/identity/java/android/security/identity/EphemeralPublicKeyNotFoundException.java b/identity/java/android/security/identity/EphemeralPublicKeyNotFoundException.java
new file mode 100644
index 0000000..265f271
--- /dev/null
+++ b/identity/java/android/security/identity/EphemeralPublicKeyNotFoundException.java
@@ -0,0 +1,44 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Thrown if the ephemeral public key was not found in the session transcript
+ * passed to {@link IdentityCredential#getEntries(byte[], Map, byte[], byte[])}.
+ */
+public class EphemeralPublicKeyNotFoundException extends IdentityCredentialException {
+ /**
+ * Constructs a new {@link EphemeralPublicKeyNotFoundException} exception.
+ *
+ * @param message the detail message.
+ */
+ public EphemeralPublicKeyNotFoundException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@link EphemeralPublicKeyNotFoundException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public EphemeralPublicKeyNotFoundException(@NonNull String message, @NonNull Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/identity/java/android/security/identity/IdentityCredential.java b/identity/java/android/security/identity/IdentityCredential.java
new file mode 100644
index 0000000..bd43919
--- /dev/null
+++ b/identity/java/android/security/identity/IdentityCredential.java
@@ -0,0 +1,309 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Class used to read data from a previously provisioned credential.
+ *
+ * Use {@link IdentityCredentialStore#getCredentialByName(String, int)} to get a
+ * {@link IdentityCredential} instance.
+ */
+public abstract class IdentityCredential {
+ /**
+ * @hide
+ */
+ protected IdentityCredential() {}
+
+ /**
+ * Create an ephemeral key pair to use to establish a secure channel with a reader.
+ *
+ * <p>Most applications will use only the public key, and only to send it to the reader,
+ * allowing the private key to be used internally for {@link #encryptMessageToReader(byte[])}
+ * and {@link #decryptMessageFromReader(byte[])}. The private key is also provided for
+ * applications that wish to use a cipher suite that is not supported by
+ * {@link IdentityCredentialStore}.
+ *
+ * @return ephemeral key pair to use to establish a secure channel with a reader.
+ */
+ public @NonNull abstract KeyPair createEphemeralKeyPair();
+
+ /**
+ * Set the ephemeral public key provided by the reader. This must be called before
+ * {@link #encryptMessageToReader} or {@link #decryptMessageFromReader} can be called.
+ *
+ * @param readerEphemeralPublicKey The ephemeral public key provided by the reader to
+ * establish a secure session.
+ * @throws InvalidKeyException if the given key is invalid.
+ */
+ public abstract void setReaderEphemeralPublicKey(@NonNull PublicKey readerEphemeralPublicKey)
+ throws InvalidKeyException;
+
+ /**
+ * Encrypt a message for transmission to the reader.
+ *
+ * @param messagePlaintext unencrypted message to encrypt.
+ * @return encrypted message.
+ */
+ public @NonNull abstract byte[] encryptMessageToReader(@NonNull byte[] messagePlaintext);
+
+ /**
+ * Decrypt a message received from the reader.
+ *
+ * @param messageCiphertext encrypted message to decrypt.
+ * @return decrypted message.
+ * @throws MessageDecryptionException if the ciphertext couldn't be decrypted.
+ */
+ public @NonNull abstract byte[] decryptMessageFromReader(@NonNull byte[] messageCiphertext)
+ throws MessageDecryptionException;
+
+ /**
+ * Gets the X.509 certificate chain for the CredentialKey which identifies this
+ * credential to the issuing authority. This is the same certificate chain that
+ * was returned by {@link WritableIdentityCredential#getCredentialKeyCertificateChain(byte[])}
+ * when the credential was first created and its Android Keystore extension will
+ * contain the <code>challenge</code> data set at that time. See the documentation
+ * for that method for important information about this certificate chain.
+ *
+ * @return the certificate chain for this credential's CredentialKey.
+ */
+ public @NonNull abstract Collection<X509Certificate> getCredentialKeyCertificateChain();
+
+ /**
+ * Sets whether to allow using an authentication key which use count has been exceeded if no
+ * other key is available. This must be called prior to calling
+ * {@link #getEntries(byte[], Map, byte[], byte[])} or using a
+ * {@link android.hardware.biometrics.BiometricPrompt.CryptoObject} which references this
+ * object.
+ *
+ * By default this is set to true.
+ *
+ * @param allowUsingExhaustedKeys whether to allow using an authentication key which use count
+ * has been exceeded if no other key is available.
+ */
+ public abstract void setAllowUsingExhaustedKeys(boolean allowUsingExhaustedKeys);
+
+ /**
+ * Called by android.hardware.biometrics.CryptoObject#getOpId() to get an
+ * operation handle.
+ *
+ * @hide
+ */
+ public abstract long getCredstoreOperationHandle();
+
+ /**
+ * Retrieve data entries and associated data from this {@code IdentityCredential}.
+ *
+ * <p>If an access control check fails for one of the requested entries or if the entry
+ * doesn't exist, the entry is simply not returned. The application can detect this
+ * by using the {@link ResultData#getStatus(String, String)} method on each of the requested
+ * entries.
+ *
+ * <p>It is the responsibility of the calling application to know if authentication is needed
+ * and use e.g. {@link android.hardware.biometrics.BiometricPrompt}) to make the user
+ * authenticate using a {@link android.hardware.biometrics.BiometricPrompt.CryptoObject} which
+ * references this object. If needed, this must be done before calling
+ * {@link #getEntries(byte[], Map, byte[], byte[])}.
+ *
+ * <p>If this method returns successfully (i.e. without throwing an exception), it must not be
+ * called again on this instance.
+ *
+ * <p>If not {@code null} the {@code requestMessage} parameter must contain data for the request
+ * from the verifier. The content can be defined in the way appropriate for the credential, byt
+ * there are three requirements that must be met to work with this API:
+ * <ul>
+ * <li>The content must be a CBOR-encoded structure.</li>
+ * <li>The CBOR structure must be a map.</li>
+ * <li>The map must contain a tstr key "nameSpaces" whose value contains a map, as described in
+ * the example below.</li>
+ * </ul>
+ *
+ * <p>Here's an example of CBOR which conforms to this requirement:
+ * <pre>
+ * ItemsRequest = {
+ * ? "docType" : DocType,
+ * "nameSpaces" : NameSpaces,
+ * ? "RequestInfo" : {* tstr => any} ; Additional info the reader wants to provide
+ * }
+ *
+ * NameSpaces = {
+ * + NameSpace => DataElements ; Requested data elements for each NameSpace
+ * }
+ *
+ * NameSpace = tstr
+ *
+ * DataElements = {
+ * + DataElement => IntentToRetain
+ * }
+ *
+ * DataElement = tstr
+ * IntentToRetain = bool
+ * </pre>
+ *
+ * <p>If the {@code sessionTranscript} parameter is not {@code null}, it must contain CBOR
+ * data conforming to the following CDDL schema:
+ *
+ * <pre>
+ * SessionTranscript = [
+ * DeviceEngagementBytes,
+ * EReaderKeyBytes
+ * ]
+ *
+ * DeviceEngagementBytes = #6.24(bstr .cbor DeviceEngagement)
+ * EReaderKeyBytes = #6.24(bstr .cbor EReaderKey.Pub)
+ * </pre>
+ *
+ * <p>If the SessionTranscript is not empty, a COSE_Key structure for the public part
+ * of the key-pair previously generated by {@link #createEphemeralKeyPair()} must appear
+ * somewhere in {@code DeviceEngagement} and the X and Y coordinates must both be present
+ * in uncompressed form.
+ *
+ * <p>If {@code readerAuth} is not {@code null} it must be the bytes of a COSE_Sign1
+ * structure as defined in RFC 8152. For the payload nil shall be used and the
+ * detached payload is the ReaderAuthentication CBOR described below.
+ * <pre>
+ * ReaderAuthentication = [
+ * "ReaderAuthentication",
+ * SessionTranscript,
+ * ItemsRequestBytes
+ * ]
+ *
+ * ItemsRequestBytes = #6.24(bstr .cbor ItemsRequest) ; Bytes of ItemsRequest
+ * </pre>
+ *
+ * <p>The public key corresponding to the key used to made signature, can be
+ * found in the {@code x5chain} unprotected header element of the COSE_Sign1
+ * structure (as as described in 'draft-ietf-cose-x509-04'). There will be at
+ * least one certificate in said element and there may be more (and if so,
+ * each certificate must be signed by its successor).
+ *
+ * <p>Data elements protected by reader authentication is returned if, and only if, they are
+ * mentioned in {@code requestMessage}, {@code requestMessage} is signed by the top-most
+ * certificate in {@code readerCertificateChain}, and the data element is configured
+ * with an {@link AccessControlProfile} with a {@link X509Certificate} in
+ * {@code readerCertificateChain}.
+ *
+ * <p>Note that only items referenced in {@code entriesToRequest} are returned - the
+ * {@code requestMessage} parameter is only used to for enforcing reader authentication.
+ *
+ * @param requestMessage If not {@code null}, must contain CBOR data conforming to
+ * the schema mentioned above.
+ * @param entriesToRequest The entries to request, organized as a map of namespace
+ * names with each value being a collection of data elements
+ * in the given namespace.
+ * @param readerSignature COSE_Sign1 structure as described above or {@code null}
+ * if reader authentication is not being used.
+ * @return A {@link ResultData} object containing entry data organized by namespace and a
+ * cryptographically authenticated representation of the same data.
+ * @throws SessionTranscriptMismatchException Thrown when trying use multiple different
+ * session transcripts in the same presentation
+ * session.
+ * @throws NoAuthenticationKeyAvailableException if authentication keys were never
+ * provisioned, the method
+ * {@link #setAvailableAuthenticationKeys(int, int)}
+ * was called with {@code keyCount} set to 0,
+ * the method
+ * {@link #setAllowUsingExhaustedKeys(boolean)}
+ * was called with {@code false} and all
+ * available authentication keys have been
+ * exhausted.
+ * @throws InvalidReaderSignatureException if the reader signature is invalid, or it
+ * doesn't contain a certificate chain, or if
+ * the signature failed to validate.
+ * @throws InvalidRequestMessageException if the requestMessage is malformed.
+ * @throws EphemeralPublicKeyNotFoundException if the ephemeral public key was not found in
+ * the session transcript.
+ */
+ public abstract @NonNull ResultData getEntries(
+ @Nullable byte[] requestMessage,
+ @NonNull Map<String, Collection<String>> entriesToRequest,
+ @Nullable byte[] sessionTranscript,
+ @Nullable byte[] readerSignature)
+ throws SessionTranscriptMismatchException, NoAuthenticationKeyAvailableException,
+ InvalidReaderSignatureException, EphemeralPublicKeyNotFoundException,
+ InvalidRequestMessageException;
+
+ /**
+ * Sets the number of dynamic authentication keys the {@code IdentityCredential} will maintain,
+ * and the number of times each should be used.
+ *
+ * <p>{@code IdentityCredential}s will select the least-used dynamic authentication key each
+ * time {@link #getEntries(byte[], Map, byte[], byte[])} is called. {@code IdentityCredential}s
+ * for which this method has not been called behave as though it had been called wit
+ * {@code keyCount} 0 and {@code maxUsesPerKey} 1.
+ *
+ * @param keyCount The number of active, certified dynamic authentication keys the
+ * {@code IdentityCredential} will try to keep available. This value
+ * must be non-negative.
+ * @param maxUsesPerKey The maximum number of times each of the keys will be used before it's
+ * eligible for replacement. This value must be greater than zero.
+ */
+ public abstract void setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey);
+
+ /**
+ * Gets a collection of dynamic authentication keys that need certification.
+ *
+ * <p>When there aren't enough certified dynamic authentication keys, either because the key
+ * count has been increased or because one or more keys have reached their usage count, this
+ * method will generate replacement keys and certificates and return them for issuer
+ * certification. The issuer certificates and associated static authentication data must then
+ * be provided back to the {@code IdentityCredential} using
+ * {@link #storeStaticAuthenticationData(X509Certificate, byte[])}.
+ *
+ * <p>Each X.509 certificate is signed by CredentialKey. The certificate chain for CredentialKey
+ * can be obtained using the {@link #getCredentialKeyCertificateChain()} method.
+ *
+ * @return A collection of X.509 certificates for dynamic authentication keys that need issuer
+ * certification.
+ */
+ public @NonNull abstract Collection<X509Certificate> getAuthKeysNeedingCertification();
+
+ /**
+ * Store authentication data associated with a dynamic authentication key.
+ *
+ * This should only be called for an authenticated key returned by
+ * {@link #getAuthKeysNeedingCertification()}.
+ *
+ * @param authenticationKey The dynamic authentication key for which certification and
+ * associated static
+ * authentication data is being provided.
+ * @param staticAuthData Static authentication data provided by the issuer that validates
+ * the authenticity
+ * and integrity of the credential data fields.
+ * @throws UnknownAuthenticationKeyException If the given authentication key is not recognized.
+ */
+ public abstract void storeStaticAuthenticationData(
+ @NonNull X509Certificate authenticationKey,
+ @NonNull byte[] staticAuthData)
+ throws UnknownAuthenticationKeyException;
+
+ /**
+ * Get the number of times the dynamic authentication keys have been used.
+ *
+ * @return int array of dynamic authentication key usage counts.
+ */
+ public @NonNull abstract int[] getAuthenticationDataUsageCount();
+}
diff --git a/identity/java/android/security/identity/IdentityCredentialException.java b/identity/java/android/security/identity/IdentityCredentialException.java
new file mode 100644
index 0000000..c811380
--- /dev/null
+++ b/identity/java/android/security/identity/IdentityCredentialException.java
@@ -0,0 +1,44 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Base class for all Identity Credential exceptions.
+ */
+public class IdentityCredentialException extends Exception {
+ /**
+ * Constructs a new {@link IdentityCredentialException} exception.
+ *
+ * @param message the detail message.
+ */
+ public IdentityCredentialException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@link IdentityCredentialException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public IdentityCredentialException(@NonNull String message, @NonNull Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/identity/java/android/security/identity/IdentityCredentialStore.java b/identity/java/android/security/identity/IdentityCredentialStore.java
new file mode 100644
index 0000000..a1dfc77
--- /dev/null
+++ b/identity/java/android/security/identity/IdentityCredentialStore.java
@@ -0,0 +1,186 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An interface to a secure store for user identity documents.
+ *
+ * <p>This interface is deliberately fairly general and abstract. To the extent possible,
+ * specification of the message formats and semantics of communication with credential
+ * verification devices and issuing authorities (IAs) is out of scope. It provides the
+ * interface with secure storage but a credential-specific Android application will be
+ * required to implement the presentation and verification protocols and processes
+ * appropriate for the specific credential type.
+ *
+ * <p>Multiple credentials can be created. Each credential comprises:</p>
+ * <ul>
+ * <li>A document type, which is a string.</li>
+ *
+ * <li>A set of namespaces, which serve to disambiguate value names. It is recommended
+ * that namespaces be structured as reverse domain names so that IANA effectively serves
+ * as the namespace registrar.</li>
+ *
+ * <li>For each namespace, a set of name/value pairs, each with an associated set of
+ * access control profile IDs. Names are strings and values are typed and can be any
+ * value supported by <a href="http://cbor.io/">CBOR</a>.</li>
+ *
+ * <li>A set of access control profiles, each with a profile ID and a specification
+ * of the conditions which satisfy the profile's requirements.</li>
+ *
+ * <li>An asymmetric key pair which is used to authenticate the credential to the Issuing
+ * Authority, called the <em>CredentialKey</em>.</li>
+ *
+ * <li>A set of zero or more named reader authentication public keys, which are used to
+ * authenticate an authorized reader to the credential.</li>
+ *
+ * <li>A set of named signing keys, which are used to sign collections of values and session
+ * transcripts.</li>
+ * </ul>
+ *
+ * <p>Implementing support for user identity documents in secure storage requires dedicated
+ * hardware-backed support and may not always be available.
+ *
+ * <p>Two different credential stores exist - the <em>default</em> store and the
+ * <em>direct access</em> store. Most often credentials will be accessed through the default
+ * store but that requires that the Android device be powered up and fully functional.
+ * It is desirable to allow identity credential usage when the Android device's battery is too
+ * low to boot the Android operating system, so direct access to the secure hardware via NFC
+ * may allow data retrieval, if the secure hardware chooses to implement it.
+ *
+ * <p>Credentials provisioned to the direct access store should <strong>always</strong> use reader
+ * authentication to protect data elements. The reason for this is user authentication or user
+ * approval of data release is not possible when the device is off.
+ */
+public abstract class IdentityCredentialStore {
+ IdentityCredentialStore() {}
+
+ /**
+ * Specifies that the cipher suite that will be used to secure communications between the reader
+ * is:
+ *
+ * <ul>
+ * <li>ECDHE with HKDF-SHA-256 for key agreement.</li>
+ * <li>AES-256 with GCM block mode for authenticated encryption (nonces are incremented by one
+ * for every message).</li>
+ * <li>ECDSA with SHA-256 for signing (used for signing session transcripts to defeat
+ * man-in-the-middle attacks), signing keys are not ephemeral. See {@link IdentityCredential}
+ * for details on reader and prover signing keys.</li>
+ * </ul>
+ *
+ * <p>
+ * At present this is the only supported cipher suite.
+ */
+ public static final int CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1;
+
+ /**
+ * Gets the default {@link IdentityCredentialStore}.
+ *
+ * @param context the application context.
+ * @return the {@link IdentityCredentialStore} or {@code null} if the device doesn't
+ * have hardware-backed support for secure storage of user identity documents.
+ */
+ public static @Nullable IdentityCredentialStore getInstance(@NonNull Context context) {
+ return CredstoreIdentityCredentialStore.getInstance(context);
+ }
+
+ /**
+ * Gets the {@link IdentityCredentialStore} for direct access.
+ *
+ * <p>Direct access requires specialized NFC hardware and may not be supported on all
+ * devices even if default store is available. Credentials provisioned to the direct
+ * access store should <strong>always</strong> use reader authentication to protect
+ * data elements.
+ *
+ * @param context the application context.
+ * @return the {@link IdentityCredentialStore} or {@code null} if direct access is not
+ * supported on this device.
+ */
+ public static @Nullable IdentityCredentialStore getDirectAccessInstance(@NonNull
+ Context context) {
+ return CredstoreIdentityCredentialStore.getDirectAccessInstance(context);
+ }
+
+ /**
+ * Gets a list of supported document types.
+ *
+ * <p>Only the direct-access store may restrict the kind of document types that can be used for
+ * credentials. The default store always supports any document type.
+ *
+ * @return The supported document types or the empty array if any document type is supported.
+ */
+ public abstract @NonNull String[] getSupportedDocTypes();
+
+ /**
+ * Creates a new credential.
+ *
+ * @param credentialName The name used to identify the credential.
+ * @param docType The document type for the credential.
+ * @return A @{link WritableIdentityCredential} that can be used to create a new credential.
+ * @throws AlreadyPersonalizedException if a credential with the given name already exists.
+ * @throws DocTypeNotSupportedException if the given document type isn't supported by the store.
+ */
+ public abstract @NonNull WritableIdentityCredential createCredential(
+ @NonNull String credentialName, @NonNull String docType)
+ throws AlreadyPersonalizedException, DocTypeNotSupportedException;
+
+ /**
+ * Retrieve a named credential.
+ *
+ * @param credentialName the name of the credential to retrieve.
+ * @param cipherSuite the cipher suite to use for communicating with the verifier.
+ * @return The named credential, or null if not found.
+ */
+ public abstract @Nullable IdentityCredential getCredentialByName(@NonNull String credentialName,
+ @Ciphersuite int cipherSuite)
+ throws CipherSuiteNotSupportedException;
+
+ /**
+ * Delete a named credential.
+ *
+ * <p>This method returns a COSE_Sign1 data structure signed by the CredentialKey
+ * with payload set to {@code ProofOfDeletion} as defined below:
+ *
+ * <pre>
+ * ProofOfDeletion = [
+ * "ProofOfDeletion", ; tstr
+ * tstr, ; DocType
+ * bool ; true if this is a test credential, should
+ * ; always be false.
+ * ]
+ * </pre>
+ *
+ * @param credentialName the name of the credential to delete.
+ * @return {@code null} if the credential was not found, the COSE_Sign1 data structure above
+ * if the credential was found and deleted.
+ */
+ public abstract @Nullable byte[] deleteCredentialByName(@NonNull String credentialName);
+
+ /** @hide */
+ @IntDef(value = {CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Ciphersuite {
+ }
+
+}
diff --git a/identity/java/android/security/identity/InvalidReaderSignatureException.java b/identity/java/android/security/identity/InvalidReaderSignatureException.java
new file mode 100644
index 0000000..3f70270
--- /dev/null
+++ b/identity/java/android/security/identity/InvalidReaderSignatureException.java
@@ -0,0 +1,46 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Thrown if the reader signature is invalid, or it doesn't contain a certificate chain, or if the
+ * signature failed to validate.
+ */
+public class InvalidReaderSignatureException extends IdentityCredentialException {
+ /**
+ * Constructs a new {@link InvalidReaderSignatureException} exception.
+ *
+ * @param message the detail message.
+ */
+ public InvalidReaderSignatureException(@NonNull String message) {
+ super(message);
+ }
+
+
+ /**
+ * Constructs a new {@link InvalidReaderSignatureException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public InvalidReaderSignatureException(@NonNull String message,
+ @NonNull Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/identity/java/android/security/identity/InvalidRequestMessageException.java b/identity/java/android/security/identity/InvalidRequestMessageException.java
new file mode 100644
index 0000000..b0c073c
--- /dev/null
+++ b/identity/java/android/security/identity/InvalidRequestMessageException.java
@@ -0,0 +1,46 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Thrown if message with the request doesn't satisfy the requirements documented in
+ * {@link IdentityCredential#getEntries(byte[], Map, byte[], byte[])}.
+ */
+public class InvalidRequestMessageException extends IdentityCredentialException {
+ /**
+ * Constructs a new {@link InvalidRequestMessageException} exception.
+ *
+ * @param message the detail message.
+ */
+ public InvalidRequestMessageException(@NonNull String message) {
+ super(message);
+ }
+
+
+ /**
+ * Constructs a new {@link InvalidRequestMessageException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public InvalidRequestMessageException(@NonNull String message,
+ @NonNull Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/identity/java/android/security/identity/MessageDecryptionException.java b/identity/java/android/security/identity/MessageDecryptionException.java
new file mode 100644
index 0000000..7a6169e
--- /dev/null
+++ b/identity/java/android/security/identity/MessageDecryptionException.java
@@ -0,0 +1,44 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Thrown when failing to decrypt a message from the reader device.
+ */
+public class MessageDecryptionException extends IdentityCredentialException {
+
+ /**
+ * Constructs a new {@link MessageDecryptionException} exception.
+ *
+ * @param message the detail message.
+ */
+ public MessageDecryptionException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@link MessageDecryptionException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public MessageDecryptionException(@NonNull String message, @NonNull Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/identity/java/android/security/identity/NoAuthenticationKeyAvailableException.java b/identity/java/android/security/identity/NoAuthenticationKeyAvailableException.java
new file mode 100644
index 0000000..7f40403
--- /dev/null
+++ b/identity/java/android/security/identity/NoAuthenticationKeyAvailableException.java
@@ -0,0 +1,46 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Thrown if no dynamic authentication keys are available.
+ */
+public class NoAuthenticationKeyAvailableException extends IdentityCredentialException {
+
+ /**
+ * Constructs a new {@link NoAuthenticationKeyAvailableException} exception.
+ *
+ * @param message the detail message.
+ */
+ public NoAuthenticationKeyAvailableException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@link NoAuthenticationKeyAvailableException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public NoAuthenticationKeyAvailableException(@NonNull String message,
+ @NonNull Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/identity/java/android/security/identity/PersonalizationData.java b/identity/java/android/security/identity/PersonalizationData.java
new file mode 100644
index 0000000..44370a1
--- /dev/null
+++ b/identity/java/android/security/identity/PersonalizationData.java
@@ -0,0 +1,157 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+
+/**
+ * An object that holds personalization data.
+ *
+ * This data includes access control profiles and a set of data entries and values, grouped by
+ * namespace.
+ *
+ * This is used to provision data into a {@link WritableIdentityCredential}.
+ *
+ * @see WritableIdentityCredential#personalize
+ */
+public class PersonalizationData {
+
+ private PersonalizationData() {
+ }
+
+ private LinkedList<AccessControlProfile> mProfiles = new LinkedList<>();
+
+ private LinkedHashMap<String, NamespaceData> mNamespaces = new LinkedHashMap<>();
+
+ Collection<AccessControlProfile> getAccessControlProfiles() {
+ return Collections.unmodifiableCollection(mProfiles);
+ }
+
+ Collection<String> getNamespaceNames() {
+ return Collections.unmodifiableCollection(mNamespaces.keySet());
+ }
+
+ NamespaceData getNamespaceData(String namespace) {
+ return mNamespaces.get(namespace);
+ }
+
+ static class NamespaceData {
+
+ private String mNamespace;
+ private LinkedHashMap<String, EntryData> mEntries = new LinkedHashMap<>();
+
+ private NamespaceData(String namespace) {
+ this.mNamespace = namespace;
+ }
+
+ String getNamespaceName() {
+ return mNamespace;
+ }
+
+ Collection<String> getEntryNames() {
+ return Collections.unmodifiableCollection(mEntries.keySet());
+ }
+
+ Collection<AccessControlProfileId> getAccessControlProfileIds(String name) {
+ EntryData value = mEntries.get(name);
+ if (value != null) {
+ return value.mAccessControlProfileIds;
+ }
+ return null;
+ }
+
+ byte[] getEntryValue(String name) {
+ EntryData value = mEntries.get(name);
+ if (value != null) {
+ return value.mValue;
+ }
+ return null;
+ }
+ }
+
+ private static class EntryData {
+ byte[] mValue;
+ Collection<AccessControlProfileId> mAccessControlProfileIds;
+
+ EntryData(byte[] value, Collection<AccessControlProfileId> accessControlProfileIds) {
+ this.mValue = value;
+ this.mAccessControlProfileIds = accessControlProfileIds;
+ }
+ }
+
+ /**
+ * A builder for {@link PersonalizationData}.
+ */
+ public static final class Builder {
+ private PersonalizationData mData;
+
+ /**
+ * Creates a new builder for a given namespace.
+ */
+ public Builder() {
+ this.mData = new PersonalizationData();
+ }
+
+ /**
+ * Adds a new entry to the builder.
+ *
+ * @param namespace The namespace to use, e.g. {@code org.iso.18013-5.2019}.
+ * @param name The name of the entry, e.g. {@code height}.
+ * @param accessControlProfileIds A set of access control profiles to use.
+ * @param value The value to add, in CBOR encoding.
+ * @return The builder.
+ */
+ public @NonNull Builder setEntry(@NonNull String namespace, @NonNull String name,
+ @NonNull Collection<AccessControlProfileId> accessControlProfileIds,
+ @NonNull byte[] value) {
+ NamespaceData namespaceData = mData.mNamespaces.get(namespace);
+ if (namespaceData == null) {
+ namespaceData = new NamespaceData(namespace);
+ mData.mNamespaces.put(namespace, namespaceData);
+ }
+ // TODO: validate/verify that value is proper CBOR.
+ namespaceData.mEntries.put(name, new EntryData(value, accessControlProfileIds));
+ return this;
+ }
+
+ /**
+ * Adds a new access control profile to the builder.
+ *
+ * @param profile The access control profile.
+ * @return The builder.
+ */
+ public @NonNull Builder addAccessControlProfile(@NonNull AccessControlProfile profile) {
+ mData.mProfiles.add(profile);
+ return this;
+ }
+
+ /**
+ * Creates a new {@link PersonalizationData} with all the entries added to the builder.
+ *
+ * @return A new {@link PersonalizationData} instance.
+ */
+ public @NonNull PersonalizationData build() {
+ return mData;
+ }
+ }
+
+}
diff --git a/identity/java/android/security/identity/ResultData.java b/identity/java/android/security/identity/ResultData.java
new file mode 100644
index 0000000..0982c8a
--- /dev/null
+++ b/identity/java/android/security/identity/ResultData.java
@@ -0,0 +1,224 @@
+/*
+ * 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 android.security.identity;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.lang.annotation.Retention;
+import java.util.Collection;
+
+/**
+ * An object that contains the result of retrieving data from a credential. This is used to return
+ * data requested from a {@link IdentityCredential}.
+ */
+public abstract class ResultData {
+
+ /** Value was successfully retrieved. */
+ public static final int STATUS_OK = 0;
+
+ /** Requested entry does not exist. */
+ public static final int STATUS_NO_SUCH_ENTRY = 1;
+
+ /** Requested entry was not requested. */
+ public static final int STATUS_NOT_REQUESTED = 2;
+
+ /** Requested entry wasn't in the request message. */
+ public static final int STATUS_NOT_IN_REQUEST_MESSAGE = 3;
+
+ /** The requested entry was not retrieved because user authentication wasn't performed. */
+ public static final int STATUS_USER_AUTHENTICATION_FAILED = 4;
+
+ /** The requested entry was not retrieved because reader authentication wasn't performed. */
+ public static final int STATUS_READER_AUTHENTICATION_FAILED = 5;
+
+ /**
+ * The requested entry was not retrieved because it was configured without any access
+ * control profile.
+ */
+ public static final int STATUS_NO_ACCESS_CONTROL_PROFILES = 6;
+
+ /**
+ * @hide
+ */
+ protected ResultData() {}
+
+ /**
+ * Returns a CBOR structure containing the retrieved data.
+ *
+ * <p>This structure - along with the session transcript - may be cryptographically
+ * authenticated to prove to the reader that the data is from a trusted credential and
+ * {@link #getMessageAuthenticationCode()} can be used to get a MAC.
+ *
+ * <p>The CBOR structure which is cryptographically authenticated is the
+ * {@code DeviceAuthentication} structure according to the following
+ * <a href="https://tools.ietf.org/html/draft-ietf-cbor-cddl-06">CDDL</a> schema:
+ *
+ * <pre>
+ * DeviceAuthentication = [
+ * "DeviceAuthentication",
+ * SessionTranscript,
+ * DocType,
+ * DeviceNameSpacesBytes
+ * ]
+ *
+ * DocType = tstr
+ *
+ * SessionTranscript = [
+ * DeviceEngagementBytes,
+ * EReaderKeyBytes
+ * ]
+ *
+ * DeviceEngagementBytes = #6.24(bstr .cbor DeviceEngagement)
+ * EReaderKeyBytes = #6.24(bstr .cbor EReaderKey.Pub)
+ *
+ * DeviceNameSpacesBytes = #6.24(bstr .cbor DeviceNameSpaces)
+ * </pre>
+ *
+ * where
+ *
+ * <pre>
+ * DeviceNameSpaces = {
+ * * NameSpace => DeviceSignedItems
+ * }
+ *
+ * DeviceSignedItems = {
+ * + DataItemName => DataItemValue
+ * }
+ *
+ * NameSpace = tstr
+ * DataItemName = tstr
+ * DataItemValue = any
+ * </pre>
+ *
+ * <p>The returned data is the binary encoding of the {@code DeviceNameSpaces} structure
+ * as defined above.
+ *
+ * @return The bytes of the {@code DeviceNameSpaces} CBOR structure.
+ */
+ public abstract @NonNull byte[] getAuthenticatedData();
+
+ /**
+ * Returns a message authentication code over the data returned by
+ * {@link #getAuthenticatedData}, to prove to the reader that the data is from a trusted
+ * credential.
+ *
+ * <p>The MAC proves to the reader that the data is from a trusted credential. This code is
+ * produced by using the key agreement and key derivation function from the ciphersuite
+ * with the authentication private key and the reader ephemeral public key to compute a
+ * shared message authentication code (MAC) key, then using the MAC function from the
+ * ciphersuite to compute a MAC of the authenticated data.
+ *
+ * <p>If the {@code sessionTranscript} parameter passed to
+ * {@link IdentityCredential#getEntries(byte[], Map, byte[], byte[])} was {@code null}
+ * or the reader ephmeral public key was never set using
+ * {@link IdentityCredential#setReaderEphemeralPublicKey(PublicKey)}, no message
+ * authencation code will be produced and this method will return {@code null}.
+ *
+ * @return A COSE_Mac0 structure with the message authentication code as described above
+ * or {@code null} if the conditions specified above are not met.
+ */
+ public abstract @Nullable byte[] getMessageAuthenticationCode();
+
+ /**
+ * Returns the static authentication data associated with the dynamic authentication
+ * key used to sign or MAC the data returned by {@link #getAuthenticatedData()}.
+ *
+ * @return The static authentication data associated with dynamic authentication key used to
+ * MAC the data.
+ */
+ public abstract @NonNull byte[] getStaticAuthenticationData();
+
+ /**
+ * Gets the names of namespaces with retrieved entries.
+ *
+ * @return collection of name of namespaces containing retrieved entries. May be empty if no
+ * data was retrieved.
+ */
+ public abstract @NonNull Collection<String> getNamespaceNames();
+
+ /**
+ * Get the names of all entries.
+ *
+ * This includes the name of entries that wasn't successfully retrieved.
+ *
+ * @param namespaceName the namespace name to get entries for.
+ * @return A collection of names or {@code null} if there are no entries for the given
+ * namespace.
+ */
+ public abstract @Nullable Collection<String> getEntryNames(@NonNull String namespaceName);
+
+ /**
+ * Get the names of all entries that was successfully retrieved.
+ *
+ * This only return entries for which {@link #getStatus(String, String)} will return
+ * {@link #STATUS_OK}.
+ *
+ * @param namespaceName the namespace name to get entries for.
+ * @return A collection of names or {@code null} if there are no entries for the given
+ * namespace.
+ */
+ public abstract @Nullable Collection<String> getRetrievedEntryNames(
+ @NonNull String namespaceName);
+
+ /**
+ * Gets the status of an entry.
+ *
+ * This returns {@link #STATUS_OK} if the value was retrieved, {@link #STATUS_NO_SUCH_ENTRY}
+ * if the given entry wasn't retrieved, {@link #STATUS_NOT_REQUESTED} if it wasn't requested,
+ * {@link #STATUS_NOT_IN_REQUEST_MESSAGE} if the request message was set but the entry wasn't
+ * present in the request message,
+ * {@link #STATUS_USER_AUTHENTICATION_FAILED} if the value
+ * wasn't retrieved because the necessary user authentication wasn't performed,
+ * {@link #STATUS_READER_AUTHENTICATION_FAILED} if the supplied reader certificate chain
+ * didn't match the set of certificates the entry was provisioned with, or
+ * {@link #STATUS_NO_ACCESS_CONTROL_PROFILES} if the entry was configured without any
+ * access control profiles.
+ *
+ * @param namespaceName the namespace name of the entry.
+ * @param name the name of the entry to get the value for.
+ * @return the status indicating whether the value was retrieved and if not, why.
+ */
+ @Status
+ public abstract int getStatus(@NonNull String namespaceName, @NonNull String name);
+
+ /**
+ * Gets the raw CBOR data for the value of an entry.
+ *
+ * This should only be called on an entry for which the {@link #getStatus(String, String)}
+ * method returns {@link #STATUS_OK}.
+ *
+ * @param namespaceName the namespace name of the entry.
+ * @param name the name of the entry to get the value for.
+ * @return the raw CBOR data or {@code null} if no entry with the given name exists.
+ */
+ public abstract @Nullable byte[] getEntry(@NonNull String namespaceName, @NonNull String name);
+
+ /**
+ * The type of the entry status.
+ * @hide
+ */
+ @Retention(SOURCE)
+ @IntDef({STATUS_OK, STATUS_NO_SUCH_ENTRY, STATUS_NOT_REQUESTED, STATUS_NOT_IN_REQUEST_MESSAGE,
+ STATUS_USER_AUTHENTICATION_FAILED, STATUS_READER_AUTHENTICATION_FAILED,
+ STATUS_NO_ACCESS_CONTROL_PROFILES})
+ public @interface Status {
+ }
+}
diff --git a/identity/java/android/security/identity/SessionTranscriptMismatchException.java b/identity/java/android/security/identity/SessionTranscriptMismatchException.java
new file mode 100644
index 0000000..8c24060
--- /dev/null
+++ b/identity/java/android/security/identity/SessionTranscriptMismatchException.java
@@ -0,0 +1,44 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Thrown when trying use multiple different session transcripts in the same presentation session.
+ */
+public class SessionTranscriptMismatchException extends IdentityCredentialException {
+
+ /**
+ * Constructs a new {@link SessionTranscriptMismatchException} exception.
+ *
+ * @param message the detail message.
+ */
+ public SessionTranscriptMismatchException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@link SessionTranscriptMismatchException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public SessionTranscriptMismatchException(@NonNull String message, @NonNull Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/identity/java/android/security/identity/UnknownAuthenticationKeyException.java b/identity/java/android/security/identity/UnknownAuthenticationKeyException.java
new file mode 100644
index 0000000..f454b2c
--- /dev/null
+++ b/identity/java/android/security/identity/UnknownAuthenticationKeyException.java
@@ -0,0 +1,43 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+/**
+ * Thrown if trying to certify an unknown dynamic authentication key.
+ */
+public class UnknownAuthenticationKeyException extends IdentityCredentialException {
+ /**
+ * Constructs a new {@link UnknownAuthenticationKeyException} exception.
+ *
+ * @param message the detail message.
+ */
+ public UnknownAuthenticationKeyException(@NonNull String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@link UnknownAuthenticationKeyException} exception.
+ *
+ * @param message the detail message.
+ * @param cause the cause.
+ */
+ public UnknownAuthenticationKeyException(@NonNull String message, @NonNull Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/identity/java/android/security/identity/Util.java b/identity/java/android/security/identity/Util.java
new file mode 100644
index 0000000..6eefeb8
--- /dev/null
+++ b/identity/java/android/security/identity/Util.java
@@ -0,0 +1,140 @@
+/*
+ * 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.security.identity;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECPoint;
+import java.util.Collection;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+class Util {
+ private static final String TAG = "Util";
+
+ static int[] integerCollectionToArray(Collection<Integer> collection) {
+ int[] result = new int[collection.size()];
+ int n = 0;
+ for (int item : collection) {
+ result[n++] = item;
+ }
+ return result;
+ }
+
+ static byte[] stripLeadingZeroes(byte[] value) {
+ int n = 0;
+ while (n < value.length && value[n] == 0) {
+ n++;
+ }
+ int newLen = value.length - n;
+ byte[] ret = new byte[newLen];
+ int m = 0;
+ while (n < value.length) {
+ ret[m++] = value[n++];
+ }
+ return ret;
+ }
+
+ static byte[] publicKeyEncodeUncompressedForm(PublicKey publicKey) {
+ ECPoint w = ((ECPublicKey) publicKey).getW();
+ // X and Y are always positive so for interop we remove any leading zeroes
+ // inserted by the BigInteger encoder.
+ byte[] x = stripLeadingZeroes(w.getAffineX().toByteArray());
+ byte[] y = stripLeadingZeroes(w.getAffineY().toByteArray());
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ baos.write(0x04);
+ baos.write(x);
+ baos.write(y);
+ return baos.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException("Unexpected IOException", e);
+ }
+ }
+
+ /**
+ * Computes an HKDF.
+ *
+ * This is based on https://github.com/google/tink/blob/master/java/src/main/java/com/google
+ * /crypto/tink/subtle/Hkdf.java
+ * which is also Copyright (c) Google and also licensed under the Apache 2 license.
+ *
+ * @param macAlgorithm the MAC algorithm used for computing the Hkdf. I.e., "HMACSHA1" or
+ * "HMACSHA256".
+ * @param ikm the input keying material.
+ * @param salt optional salt. A possibly non-secret random value. If no salt is
+ * provided (i.e. if
+ * salt has length 0) then an array of 0s of the same size as the hash
+ * digest is used as salt.
+ * @param info optional context and application specific information.
+ * @param size The length of the generated pseudorandom string in bytes. The maximal
+ * size is
+ * 255.DigestSize, where DigestSize is the size of the underlying HMAC.
+ * @return size pseudorandom bytes.
+ */
+ static byte[] computeHkdf(
+ String macAlgorithm, final byte[] ikm, final byte[] salt, final byte[] info, int size) {
+ Mac mac = null;
+ try {
+ mac = Mac.getInstance(macAlgorithm);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("No such algorithm: " + macAlgorithm, e);
+ }
+ if (size > 255 * mac.getMacLength()) {
+ throw new RuntimeException("size too large");
+ }
+ try {
+ if (salt == null || salt.length == 0) {
+ // According to RFC 5869, Section 2.2 the salt is optional. If no salt is provided
+ // then HKDF uses a salt that is an array of zeros of the same length as the hash
+ // digest.
+ mac.init(new SecretKeySpec(new byte[mac.getMacLength()], macAlgorithm));
+ } else {
+ mac.init(new SecretKeySpec(salt, macAlgorithm));
+ }
+ byte[] prk = mac.doFinal(ikm);
+ byte[] result = new byte[size];
+ int ctr = 1;
+ int pos = 0;
+ mac.init(new SecretKeySpec(prk, macAlgorithm));
+ byte[] digest = new byte[0];
+ while (true) {
+ mac.update(digest);
+ mac.update(info);
+ mac.update((byte) ctr);
+ digest = mac.doFinal();
+ if (pos + digest.length < size) {
+ System.arraycopy(digest, 0, result, pos, digest.length);
+ pos += digest.length;
+ ctr++;
+ } else {
+ System.arraycopy(digest, 0, result, pos, size - pos);
+ break;
+ }
+ }
+ return result;
+ } catch (InvalidKeyException e) {
+ throw new RuntimeException("Error MACing", e);
+ }
+ }
+
+}
diff --git a/identity/java/android/security/identity/WritableIdentityCredential.java b/identity/java/android/security/identity/WritableIdentityCredential.java
new file mode 100644
index 0000000..e2a389b
--- /dev/null
+++ b/identity/java/android/security/identity/WritableIdentityCredential.java
@@ -0,0 +1,116 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+
+/**
+ * Class used to personalize a new identity credential.
+ *
+ * <p>Credentials cannot be updated or modified after creation; any changes require deletion and
+ * re-creation.
+ *
+ * Use {@link IdentityCredentialStore#createCredential(String, String)} to create a new credential.
+ */
+public abstract class WritableIdentityCredential {
+ /**
+ * @hide
+ */
+ protected WritableIdentityCredential() {}
+
+ /**
+ * Generates and returns an X.509 certificate chain for the CredentialKey which identifies this
+ * credential to the issuing authority. The certificate contains an
+ * <a href="https://source.android.com/security/keystore/attestation">Android Keystore</a>
+ * attestation extension which describes the key and the security hardware in which it lives.
+ *
+ * <p>Additionally, the attestation extension will contain the tag TODO_IC_KEY which indicates
+ * it is an Identity Credential key (which can only sign/MAC very specific messages) and not
+ * an Android Keystore key (which can be used to sign/MAC anything).
+ *
+ * <p>The issuer <b>MUST</b> carefully examine this certificate chain including (but not
+ * limited to) checking that the root certificate is well-known, the tag TODO_IC_KEY is
+ * present, the passed in challenge is present, the device has verified boot enabled, that each
+ * certificate in the chain is signed by its successor, that none of the certificates have been
+ * revoked and so on.
+ *
+ * <p>It is not strictly necessary to use this method to provision a credential if the issuing
+ * authority doesn't care about the nature of the security hardware. If called, however, this
+ * method must be called before {@link #personalize(PersonalizationData)}.
+ *
+ * @param challenge is a byte array whose contents should be unique, fresh and provided by
+ * the issuing authority. The value provided is embedded in the attestation
+ * extension and enables the issuing authority to verify that the attestation
+ * certificate is fresh.
+ * @return the X.509 certificate for this credential's CredentialKey.
+ */
+ public abstract @NonNull Collection<X509Certificate> getCredentialKeyCertificateChain(
+ @NonNull byte[] challenge);
+
+ /**
+ * Stores all of the data in the credential, with the specified access control profiles.
+ *
+ * <p>This method returns a COSE_Sign1 data structure signed by the CredentialKey with payload
+ * set to {@code ProofOfProvisioning} as defined below.
+ *
+ * <pre>
+ * ProofOfProvisioning = [
+ * "ProofOfProvisioning", ; tstr
+ * tstr, ; DocType
+ * [ * AccessControlProfile ],
+ * ProvisionedData,
+ * bool ; true if this is a test credential, should
+ * ; always be false.
+ * ]
+ *
+ * AccessControlProfile = {
+ * "id": uint,
+ * ? "readerCertificate" : bstr,
+ * ? (
+ * "userAuthenticationRequired" : bool,
+ * "timeoutMillis" : uint,
+ * )
+ * }
+ *
+ * ProvisionedData = {
+ * * Namespace => [ + Entry ]
+ * },
+ *
+ * Namespace = tstr
+ *
+ * Entry = {
+ * "name" : tstr,
+ * "value" : any,
+ * "accessControlProfiles" : [ * uint ],
+ * }
+ * </pre>
+ *
+ * <p>This data structure provides a guarantee to the issuer about the data which may be
+ * returned in the CBOR returned by
+ * {@link ResultData#getAuthenticatedData()} during a credential
+ * presentation.
+ *
+ * @param personalizationData The data to provision, including access control profiles
+ * and data elements and their values, grouped into namespaces.
+ * @return A COSE_Sign1 data structure, see above.
+ */
+ public abstract @NonNull byte[] personalize(
+ @NonNull PersonalizationData personalizationData);
+}
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index fad7d80..7282bcf 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -16,7 +16,7 @@
package android.security;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.org.bouncycastle.util.io.pem.PemObject;
import com.android.org.bouncycastle.util.io.pem.PemReader;
diff --git a/keystore/java/android/security/GateKeeper.java b/keystore/java/android/security/GateKeeper.java
index a50ff79..af188a9 100644
--- a/keystore/java/android/security/GateKeeper.java
+++ b/keystore/java/android/security/GateKeeper.java
@@ -16,7 +16,7 @@
package android.security;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index c0a0422..e9bc802 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -16,10 +16,10 @@
package android.security;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.Application;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.face.FaceManager;
@@ -31,7 +31,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.security.KeyStoreException;
import android.security.keymaster.ExportResult;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
index c6515ef..feb6101 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
@@ -176,7 +176,7 @@
KeyStore keyStore, IBinder operationToken) {
KeyStoreCryptoOperationStreamer streamer = new KeyStoreCryptoOperationChunkedStreamer(
new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
- keyStore, operationToken));
+ keyStore, operationToken), 0);
if (isEncrypting()) {
return streamer;
} else {
@@ -191,7 +191,7 @@
protected final KeyStoreCryptoOperationStreamer createAdditionalAuthenticationDataStreamer(
KeyStore keyStore, IBinder operationToken) {
return new KeyStoreCryptoOperationChunkedStreamer(
- new AdditionalAuthenticationDataStream(keyStore, operationToken));
+ new AdditionalAuthenticationDataStream(keyStore, operationToken), 0);
}
@Override
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
index 5bcb34a..ccc3153 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
@@ -299,7 +299,7 @@
KeyStore keyStore, IBinder operationToken) {
return new KeyStoreCryptoOperationChunkedStreamer(
new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
- keyStore, operationToken));
+ keyStore, operationToken), 0);
}
/**
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index 234615d..8be85d6 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -17,7 +17,7 @@
package android.security.keystore;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.security.KeyStore;
import android.security.keymaster.ExportResult;
import android.security.keymaster.KeyCharacteristics;
diff --git a/keystore/java/android/security/keystore/ArrayUtils.java b/keystore/java/android/security/keystore/ArrayUtils.java
index 26172d2..f519c7c 100644
--- a/keystore/java/android/security/keystore/ArrayUtils.java
+++ b/keystore/java/android/security/keystore/ArrayUtils.java
@@ -55,6 +55,34 @@
}
}
+ /**
+ * Copies a subset of the source array to the destination array.
+ * Length will be limited to the bounds of source and destination arrays.
+ * The length actually copied is returned, which will be <= length argument.
+ * @param src is the source array
+ * @param srcOffset is the offset in the source array.
+ * @param dst is the destination array.
+ * @param dstOffset is the offset in the destination array.
+ * @param length is the length to be copied from source to destination array.
+ * @return The length actually copied from source array.
+ */
+ public static int copy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int length) {
+ if (dst == null || src == null) {
+ return 0;
+ }
+ if (length > dst.length - dstOffset) {
+ length = dst.length - dstOffset;
+ }
+ if (length > src.length - srcOffset) {
+ length = src.length - srcOffset;
+ }
+ if (length <= 0) {
+ return 0;
+ }
+ System.arraycopy(src, srcOffset, dst, dstOffset, length);
+ return length;
+ }
+
public static byte[] subarray(byte[] arr, int offset, int len) {
if (len == 0) {
return EmptyArray.BYTE;
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index e3f43ef..630a6dd 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -20,8 +20,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.security.GateKeeper;
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
index 75bea26..2c0f40d 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
@@ -24,19 +24,20 @@
import libcore.util.EmptyArray;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.ProviderException;
-
/**
* Helper for streaming a crypto operation's input and output via {@link KeyStore} service's
* {@code update} and {@code finish} operations.
*
- * <p>The helper abstracts away to issues that need to be solved in most code that uses KeyStore's
+ * <p>The helper abstracts away issues that need to be solved in most code that uses KeyStore's
* update and finish operations. Firstly, KeyStore's update operation can consume only a limited
* amount of data in one go because the operations are marshalled via Binder. Secondly, the update
* operation may consume less data than provided, in which case the caller has to buffer the
- * remainder for next time. The helper exposes {@link #update(byte[], int, int) update} and
+ * remainder for next time. Thirdly, when the input is smaller than a threshold, skipping update
+ * and passing input data directly to final improves performance. This threshold is configurable;
+ * using a threshold <= 1 causes the helper act eagerly, which may be required for some types of
+ * operations (e.g. ciphers).
+ *
+ * <p>The helper exposes {@link #update(byte[], int, int) update} and
* {@link #doFinal(byte[], int, int, byte[], byte[]) doFinal} operations which can be used to
* conveniently implement various JCA crypto primitives.
*
@@ -67,240 +68,122 @@
// Binder buffer is about 1MB, but it's shared between all active transactions of the process.
// Thus, it's safer to use a much smaller upper bound.
- private static final int DEFAULT_MAX_CHUNK_SIZE = 64 * 1024;
+ private static final int DEFAULT_CHUNK_SIZE_MAX = 64 * 1024;
+ // The chunk buffer will be sent to update until its size under this threshold.
+ // This threshold should be <= the max input allowed for finish.
+ // Setting this threshold <= 1 will effectivley disable buffering between updates.
+ private static final int DEFAULT_CHUNK_SIZE_THRESHOLD = 2 * 1024;
private final Stream mKeyStoreStream;
- private final int mMaxChunkSize;
-
- private byte[] mBuffered = EmptyArray.BYTE;
- private int mBufferedOffset;
- private int mBufferedLength;
+ private final int mChunkSizeMax;
+ private final int mChunkSizeThreshold;
+ private final byte[] mChunk;
+ private int mChunkLength = 0;
private long mConsumedInputSizeBytes;
private long mProducedOutputSizeBytes;
- public KeyStoreCryptoOperationChunkedStreamer(Stream operation) {
- this(operation, DEFAULT_MAX_CHUNK_SIZE);
+ KeyStoreCryptoOperationChunkedStreamer(Stream operation) {
+ this(operation, DEFAULT_CHUNK_SIZE_THRESHOLD, DEFAULT_CHUNK_SIZE_MAX);
}
- public KeyStoreCryptoOperationChunkedStreamer(Stream operation, int maxChunkSize) {
+ KeyStoreCryptoOperationChunkedStreamer(Stream operation, int chunkSizeThreshold) {
+ this(operation, chunkSizeThreshold, DEFAULT_CHUNK_SIZE_MAX);
+ }
+
+ KeyStoreCryptoOperationChunkedStreamer(Stream operation, int chunkSizeThreshold,
+ int chunkSizeMax) {
mKeyStoreStream = operation;
- mMaxChunkSize = maxChunkSize;
+ mChunkSizeMax = chunkSizeMax;
+ if (chunkSizeThreshold <= 0) {
+ mChunkSizeThreshold = 1;
+ } else if (chunkSizeThreshold > chunkSizeMax) {
+ mChunkSizeThreshold = chunkSizeMax;
+ } else {
+ mChunkSizeThreshold = chunkSizeThreshold;
+ }
+ mChunk = new byte[mChunkSizeMax];
}
- @Override
public byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException {
- if (inputLength == 0) {
+ if (inputLength == 0 || input == null) {
// No input provided
return EmptyArray.BYTE;
}
+ if (inputLength < 0 || inputOffset < 0 || (inputOffset + inputLength) > input.length) {
+ throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
+ "Input offset and length out of bounds of input array");
+ }
- ByteArrayOutputStream bufferedOutput = null;
+ byte[] output = EmptyArray.BYTE;
- while (inputLength > 0) {
- byte[] chunk;
- int inputBytesInChunk;
- if ((mBufferedLength + inputLength) > mMaxChunkSize) {
- // Too much input for one chunk -- extract one max-sized chunk and feed it into the
- // update operation.
- inputBytesInChunk = mMaxChunkSize - mBufferedLength;
- chunk = ArrayUtils.concat(mBuffered, mBufferedOffset, mBufferedLength,
- input, inputOffset, inputBytesInChunk);
- } else {
- // All of available input fits into one chunk.
- if ((mBufferedLength == 0) && (inputOffset == 0)
- && (inputLength == input.length)) {
- // Nothing buffered and all of input array needs to be fed into the update
- // operation.
- chunk = input;
- inputBytesInChunk = input.length;
- } else {
- // Need to combine buffered data with input data into one array.
- inputBytesInChunk = inputLength;
- chunk = ArrayUtils.concat(mBuffered, mBufferedOffset, mBufferedLength,
- input, inputOffset, inputBytesInChunk);
+ while (inputLength > 0 || mChunkLength >= mChunkSizeThreshold) {
+ int inputConsumed = ArrayUtils.copy(input, inputOffset, mChunk, mChunkLength,
+ inputLength);
+ inputLength -= inputConsumed;
+ inputOffset += inputConsumed;
+ mChunkLength += inputConsumed;
+ mConsumedInputSizeBytes += inputConsumed;
+
+ if (mChunkLength > mChunkSizeMax) {
+ throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
+ "Chunk size exceeded max chunk size. Max: " + mChunkSizeMax
+ + " Actual: " + mChunkLength);
+ }
+
+ if (mChunkLength >= mChunkSizeThreshold) {
+ OperationResult opResult = mKeyStoreStream.update(
+ ArrayUtils.subarray(mChunk, 0, mChunkLength));
+
+ if (opResult == null) {
+ throw new KeyStoreConnectException();
+ } else if (opResult.resultCode != KeyStore.NO_ERROR) {
+ throw KeyStore.getKeyStoreException(opResult.resultCode);
}
- }
- // Update input array references to reflect that some of its bytes are now in mBuffered.
- inputOffset += inputBytesInChunk;
- inputLength -= inputBytesInChunk;
- mConsumedInputSizeBytes += inputBytesInChunk;
-
- OperationResult opResult = mKeyStoreStream.update(chunk);
- if (opResult == null) {
- throw new KeyStoreConnectException();
- } else if (opResult.resultCode != KeyStore.NO_ERROR) {
- throw KeyStore.getKeyStoreException(opResult.resultCode);
- }
-
- if (opResult.inputConsumed == chunk.length) {
- // The whole chunk was consumed
- mBuffered = EmptyArray.BYTE;
- mBufferedOffset = 0;
- mBufferedLength = 0;
- } else if (opResult.inputConsumed <= 0) {
- // Nothing was consumed. More input needed.
- if (inputLength > 0) {
- // More input is available, but it wasn't included into the previous chunk
- // because the chunk reached its maximum permitted size.
- // Shouldn't have happened.
+ if (opResult.inputConsumed <= 0) {
+ throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
+ "Keystore consumed 0 of " + mChunkLength + " bytes provided.");
+ } else if (opResult.inputConsumed > mChunkLength) {
throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
- "Keystore consumed nothing from max-sized chunk: " + chunk.length
- + " bytes");
+ "Keystore consumed more input than provided. Provided: "
+ + mChunkLength + ", consumed: " + opResult.inputConsumed);
}
- mBuffered = chunk;
- mBufferedOffset = 0;
- mBufferedLength = chunk.length;
- } else if (opResult.inputConsumed < chunk.length) {
- // The chunk was consumed only partially -- buffer the rest of the chunk
- mBuffered = chunk;
- mBufferedOffset = opResult.inputConsumed;
- mBufferedLength = chunk.length - opResult.inputConsumed;
- } else {
- throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
- "Keystore consumed more input than provided. Provided: " + chunk.length
- + ", consumed: " + opResult.inputConsumed);
- }
+ mChunkLength -= opResult.inputConsumed;
- if ((opResult.output != null) && (opResult.output.length > 0)) {
- if (inputLength + mBufferedLength > 0) {
- // More output might be produced in this loop -- buffer the current output
- if (bufferedOutput == null) {
- bufferedOutput = new ByteArrayOutputStream();
- }
- try {
- bufferedOutput.write(opResult.output);
- } catch (IOException e) {
- throw new ProviderException("Failed to buffer output", e);
- }
- } else {
- // No more output will be produced in this loop
- byte[] result;
- if (bufferedOutput == null) {
- // No previously buffered output
- result = opResult.output;
- } else {
- // There was some previously buffered output
- try {
- bufferedOutput.write(opResult.output);
- } catch (IOException e) {
- throw new ProviderException("Failed to buffer output", e);
- }
- result = bufferedOutput.toByteArray();
- }
- mProducedOutputSizeBytes += result.length;
- return result;
+ if (mChunkLength > 0) {
+ // Partialy consumed, shift chunk contents
+ ArrayUtils.copy(mChunk, opResult.inputConsumed, mChunk, 0, mChunkLength);
+ }
+
+ if ((opResult.output != null) && (opResult.output.length > 0)) {
+ // Output was produced
+ mProducedOutputSizeBytes += opResult.output.length;
+ output = ArrayUtils.concat(output, opResult.output);
}
}
}
-
- byte[] result;
- if (bufferedOutput == null) {
- // No output produced
- result = EmptyArray.BYTE;
- } else {
- result = bufferedOutput.toByteArray();
- }
- mProducedOutputSizeBytes += result.length;
- return result;
+ return output;
}
- @Override
public byte[] doFinal(byte[] input, int inputOffset, int inputLength,
byte[] signature, byte[] additionalEntropy) throws KeyStoreException {
- if (inputLength == 0) {
- // No input provided -- simplify the rest of the code
- input = EmptyArray.BYTE;
- inputOffset = 0;
- }
-
- // Flush all buffered input and provided input into keystore/keymaster.
byte[] output = update(input, inputOffset, inputLength);
- output = ArrayUtils.concat(output, flush());
+ byte[] finalChunk = ArrayUtils.subarray(mChunk, 0, mChunkLength);
+ OperationResult opResult = mKeyStoreStream.finish(finalChunk, signature, additionalEntropy);
- OperationResult opResult = mKeyStoreStream.finish(EmptyArray.BYTE, signature,
- additionalEntropy);
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
throw KeyStore.getKeyStoreException(opResult.resultCode);
}
- mProducedOutputSizeBytes += opResult.output.length;
+ // If no error, assume all input consumed
+ mConsumedInputSizeBytes += finalChunk.length;
- return ArrayUtils.concat(output, opResult.output);
- }
-
- public byte[] flush() throws KeyStoreException {
- if (mBufferedLength <= 0) {
- return EmptyArray.BYTE;
+ if ((opResult.output != null) && (opResult.output.length > 0)) {
+ mProducedOutputSizeBytes += opResult.output.length;
+ output = ArrayUtils.concat(output, opResult.output);
}
- // Keep invoking the update operation with remaining buffered data until either all of the
- // buffered data is consumed or until update fails to consume anything.
- ByteArrayOutputStream bufferedOutput = null;
- while (mBufferedLength > 0) {
- byte[] chunk = ArrayUtils.subarray(mBuffered, mBufferedOffset, mBufferedLength);
- OperationResult opResult = mKeyStoreStream.update(chunk);
- if (opResult == null) {
- throw new KeyStoreConnectException();
- } else if (opResult.resultCode != KeyStore.NO_ERROR) {
- throw KeyStore.getKeyStoreException(opResult.resultCode);
- }
-
- if (opResult.inputConsumed <= 0) {
- // Nothing was consumed. Break out of the loop to avoid an infinite loop.
- break;
- }
-
- if (opResult.inputConsumed >= chunk.length) {
- // All of the input was consumed
- mBuffered = EmptyArray.BYTE;
- mBufferedOffset = 0;
- mBufferedLength = 0;
- } else {
- // Some of the input was not consumed
- mBuffered = chunk;
- mBufferedOffset = opResult.inputConsumed;
- mBufferedLength = chunk.length - opResult.inputConsumed;
- }
-
- if (opResult.inputConsumed > chunk.length) {
- throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
- "Keystore consumed more input than provided. Provided: "
- + chunk.length + ", consumed: " + opResult.inputConsumed);
- }
-
- if ((opResult.output != null) && (opResult.output.length > 0)) {
- // Some output was produced by this update operation
- if (bufferedOutput == null) {
- // No output buffered yet.
- if (mBufferedLength == 0) {
- // No more output will be produced by this flush operation
- mProducedOutputSizeBytes += opResult.output.length;
- return opResult.output;
- } else {
- // More output might be produced by this flush operation -- buffer output.
- bufferedOutput = new ByteArrayOutputStream();
- }
- }
- // Buffer the output from this update operation
- try {
- bufferedOutput.write(opResult.output);
- } catch (IOException e) {
- throw new ProviderException("Failed to buffer output", e);
- }
- }
- }
-
- if (mBufferedLength > 0) {
- throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
- "Keystore failed to consume last "
- + ((mBufferedLength != 1) ? (mBufferedLength + " bytes") : "byte")
- + " of input");
- }
-
- byte[] result = (bufferedOutput != null) ? bufferedOutput.toByteArray() : EmptyArray.BYTE;
- mProducedOutputSizeBytes += result.length;
- return result;
+ return output;
}
@Override
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 4c08a38..98de9c3 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -25,11 +25,6 @@
// GCC false-positives on this warning, and since we -Werror that's
// a problem
"-Wno-free-nonheap-object",
-
- // Clang is producing non-determistic binary when the new pass manager is
- // enabled. Disable the new PM as a temporary workaround.
- // b/142372146
- "-fno-experimental-new-pass-manager",
],
include_dirs: [
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 219d040..c21bdca 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -219,7 +219,7 @@
Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info, BitmapPalette palette)
: SkPixelRef(info.width(), info.height(), nullptr,
- bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride())
+ bytesPerPixel(buffer->getPixelFormat()) * (buffer->getStride() > 0 ? buffer->getStride() : buffer->getWidth()))
, mInfo(validateAlpha(info))
, mPixelStorageType(PixelStorageType::Hardware)
, mPalette(palette)
diff --git a/location/java/android/location/Country.java b/location/java/android/location/Country.java
index f3c2a16..8c40338 100644
--- a/location/java/android/location/Country.java
+++ b/location/java/android/location/Country.java
@@ -16,7 +16,7 @@
package android.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
diff --git a/location/java/android/location/CountryDetector.java b/location/java/android/location/CountryDetector.java
index ae13949..e344b82 100644
--- a/location/java/android/location/CountryDetector.java
+++ b/location/java/android/location/CountryDetector.java
@@ -16,10 +16,8 @@
package android.location;
-import java.util.HashMap;
-
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
@@ -27,6 +25,8 @@
import android.os.RemoteException;
import android.util.Log;
+import java.util.HashMap;
+
/**
* This class provides access to the system country detector service. This
* service allows applications to obtain the country that the user is in.
diff --git a/location/java/android/location/CountryListener.java b/location/java/android/location/CountryListener.java
index 70a83c5..eb67205 100644
--- a/location/java/android/location/CountryListener.java
+++ b/location/java/android/location/CountryListener.java
@@ -16,7 +16,7 @@
package android.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The listener for receiving the notification when the country is detected or
diff --git a/location/java/android/location/GeocoderParams.java b/location/java/android/location/GeocoderParams.java
index 45d92ee..1c6e9b6 100644
--- a/location/java/android/location/GeocoderParams.java
+++ b/location/java/android/location/GeocoderParams.java
@@ -16,7 +16,7 @@
package android.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java
index 9570b26..af57bfd 100644
--- a/location/java/android/location/Geofence.java
+++ b/location/java/android/location/Geofence.java
@@ -16,7 +16,7 @@
package android.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 609a15e..8a5edc4 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -16,7 +16,7 @@
package android.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.util.SparseArray;
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 9c36d76..6f12c78 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -18,7 +18,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 7b24f44..f17f748 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -30,8 +30,8 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 0902acf..adea73d 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -22,7 +22,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index f9b2fe0..9846436 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -19,6 +19,7 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -37,8 +38,6 @@
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.telephony.GsmAlphabet;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeUnit;
@@ -126,7 +125,7 @@
public static class GpsNiNotification
{
- @android.annotation.UnsupportedAppUsage
+ @android.compat.annotation.UnsupportedAppUsage
public GpsNiNotification() {
}
public int notificationId;
diff --git a/location/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java
index 155f788..c23f499 100644
--- a/location/java/com/android/internal/location/ProviderRequest.java
+++ b/location/java/com/android/internal/location/ProviderRequest.java
@@ -16,7 +16,7 @@
package com.android.internal.location;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.location.LocationRequest;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/media/OWNERS b/media/OWNERS
index 8bd037a..be60583 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -5,6 +5,7 @@
etalvala@google.com
gkasten@google.com
hdmoon@google.com
+hkuang@google.com
hunga@google.com
insun@google.com
jaewan@google.com
diff --git a/media/java/android/media/AmrInputStream.java b/media/java/android/media/AmrInputStream.java
index 5088798..3cb224d 100644
--- a/media/java/android/media/AmrInputStream.java
+++ b/media/java/android/media/AmrInputStream.java
@@ -16,14 +16,14 @@
package android.media;
-import java.io.InputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.MediaCodec.BufferInfo;
import android.util.Log;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
/**
* DO NOT USE
diff --git a/media/java/android/media/AsyncPlayer.java b/media/java/android/media/AsyncPlayer.java
index 8ac2655..c3dc118 100644
--- a/media/java/android/media/AsyncPlayer.java
+++ b/media/java/android/media/AsyncPlayer.java
@@ -17,9 +17,8 @@
package android.media;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.media.PlayerBase;
import android.net.Uri;
import android.os.PowerManager;
import android.os.SystemClock;
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 820d82d..bb87404 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.audiopolicy.AudioProductStrategy;
import android.os.Build;
import android.os.Bundle;
diff --git a/media/java/android/media/AudioDeviceAddress.aidl b/media/java/android/media/AudioDeviceAddress.aidl
new file mode 100644
index 0000000..6a1a7f7
--- /dev/null
+++ b/media/java/android/media/AudioDeviceAddress.aidl
@@ -0,0 +1,18 @@
+/* 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.media;
+
+parcelable AudioDeviceAddress;
diff --git a/media/java/android/media/AudioDeviceAddress.java b/media/java/android/media/AudioDeviceAddress.java
new file mode 100644
index 0000000..415e77d
--- /dev/null
+++ b/media/java/android/media/AudioDeviceAddress.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+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.Objects;
+
+/**
+ * @hide
+ * Class to represent device type (speaker, headset...), address and role (input, output)
+ * of an audio device.
+ * <p>Unlike {@link AudioDeviceInfo}, the device
+ * doesn't need to be connected to be uniquely identified, it can
+ * for instance represent a specific A2DP headset even after a
+ * disconnection, whereas the corresponding <code>AudioDeviceInfo</code>
+ * would then be invalid.
+ * <p>While creating / obtaining an instance is not protected by a
+ * permission, APIs using one rely on MODIFY_AUDIO_ROUTING.
+ */
+@SystemApi
+public final class AudioDeviceAddress implements Parcelable {
+
+ /**
+ * A role identifying input devices, such as microphones.
+ */
+ public static final int ROLE_INPUT = AudioPort.ROLE_SOURCE;
+ /**
+ * A role identifying output devices, such as speakers or headphones.
+ */
+ public static final int ROLE_OUTPUT = AudioPort.ROLE_SINK;
+
+ /** @hide */
+ @IntDef(flag = false, prefix = "ROLE_", value = {
+ ROLE_INPUT, ROLE_OUTPUT }
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Role {}
+
+ /**
+ * The audio device type, as defined in {@link AudioDeviceInfo}
+ */
+ private final @AudioDeviceInfo.AudioDeviceType int mType;
+ /**
+ * The unique address of the device. Some devices don't have addresses, only an empty string.
+ */
+ private final @NonNull String mAddress;
+
+ /**
+ * Is input or output device
+ */
+ private final @Role int mRole;
+
+ /**
+ * Constructor from a valid {@link AudioDeviceInfo}
+ * @param deviceInfo the connected audio device from which to obtain the device-identifying
+ * type and address.
+ */
+ public AudioDeviceAddress(@NonNull AudioDeviceInfo deviceInfo) {
+ Objects.requireNonNull(deviceInfo);
+ mRole = deviceInfo.isSink() ? ROLE_OUTPUT : ROLE_INPUT;
+ mType = deviceInfo.getType();
+ mAddress = deviceInfo.getAddress();
+ }
+
+ public AudioDeviceAddress(@Role int role, @AudioDeviceInfo.AudioDeviceType int type,
+ @NonNull String address) {
+ Objects.requireNonNull(address);
+ if (role != ROLE_OUTPUT && role != ROLE_INPUT) {
+ throw new IllegalArgumentException("Invalid role " + role);
+ }
+ if (role == ROLE_OUTPUT && !AudioDeviceInfo.isValidAudioDeviceTypeOut(type)) {
+ throw new IllegalArgumentException("Invalid output device type " + type);
+ }
+ if (role == ROLE_INPUT && !AudioDeviceInfo.isValidAudioDeviceTypeIn(type)) {
+ throw new IllegalArgumentException("Invalid input device type " + type);
+ }
+
+ mRole = role;
+ mType = type;
+ mAddress = address;
+ }
+
+ public @Role int getRole() {
+ return mRole;
+ }
+
+ public @AudioDeviceInfo.AudioDeviceType int getType() {
+ return mType;
+ }
+
+ public @NonNull String getAddress() {
+ return mAddress;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mRole, mType, mAddress);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AudioDeviceAddress that = (AudioDeviceAddress) o;
+ return ((mRole == that.mRole)
+ && (mType == that.mType)
+ && mAddress.equals(that.mAddress));
+ }
+
+ /** @hide */
+ public static String roleToString(@Role int role) {
+ return (role == ROLE_OUTPUT ? "output" : "input");
+ }
+
+ @Override
+ public String toString() {
+ return new String("AudioDeviceAddress:"
+ + " role:" + roleToString(mRole)
+ + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(
+ AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType))
+ : AudioSystem.getInputDeviceName(
+ AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType)))
+ + " addr:" + mAddress);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mRole);
+ dest.writeInt(mType);
+ dest.writeString(mAddress);
+ }
+
+ private AudioDeviceAddress(@NonNull Parcel in) {
+ mRole = in.readInt();
+ mType = in.readInt();
+ mAddress = in.readString();
+ }
+
+ public static final @NonNull Parcelable.Creator<AudioDeviceAddress> CREATOR =
+ new Parcelable.Creator<AudioDeviceAddress>() {
+ /**
+ * Rebuilds an AudioDeviceAddress previously stored with writeToParcel().
+ * @param p Parcel object to read the AudioDeviceAddress from
+ * @return a new AudioDeviceAddress created from the data in the parcel
+ */
+ public AudioDeviceAddress createFromParcel(Parcel p) {
+ return new AudioDeviceAddress(p);
+ }
+
+ public AudioDeviceAddress[] newArray(int size) {
+ return new AudioDeviceAddress[size];
+ }
+ };
+}
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index ca895fc..a39bc51 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -149,6 +149,55 @@
TYPE_AUX_LINE,
TYPE_IP,
TYPE_BUS,
+ TYPE_HEARING_AID,
+ TYPE_BUILTIN_MIC,
+ TYPE_FM_TUNER,
+ TYPE_TV_TUNER }
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AudioDeviceType {} /** @hide */
+ @IntDef(flag = false, prefix = "TYPE", value = {
+ TYPE_BUILTIN_MIC,
+ TYPE_BLUETOOTH_SCO,
+ TYPE_BLUETOOTH_A2DP,
+ TYPE_WIRED_HEADSET,
+ TYPE_HDMI,
+ TYPE_TELEPHONY,
+ TYPE_DOCK,
+ TYPE_USB_ACCESSORY,
+ TYPE_USB_DEVICE,
+ TYPE_USB_HEADSET,
+ TYPE_FM_TUNER,
+ TYPE_TV_TUNER,
+ TYPE_LINE_ANALOG,
+ TYPE_LINE_DIGITAL,
+ TYPE_IP,
+ TYPE_BUS }
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AudioDeviceTypeIn {}
+
+ /** @hide */
+ @IntDef(flag = false, prefix = "TYPE", value = {
+ TYPE_BUILTIN_EARPIECE,
+ TYPE_BUILTIN_SPEAKER,
+ TYPE_WIRED_HEADSET,
+ TYPE_WIRED_HEADPHONES,
+ TYPE_BLUETOOTH_SCO,
+ TYPE_BLUETOOTH_A2DP,
+ TYPE_HDMI,
+ TYPE_DOCK,
+ TYPE_USB_ACCESSORY,
+ TYPE_USB_DEVICE,
+ TYPE_USB_HEADSET,
+ TYPE_TELEPHONY,
+ TYPE_LINE_ANALOG,
+ TYPE_HDMI_ARC,
+ TYPE_LINE_DIGITAL,
+ TYPE_FM,
+ TYPE_AUX_LINE,
+ TYPE_IP,
+ TYPE_BUS,
TYPE_HEARING_AID }
)
@Retention(RetentionPolicy.SOURCE)
@@ -183,6 +232,31 @@
}
}
+ /** @hide */
+ /*package*/ static boolean isValidAudioDeviceTypeIn(int type) {
+ switch (type) {
+ case TYPE_BUILTIN_MIC:
+ case TYPE_BLUETOOTH_SCO:
+ case TYPE_BLUETOOTH_A2DP:
+ case TYPE_WIRED_HEADSET:
+ case TYPE_HDMI:
+ case TYPE_TELEPHONY:
+ case TYPE_DOCK:
+ case TYPE_USB_ACCESSORY:
+ case TYPE_USB_DEVICE:
+ case TYPE_USB_HEADSET:
+ case TYPE_FM_TUNER:
+ case TYPE_TV_TUNER:
+ case TYPE_LINE_ANALOG:
+ case TYPE_LINE_DIGITAL:
+ case TYPE_IP:
+ case TYPE_BUS:
+ return true;
+ default:
+ return false;
+ }
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index 62b18cb..51909db 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -16,8 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
-import android.media.AudioSystem;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The AudioDevicePort is a specialized type of AudioPort
diff --git a/media/java/android/media/AudioDevicePortConfig.java b/media/java/android/media/AudioDevicePortConfig.java
index 0c647ea..51b8037 100644
--- a/media/java/android/media/AudioDevicePortConfig.java
+++ b/media/java/android/media/AudioDevicePortConfig.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An AudioDevicePortConfig describes a possible configuration of an output or input device
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index e55585a..7ff15df 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -20,7 +20,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/media/java/android/media/AudioGain.java b/media/java/android/media/AudioGain.java
index dd129a2..cae1b59 100644
--- a/media/java/android/media/AudioGain.java
+++ b/media/java/android/media/AudioGain.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The AudioGain describes a gain controller. Gain controllers are exposed by
diff --git a/media/java/android/media/AudioGainConfig.java b/media/java/android/media/AudioGainConfig.java
index f5ebef8..dfefa86 100644
--- a/media/java/android/media/AudioGainConfig.java
+++ b/media/java/android/media/AudioGainConfig.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The AudioGainConfig is used by APIs setting or getting values on a given gain
diff --git a/media/java/android/media/AudioHandle.java b/media/java/android/media/AudioHandle.java
index 24f81f9..8fc834f 100644
--- a/media/java/android/media/AudioHandle.java
+++ b/media/java/android/media/AudioHandle.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The AudioHandle is used by the audio framework implementation to
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index f797da7..32eec00 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -27,12 +27,12 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java
index c4a5c4d..33d603f 100644
--- a/media/java/android/media/AudioMixPort.java
+++ b/media/java/android/media/AudioMixPort.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* The AudioMixPort is a specialized type of AudioPort
diff --git a/media/java/android/media/AudioMixPortConfig.java b/media/java/android/media/AudioMixPortConfig.java
index 315e46b..9d81206 100644
--- a/media/java/android/media/AudioMixPortConfig.java
+++ b/media/java/android/media/AudioMixPortConfig.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An AudioMixPortConfig describes a possible configuration of an output or input mixer.
diff --git a/media/java/android/media/AudioPatch.java b/media/java/android/media/AudioPatch.java
index d1f8006..e5107d4 100644
--- a/media/java/android/media/AudioPatch.java
+++ b/media/java/android/media/AudioPatch.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index 83eb240..7c3ca24 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An audio port is a node of the audio framework or hardware that can be connected to or
diff --git a/media/java/android/media/AudioPortConfig.java b/media/java/android/media/AudioPortConfig.java
index ac19bb1..16fb5b8 100644
--- a/media/java/android/media/AudioPortConfig.java
+++ b/media/java/android/media/AudioPortConfig.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An AudioPortConfig contains a possible configuration of an audio port chosen
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
index 6d9d626..14249cb 100644
--- a/media/java/android/media/AudioPortEventHandler.java
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index ce9b07d..306999c 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -23,8 +23,8 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.MediaRecorder.Source;
import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioPolicy;
diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java
index 874a215..5f32c0f 100644
--- a/media/java/android/media/AudioRecordingConfiguration.java
+++ b/media/java/android/media/AudioRecordingConfiguration.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.audiofx.AudioEffect;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 1033e56..1ad6198 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -19,8 +19,8 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothCodecConfig;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.audiofx.AudioEffect;
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 7cd09de..0ced68ef 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -23,7 +23,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index 963b1d1..e4bab74 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.os.Build;
diff --git a/media/java/android/media/DecoderCapabilities.java b/media/java/android/media/DecoderCapabilities.java
index df5e918..ebfc63b 100644
--- a/media/java/android/media/DecoderCapabilities.java
+++ b/media/java/android/media/DecoderCapabilities.java
@@ -16,9 +16,10 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
-import java.util.List;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.ArrayList;
+import java.util.List;
/**
* {@hide}
diff --git a/media/java/android/media/EncoderCapabilities.java b/media/java/android/media/EncoderCapabilities.java
index c09c5fa..67ce0f7 100644
--- a/media/java/android/media/EncoderCapabilities.java
+++ b/media/java/android/media/EncoderCapabilities.java
@@ -16,9 +16,10 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
-import java.util.List;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.ArrayList;
+import java.util.List;
/**
* The EncoderCapabilities class is used to retrieve the
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 5645ba5..b417927 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -20,7 +20,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 70a343f..b5acbd4 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -16,14 +16,13 @@
package android.media;
-import java.nio.ByteBuffer;
-import java.lang.AutoCloseable;
-
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
+import java.nio.ByteBuffer;
+
/**
* <p>A single complete image buffer to use with a media source such as a
* {@link MediaCodec} or a
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index e85b3ff9..84ee09b 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -17,7 +17,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.os.Handler;
import android.os.Looper;
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index c9d7978..e702f19 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index f304f7c..f3752d5 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -22,7 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.SystemProperties;
import android.util.Log;
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index a08aec3..ea9a373 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -21,17 +21,17 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
-import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
-import android.os.Message;
import android.os.Parcel;
import android.os.PersistableBundle;
import android.util.Log;
+
import dalvik.system.CloseGuard;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index c4eb031..9908e04 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.mtp.MtpConstants;
import libcore.content.type.MimeMap;
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 8b667f7..841799a 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index 8ee929e..a17ff82 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -18,13 +18,14 @@
import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.NetworkUtils;
import android.os.IBinder;
import android.os.StrictMode;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
diff --git a/media/java/android/media/MediaHTTPService.java b/media/java/android/media/MediaHTTPService.java
index 97a0df7..3008067 100644
--- a/media/java/android/media/MediaHTTPService.java
+++ b/media/java/android/media/MediaHTTPService.java
@@ -17,7 +17,7 @@
package android.media;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.util.Log;
diff --git a/media/java/android/media/MediaInserter.java b/media/java/android/media/MediaInserter.java
index 0749f58..ca7a01c 100644
--- a/media/java/android/media/MediaInserter.java
+++ b/media/java/android/media/MediaInserter.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.net.Uri;
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index 8512dbe..a23191f 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -17,7 +17,7 @@
import android.annotation.NonNull;
import android.annotation.StringDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index c43b78c..a21a630 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index 0fb392b..14a48d7 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -18,8 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.media.MediaCodec;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.MediaCodec.BufferInfo;
import dalvik.system.CloseGuard;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 353e58e..6b953ae 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -19,8 +19,8 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 63b22df..c957a88 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -23,8 +23,8 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.Camera;
import android.os.Build;
import android.os.Handler;
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index d72231f..9837e1c 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -22,8 +22,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 771628c..317502d 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentUris;
diff --git a/media/java/android/media/Metadata.java b/media/java/android/media/Metadata.java
index 792a2ba..ef17073 100644
--- a/media/java/android/media/Metadata.java
+++ b/media/java/android/media/Metadata.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.util.Log;
import android.util.MathUtils;
diff --git a/media/java/android/media/MicrophoneInfo.java b/media/java/android/media/MicrophoneInfo.java
index f805975..876628f 100644
--- a/media/java/android/media/MicrophoneInfo.java
+++ b/media/java/android/media/MicrophoneInfo.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Pair;
import java.lang.annotation.Retention;
diff --git a/media/java/android/media/PlaybackParams.java b/media/java/android/media/PlaybackParams.java
index b4325b6..f24f831 100644
--- a/media/java/android/media/PlaybackParams.java
+++ b/media/java/android/media/PlaybackParams.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 325420b..c5fd3c3 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -16,8 +16,8 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.Bitmap;
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index f70963a..9e48f1e 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -16,8 +16,8 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Bitmap;
diff --git a/media/java/android/media/RemoteDisplay.java b/media/java/android/media/RemoteDisplay.java
index 2be206f..e529af9 100644
--- a/media/java/android/media/RemoteDisplay.java
+++ b/media/java/android/media/RemoteDisplay.java
@@ -16,12 +16,12 @@
package android.media;
-import dalvik.system.CloseGuard;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.view.Surface;
+import dalvik.system.CloseGuard;
+
/**
* Listens for Wifi remote display connections managed by the media server.
*
diff --git a/media/java/android/media/RemoteDisplayState.java b/media/java/android/media/RemoteDisplayState.java
index 2f4ace0..fed361a 100644
--- a/media/java/android/media/RemoteDisplayState.java
+++ b/media/java/android/media/RemoteDisplayState.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index eb680c8..d35bc41 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -17,7 +17,7 @@
package android.media;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 435d8d7..6fd47c4 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -22,9 +22,9 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
import android.app.Activity;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
diff --git a/media/java/android/media/SubtitleController.java b/media/java/android/media/SubtitleController.java
index 1a241af..48657a6c 100644
--- a/media/java/android/media/SubtitleController.java
+++ b/media/java/android/media/SubtitleController.java
@@ -16,10 +16,7 @@
package android.media;
-import java.util.Locale;
-import java.util.Vector;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.MediaPlayer.TrackInfo;
import android.media.SubtitleTrack.RenderingWidget;
@@ -28,6 +25,9 @@
import android.os.Message;
import android.view.accessibility.CaptioningManager;
+import java.util.Locale;
+import java.util.Vector;
+
/**
* The subtitle controller provides the architecture to display subtitles for a
* media source. It allows specifying which tracks to display, on which anchor
diff --git a/media/java/android/media/SubtitleTrack.java b/media/java/android/media/SubtitleTrack.java
index 0705d97..10669f4 100644
--- a/media/java/android/media/SubtitleTrack.java
+++ b/media/java/android/media/SubtitleTrack.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.media.MediaPlayer.TrackInfo;
import android.os.Handler;
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 534d63b..cbdf9ad 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -24,7 +24,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
diff --git a/media/java/android/media/TimedText.java b/media/java/android/media/TimedText.java
index d8cdf9c..120642a 100644
--- a/media/java/android/media/TimedText.java
+++ b/media/java/android/media/TimedText.java
@@ -16,14 +16,15 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.os.Parcel;
import android.util.Log;
-import java.util.HashMap;
-import java.util.Set;
-import java.util.List;
+
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
/**
* Class to hold the timed text's metadata, including:
diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
index c6d5ba3..cc114a9 100644
--- a/media/java/android/media/ToneGenerator.java
+++ b/media/java/android/media/ToneGenerator.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
diff --git a/media/java/android/media/TtmlRenderer.java b/media/java/android/media/TtmlRenderer.java
index 34154ce..e578264 100644
--- a/media/java/android/media/TtmlRenderer.java
+++ b/media/java/android/media/TtmlRenderer.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -27,6 +27,10 @@
import android.widget.LinearLayout;
import android.widget.TextView;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
@@ -37,10 +41,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
/** @hide */
public class TtmlRenderer extends SubtitleController.Renderer {
private final Context mContext;
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index 663d564..99dfe1e 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -19,13 +19,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+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.lang.AutoCloseable;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Objects;
diff --git a/media/java/android/media/WebVttRenderer.java b/media/java/android/media/WebVttRenderer.java
index 36458d7..bc14294 100644
--- a/media/java/android/media/WebVttRenderer.java
+++ b/media/java/android/media/WebVttRenderer.java
@@ -16,7 +16,7 @@
package android.media;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.text.Layout.Alignment;
import android.text.SpannableStringBuilder;
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 5b4bbce..cad5aa6 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -16,11 +16,18 @@
package android.media.audiofx;
+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.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.media.AudioDeviceAddress;
+import android.media.AudioDeviceInfo;
+import android.media.AudioSystem;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -448,12 +455,46 @@
public AudioEffect(UUID type, UUID uuid, int priority, int audioSession)
throws IllegalArgumentException, UnsupportedOperationException,
RuntimeException {
+ this(type, uuid, priority, audioSession, null);
+ }
+
+ /**
+ * Constructs an AudioEffect attached to a particular audio device.
+ * The device does not have to be attached when the effect is created. The effect will only
+ * be applied when the device is actually selected for playback or capture.
+ * @param uuid unique identifier of a particular effect implementation.
+ * @param device the device the effect must be attached to.
+ *
+ * @throws java.lang.IllegalArgumentException
+ * @throws java.lang.UnsupportedOperationException
+ * @throws java.lang.RuntimeException
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
+ public AudioEffect(@NonNull UUID uuid, @NonNull AudioDeviceAddress device) {
+ this(EFFECT_TYPE_NULL, Objects.requireNonNull(uuid), 0, -2, Objects.requireNonNull(device));
+ }
+
+ private AudioEffect(UUID type, UUID uuid, int priority,
+ int audioSession, @Nullable AudioDeviceAddress device)
+ throws IllegalArgumentException, UnsupportedOperationException,
+ RuntimeException {
int[] id = new int[1];
Descriptor[] desc = new Descriptor[1];
+
+ int deviceType = AudioSystem.DEVICE_NONE;
+ String deviceAddress = "";
+ if (device != null) {
+ deviceType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
+ deviceAddress = device.getAddress();
+ }
+
// native initialization
int initResult = native_setup(new WeakReference<AudioEffect>(this),
- type.toString(), uuid.toString(), priority, audioSession, id,
- desc, ActivityThread.currentOpPackageName());
+ type.toString(), uuid.toString(), priority, audioSession,
+ deviceType, deviceAddress,
+ id, desc, ActivityThread.currentOpPackageName());
if (initResult != SUCCESS && initResult != ALREADY_EXISTS) {
Log.e(TAG, "Error code " + initResult
+ " when initializing AudioEffect.");
@@ -1293,7 +1334,8 @@
private static native final void native_init();
private native final int native_setup(Object audioeffect_this, String type,
- String uuid, int priority, int audioSession, int[] id, Object[] desc,
+ String uuid, int priority, int audioSession,
+ int deviceType, String deviceAddress, int[] id, Object[] desc,
String opPackageName);
private native final void native_finalize();
diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java
index 89a509f..392e8fe 100644
--- a/media/java/android/media/audiofx/Visualizer.java
+++ b/media/java/android/media/audiofx/Visualizer.java
@@ -16,8 +16,8 @@
package android.media.audiofx;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index a82c78f..dd9877a 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioSystem;
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index c4afd95..8c204d2 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioAttributes;
import android.os.Parcel;
import android.util.Log;
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 1fc4f7d..a856653 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.media.AudioAttributes;
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index e11715f..5db4e8c 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -19,9 +19,9 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index 123c4f7..0d506f0 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -16,9 +16,9 @@
package android.media.session;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -26,7 +26,6 @@
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
-import android.media.AudioManager;
import android.media.MediaMetadata;
import android.media.MediaMetadataEditor;
import android.media.MediaMetadataRetriever;
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index a89dc5f..aff7257 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -22,7 +22,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ParceledListSlice;
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index 56e5566..77596a5 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -22,7 +22,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.SoundTrigger;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index ada77c5..3f0aec6 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -23,7 +23,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.hardware.soundtrigger.SoundTrigger;
diff --git a/media/java/android/media/tv/DvbDeviceInfo.java b/media/java/android/media/tv/DvbDeviceInfo.java
index a574fe1..96c8528 100644
--- a/media/java/android/media/tv/DvbDeviceInfo.java
+++ b/media/java/android/media/tv/DvbDeviceInfo.java
@@ -16,6 +16,8 @@
package android.media.tv;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
@@ -26,10 +28,11 @@
*
* @hide
*/
+@SystemApi
public final class DvbDeviceInfo implements Parcelable {
static final String TAG = "DvbDeviceInfo";
- public static final @android.annotation.NonNull Parcelable.Creator<DvbDeviceInfo> CREATOR =
+ public static final @NonNull Parcelable.Creator<DvbDeviceInfo> CREATOR =
new Parcelable.Creator<DvbDeviceInfo>() {
@Override
public DvbDeviceInfo createFromParcel(Parcel source) {
@@ -86,7 +89,7 @@
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mAdapterId);
dest.writeInt(mDeviceId);
}
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 1b9cac0..377b2bc 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.StringRes;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index d22a298..854ea43 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -103,6 +103,12 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
+ @IntDef({DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_FRONTEND})
+ public @interface DvbDeviceType {}
+
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
@IntDef({VIDEO_UNAVAILABLE_REASON_UNKNOWN, VIDEO_UNAVAILABLE_REASON_TUNING,
VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL, VIDEO_UNAVAILABLE_REASON_BUFFERING,
VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY})
@@ -1663,6 +1669,9 @@
* @return the list of {@link DvbDeviceInfo} objects representing available DVB devices.
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.DVB_DEVICE)
+ @NonNull
public List<DvbDeviceInfo> getDvbDeviceList() {
try {
return mService.getDvbDeviceList();
@@ -1676,19 +1685,24 @@
* {@link DvbDeviceInfo}
*
* @param info A {@link DvbDeviceInfo} to open a DVB device.
- * @param device A DVB device. The DVB device can be {@link #DVB_DEVICE_DEMUX},
+ * @param deviceType A DVB device type. The type can be {@link #DVB_DEVICE_DEMUX},
* {@link #DVB_DEVICE_DVR} or {@link #DVB_DEVICE_FRONTEND}.
* @return a {@link ParcelFileDescriptor} of a specified DVB device for a given
- * {@link DvbDeviceInfo}, or {@code null} if the given {@link DvbDeviceInfo} was invalid
- * or the specified DVB device was busy with a previous request.
+ * {@link DvbDeviceInfo}, or {@code null} if the given {@link DvbDeviceInfo}
+ * failed to open.
+ * @throws IllegalArgumentException if {@code deviceType} is invalid or the device is not found.
* @hide
*/
- public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info, int device) {
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.DVB_DEVICE)
+ @Nullable
+ public ParcelFileDescriptor openDvbDevice(@NonNull DvbDeviceInfo info,
+ @DvbDeviceType int deviceType) {
try {
- if (DVB_DEVICE_START > device || DVB_DEVICE_END < device) {
- throw new IllegalArgumentException("Invalid DVB device: " + device);
+ if (DVB_DEVICE_START > deviceType || DVB_DEVICE_END < deviceType) {
+ throw new IllegalArgumentException("Invalid DVB device: " + deviceType);
}
- return mService.openDvbDevice(info, device);
+ return mService.openDvbDevice(info, deviceType);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 5c11ed9b..7fbb337 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -22,9 +22,9 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java
index ea00d6e..4318a0a 100644
--- a/media/java/android/media/tv/TvTrackInfo.java
+++ b/media/java/android/media/tv/TvTrackInfo.java
@@ -61,6 +61,9 @@
private final boolean mEncrypted;
private final int mAudioChannelCount;
private final int mAudioSampleRate;
+ private final boolean mAudioDescription;
+ private final boolean mHardOfHearing;
+ private final boolean mSpokenSubtitle;
private final int mVideoWidth;
private final int mVideoHeight;
private final float mVideoFrameRate;
@@ -70,9 +73,10 @@
private final Bundle mExtra;
private TvTrackInfo(int type, String id, String language, CharSequence description,
- boolean encrypted, int audioChannelCount, int audioSampleRate, int videoWidth,
- int videoHeight, float videoFrameRate, float videoPixelAspectRatio,
- byte videoActiveFormatDescription, Bundle extra) {
+ boolean encrypted, int audioChannelCount, int audioSampleRate, boolean audioDescription,
+ boolean hardOfHearing, boolean spokenSubtitle, int videoWidth, int videoHeight,
+ float videoFrameRate, float videoPixelAspectRatio, byte videoActiveFormatDescription,
+ Bundle extra) {
mType = type;
mId = id;
mLanguage = language;
@@ -80,6 +84,9 @@
mEncrypted = encrypted;
mAudioChannelCount = audioChannelCount;
mAudioSampleRate = audioSampleRate;
+ mAudioDescription = audioDescription;
+ mHardOfHearing = hardOfHearing;
+ mSpokenSubtitle = spokenSubtitle;
mVideoWidth = videoWidth;
mVideoHeight = videoHeight;
mVideoFrameRate = videoFrameRate;
@@ -96,6 +103,9 @@
mEncrypted = in.readInt() != 0;
mAudioChannelCount = in.readInt();
mAudioSampleRate = in.readInt();
+ mAudioDescription = in.readInt() != 0;
+ mHardOfHearing = in.readInt() != 0;
+ mSpokenSubtitle = in.readInt() != 0;
mVideoWidth = in.readInt();
mVideoHeight = in.readInt();
mVideoFrameRate = in.readFloat();
@@ -172,6 +182,56 @@
}
/**
+ * Returns {@code true} if the track is an audio description intended for people with visual
+ * impairment, {@code false} otherwise. Valid only for {@link #TYPE_AUDIO} tracks.
+ *
+ * <p>For example of broadcast, audio description information may be referred to broadcast
+ * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio Language
+ * Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN 300 468).
+ *
+ * @throws IllegalStateException if not called on an audio track
+ */
+ public boolean isAudioDescription() {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ return mAudioDescription;
+ }
+
+ /**
+ * Returns {@code true} if the track is intended for people with hearing impairment, {@code
+ * false} otherwise. Valid only for {@link #TYPE_AUDIO} and {@link #TYPE_SUBTITLE} tracks.
+ *
+ * <p>For example of broadcast, hard of hearing information may be referred to broadcast
+ * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio Language
+ * Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN 300 468).
+ *
+ * @throws IllegalStateException if not called on an audio track or a subtitle track
+ */
+ public boolean isHardOfHearing() {
+ if (mType != TYPE_AUDIO && mType != TYPE_SUBTITLE) {
+ throw new IllegalStateException("Not an audio or a subtitle track");
+ }
+ return mHardOfHearing;
+ }
+
+ /**
+ * Returns {@code true} if the track is a spoken subtitle for people with visual impairment,
+ * {@code false} otherwise. Valid only for {@link #TYPE_AUDIO} tracks.
+ *
+ * <p>For example of broadcast, spoken subtitle information may be referred to broadcast
+ * standard (e.g. Supplementary Audio Language Descriptor of ETSI EN 300 468).
+ *
+ * @throws IllegalStateException if not called on an audio track
+ */
+ public boolean isSpokenSubtitle() {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ return mSpokenSubtitle;
+ }
+
+ /**
* Returns the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
* tracks.
*
@@ -266,6 +326,9 @@
dest.writeInt(mEncrypted ? 1 : 0);
dest.writeInt(mAudioChannelCount);
dest.writeInt(mAudioSampleRate);
+ dest.writeInt(mAudioDescription ? 1 : 0);
+ dest.writeInt(mHardOfHearing ? 1 : 0);
+ dest.writeInt(mSpokenSubtitle ? 1 : 0);
dest.writeInt(mVideoWidth);
dest.writeInt(mVideoHeight);
dest.writeFloat(mVideoFrameRate);
@@ -289,6 +352,7 @@
if (!TextUtils.equals(mId, obj.mId) || mType != obj.mType
|| !TextUtils.equals(mLanguage, obj.mLanguage)
|| !TextUtils.equals(mDescription, obj.mDescription)
+ || mEncrypted != obj.mEncrypted
|| !Objects.equals(mExtra, obj.mExtra)) {
return false;
}
@@ -296,7 +360,10 @@
switch (mType) {
case TYPE_AUDIO:
return mAudioChannelCount == obj.mAudioChannelCount
- && mAudioSampleRate == obj.mAudioSampleRate;
+ && mAudioSampleRate == obj.mAudioSampleRate
+ && mAudioDescription == obj.mAudioDescription
+ && mHardOfHearing == obj.mHardOfHearing
+ && mSpokenSubtitle == obj.mSpokenSubtitle;
case TYPE_VIDEO:
return mVideoWidth == obj.mVideoWidth
@@ -304,6 +371,9 @@
&& mVideoFrameRate == obj.mVideoFrameRate
&& mVideoPixelAspectRatio == obj.mVideoPixelAspectRatio
&& mVideoActiveFormatDescription == obj.mVideoActiveFormatDescription;
+
+ case TYPE_SUBTITLE:
+ return mHardOfHearing == obj.mHardOfHearing;
}
return true;
@@ -338,6 +408,9 @@
private boolean mEncrypted;
private int mAudioChannelCount;
private int mAudioSampleRate;
+ private boolean mAudioDescription;
+ private boolean mHardOfHearing;
+ private boolean mSpokenSubtitle;
private int mVideoWidth;
private int mVideoHeight;
private float mVideoFrameRate;
@@ -430,6 +503,67 @@
}
/**
+ * Sets the audio description attribute of the audio. Valid only for {@link #TYPE_AUDIO}
+ * tracks.
+ *
+ * <p>For example of broadcast, audio description information may be referred to broadcast
+ * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio
+ * Language Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN
+ * 300 468).
+ *
+ * @param audioDescription The audio description attribute of the audio.
+ * @throws IllegalStateException if not called on an audio track
+ */
+ @NonNull
+ public Builder setAudioDescription(boolean audioDescription) {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ mAudioDescription = audioDescription;
+ return this;
+ }
+
+ /**
+ * Sets the hard of hearing attribute of the track. Valid only for {@link #TYPE_AUDIO} and
+ * {@link #TYPE_SUBTITLE} tracks.
+ *
+ * <p>For example of broadcast, hard of hearing information may be referred to broadcast
+ * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio
+ * Language Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN
+ * 300 468).
+ *
+ * @param hardOfHearing The hard of hearing attribute of the track.
+ * @throws IllegalStateException if not called on an audio track or a subtitle track
+ */
+ @NonNull
+ public Builder setHardOfHearing(boolean hardOfHearing) {
+ if (mType != TYPE_AUDIO && mType != TYPE_SUBTITLE) {
+ throw new IllegalStateException("Not an audio track or a subtitle track");
+ }
+ mHardOfHearing = hardOfHearing;
+ return this;
+ }
+
+ /**
+ * Sets the spoken subtitle attribute of the audio. Valid only for {@link #TYPE_AUDIO}
+ * tracks.
+ *
+ * <p>For example of broadcast, spoken subtitle information may be referred to broadcast
+ * standard (e.g. Supplementary Audio Language Descriptor of ETSI EN 300 468).
+ *
+ * @param spokenSubtitle The spoken subtitle attribute of the audio.
+ * @throws IllegalStateException if not called on an audio track
+ */
+ @NonNull
+ public Builder setSpokenSubtitle(boolean spokenSubtitle) {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ mSpokenSubtitle = spokenSubtitle;
+ return this;
+ }
+
+ /**
* Sets the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
* tracks.
*
@@ -531,8 +665,9 @@
*/
public TvTrackInfo build() {
return new TvTrackInfo(mType, mId, mLanguage, mDescription, mEncrypted,
- mAudioChannelCount, mAudioSampleRate, mVideoWidth, mVideoHeight,
- mVideoFrameRate, mVideoPixelAspectRatio, mVideoActiveFormatDescription, mExtra);
+ mAudioChannelCount, mAudioSampleRate, mAudioDescription, mHardOfHearing,
+ mSpokenSubtitle, mVideoWidth, mVideoHeight, mVideoFrameRate,
+ mVideoPixelAspectRatio, mVideoActiveFormatDescription, mExtra);
}
}
}
diff --git a/media/java/android/mtp/MtpPropertyList.java b/media/java/android/mtp/MtpPropertyList.java
index 557f099..53d838d 100644
--- a/media/java/android/mtp/MtpPropertyList.java
+++ b/media/java/android/mtp/MtpPropertyList.java
@@ -16,7 +16,8 @@
package android.mtp;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.ArrayList;
import java.util.List;
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index 65d0fef..d385816 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -16,7 +16,7 @@
package android.mtp;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.storage.StorageVolume;
import android.provider.MediaStore;
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 86a1076..06adf30 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -21,8 +21,8 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 8d420e2..05aaa82 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -743,8 +743,10 @@
}
status_t JMediaCodec::getMetrics(JNIEnv *, MediaAnalyticsItem * &reply) const {
-
- status_t status = mCodec->getMetrics(reply);
+ mediametrics_handle_t reply2 = MediaAnalyticsItem::convert(reply);
+ status_t status = mCodec->getMetrics(reply2);
+ // getMetrics() updates reply2, pass the converted update along to our caller.
+ reply = MediaAnalyticsItem::convert(reply2);
return status;
}
@@ -1848,7 +1850,7 @@
}
// get what we have for the metrics from the codec
- MediaAnalyticsItem *item = NULL;
+ MediaAnalyticsItem *item = 0;
status_t err = codec->getMetrics(env, item);
if (err != OK) {
@@ -1860,7 +1862,7 @@
// housekeeping
delete item;
- item = NULL;
+ item = 0;
return mybundle;
}
diff --git a/media/jni/audioeffect/Android.bp b/media/jni/audioeffect/Android.bp
index 41ab670..5ba5c01 100644
--- a/media/jni/audioeffect/Android.bp
+++ b/media/jni/audioeffect/Android.bp
@@ -17,6 +17,7 @@
"libnativehelper",
"libaudioclient",
"libaudioutils",
+ "libaudiofoundation",
],
version_script: "exports.lds",
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 747d4c01..007dd10 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -268,8 +268,9 @@
static jint
android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
- jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId,
- jobjectArray javadesc, jstring opPackageName)
+ jstring type, jstring uuid, jint priority, jint sessionId,
+ jint deviceType, jstring deviceAddress,
+ jintArray jId, jobjectArray javadesc, jstring opPackageName)
{
ALOGV("android_media_AudioEffect_native_setup");
AudioEffectJniStorage* lpJniStorage = NULL;
@@ -280,6 +281,7 @@
const char *uuidStr = NULL;
effect_descriptor_t desc;
jobject jdesc;
+ AudioDeviceTypeAddr device;
ScopedUtfChars opPackageNameStr(env, opPackageName);
@@ -328,6 +330,12 @@
goto setup_failure;
}
+ if (deviceType != AUDIO_DEVICE_NONE) {
+ device.mType = deviceType;
+ ScopedUtfChars address(env, deviceAddress);
+ device.mAddress = address.c_str();
+ }
+
// create the native AudioEffect object
lpAudioEffect = new AudioEffect(typeStr,
String16(opPackageNameStr.c_str()),
@@ -336,7 +344,8 @@
effectCallback,
&lpJniStorage->mCallbackData,
(audio_session_t) sessionId,
- AUDIO_IO_HANDLE_NONE);
+ AUDIO_IO_HANDLE_NONE,
+ device);
if (lpAudioEffect == 0) {
ALOGE("Error creating AudioEffect");
goto setup_failure;
@@ -757,7 +766,7 @@
// Dalvik VM type signatures
static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_AudioEffect_native_init},
- {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;II[I[Ljava/lang/Object;Ljava/lang/String;)I",
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;IIILjava/lang/String;[I[Ljava/lang/Object;Ljava/lang/String;)I",
(void *)android_media_AudioEffect_native_setup},
{"native_finalize", "()V", (void *)android_media_AudioEffect_native_finalize},
{"native_release", "()V", (void *)android_media_AudioEffect_native_release},
diff --git a/media/mca/effect/java/android/media/effect/SingleFilterEffect.java b/media/mca/effect/java/android/media/effect/SingleFilterEffect.java
index dfbf5d2..121443f 100644
--- a/media/mca/effect/java/android/media/effect/SingleFilterEffect.java
+++ b/media/mca/effect/java/android/media/effect/SingleFilterEffect.java
@@ -17,12 +17,11 @@
package android.media.effect;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.filterfw.core.Filter;
import android.filterfw.core.FilterFactory;
import android.filterfw.core.FilterFunction;
import android.filterfw.core.Frame;
-import android.media.effect.EffectContext;
/**
* Effect subclass for effects based on a single Filter. Subclasses need only invoke the
diff --git a/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java b/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java
index 52615bf..3a7f1ed 100644
--- a/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java
+++ b/media/mca/filterfw/java/android/filterfw/GraphEnvironment.java
@@ -17,11 +17,11 @@
package android.filterfw;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.filterfw.core.AsyncRunner;
-import android.filterfw.core.FilterGraph;
import android.filterfw.core.FilterContext;
+import android.filterfw.core.FilterGraph;
import android.filterfw.core.FrameManager;
import android.filterfw.core.GraphRunner;
import android.filterfw.core.RoundRobinScheduler;
diff --git a/media/mca/filterfw/java/android/filterfw/core/Filter.java b/media/mca/filterfw/java/android/filterfw/core/Filter.java
index 4f56b92..a608ef5 100644
--- a/media/mca/filterfw/java/android/filterfw/core/Filter.java
+++ b/media/mca/filterfw/java/android/filterfw/core/Filter.java
@@ -17,19 +17,15 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.FilterContext;
-import android.filterfw.core.FilterPort;
-import android.filterfw.core.KeyValueMap;
-import android.filterfw.io.TextGraphReader;
-import android.filterfw.io.GraphIOException;
+import android.compat.annotation.UnsupportedAppUsage;
import android.filterfw.format.ObjectFormat;
+import android.filterfw.io.GraphIOException;
+import android.filterfw.io.TextGraphReader;
import android.util.Log;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
-import java.lang.Thread;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
diff --git a/media/mca/filterfw/java/android/filterfw/core/FilterContext.java b/media/mca/filterfw/java/android/filterfw/core/FilterContext.java
index a19220e..6b0a219 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FilterContext.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FilterContext.java
@@ -17,11 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.Filter;
-import android.filterfw.core.Frame;
-import android.filterfw.core.FrameManager;
-import android.filterfw.core.GLEnvironment;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.HashMap;
import java.util.HashSet;
diff --git a/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java b/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java
index e6ca11f..35a298f 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FilterGraph.java
@@ -17,6 +17,11 @@
package android.filterfw.core;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.filterpacks.base.FrameBranch;
+import android.filterpacks.base.NullFilter;
+import android.util.Log;
+
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -25,14 +30,6 @@
import java.util.Set;
import java.util.Stack;
-import android.filterfw.core.FilterContext;
-import android.filterfw.core.KeyValueMap;
-import android.filterpacks.base.FrameBranch;
-import android.filterpacks.base.NullFilter;
-
-import android.annotation.UnsupportedAppUsage;
-import android.util.Log;
-
/**
* @hide
*/
diff --git a/media/mca/filterfw/java/android/filterfw/core/Frame.java b/media/mca/filterfw/java/android/filterfw/core/Frame.java
index e880783..c4d935a 100644
--- a/media/mca/filterfw/java/android/filterfw/core/Frame.java
+++ b/media/mca/filterfw/java/android/filterfw/core/Frame.java
@@ -17,9 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.FrameFormat;
-import android.filterfw.core.FrameManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import java.nio.ByteBuffer;
diff --git a/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java b/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java
index eb0ff0a..a87e9b9 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FrameFormat.java
@@ -17,9 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.KeyValueMap;
-import android.filterfw.core.MutableFrameFormat;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.Arrays;
import java.util.Map.Entry;
diff --git a/media/mca/filterfw/java/android/filterfw/core/FrameManager.java b/media/mca/filterfw/java/android/filterfw/core/FrameManager.java
index 85c8fcd..e49aaf1 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FrameManager.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FrameManager.java
@@ -17,10 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.Frame;
-import android.filterfw.core.FrameFormat;
-import android.filterfw.core.MutableFrameFormat;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java b/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java
index e25d6a7..7e4e8a6 100644
--- a/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java
+++ b/media/mca/filterfw/java/android/filterfw/core/GLEnvironment.java
@@ -17,13 +17,12 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.NativeAllocatorTag;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.SurfaceTexture;
+import android.media.MediaRecorder;
import android.os.Looper;
import android.util.Log;
import android.view.Surface;
-import android.media.MediaRecorder;
/**
* @hide
diff --git a/media/mca/filterfw/java/android/filterfw/core/GLFrame.java b/media/mca/filterfw/java/android/filterfw/core/GLFrame.java
index 9e3025f..1ccd7fe 100644
--- a/media/mca/filterfw/java/android/filterfw/core/GLFrame.java
+++ b/media/mca/filterfw/java/android/filterfw/core/GLFrame.java
@@ -17,15 +17,10 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.Frame;
-import android.filterfw.core.FrameFormat;
-import android.filterfw.core.FrameManager;
-import android.filterfw.core.NativeFrame;
-import android.filterfw.core.StopWatchMap;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
-import android.opengl.GLES20;
import android.graphics.Rect;
+import android.opengl.GLES20;
import java.nio.ByteBuffer;
diff --git a/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java b/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java
index 250cfaa..b57e8bb 100644
--- a/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java
+++ b/media/mca/filterfw/java/android/filterfw/core/GraphRunner.java
@@ -17,7 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java b/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java
index ae2ad99..da00b1f 100644
--- a/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java
+++ b/media/mca/filterfw/java/android/filterfw/core/MutableFrameFormat.java
@@ -17,9 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.FrameFormat;
-import android.filterfw.core.KeyValueMap;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.Arrays;
diff --git a/media/mca/filterfw/java/android/filterfw/core/Program.java b/media/mca/filterfw/java/android/filterfw/core/Program.java
index 376c085..145388e 100644
--- a/media/mca/filterfw/java/android/filterfw/core/Program.java
+++ b/media/mca/filterfw/java/android/filterfw/core/Program.java
@@ -17,8 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.Frame;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java b/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java
index f41636e..e043be0 100644
--- a/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java
+++ b/media/mca/filterfw/java/android/filterfw/core/ShaderProgram.java
@@ -17,12 +17,7 @@
package android.filterfw.core;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.core.Frame;
-import android.filterfw.core.NativeAllocatorTag;
-import android.filterfw.core.Program;
-import android.filterfw.core.StopWatchMap;
-import android.filterfw.core.VertexFrame;
+import android.compat.annotation.UnsupportedAppUsage;
import android.filterfw.geometry.Quad;
import android.opengl.GLES20;
diff --git a/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java b/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java
index ac08730..0e05092 100644
--- a/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java
+++ b/media/mca/filterfw/java/android/filterfw/format/ImageFormat.java
@@ -17,7 +17,7 @@
package android.filterfw.format;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.filterfw.core.FrameFormat;
import android.filterfw.core.MutableFrameFormat;
import android.graphics.Bitmap;
diff --git a/media/mca/filterfw/java/android/filterfw/geometry/Point.java b/media/mca/filterfw/java/android/filterfw/geometry/Point.java
index d7acf12..96d2d7b 100644
--- a/media/mca/filterfw/java/android/filterfw/geometry/Point.java
+++ b/media/mca/filterfw/java/android/filterfw/geometry/Point.java
@@ -17,8 +17,7 @@
package android.filterfw.geometry;
-import android.annotation.UnsupportedAppUsage;
-import java.lang.Math;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/media/mca/filterfw/java/android/filterfw/geometry/Quad.java b/media/mca/filterfw/java/android/filterfw/geometry/Quad.java
index 610e5b8..2b308a9 100644
--- a/media/mca/filterfw/java/android/filterfw/geometry/Quad.java
+++ b/media/mca/filterfw/java/android/filterfw/geometry/Quad.java
@@ -17,10 +17,8 @@
package android.filterfw.geometry;
-import android.annotation.UnsupportedAppUsage;
-import android.filterfw.geometry.Point;
+import android.compat.annotation.UnsupportedAppUsage;
-import java.lang.Float;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
diff --git a/mms/OWNERS b/mms/OWNERS
index ba00d5d..befc320 100644
--- a/mms/OWNERS
+++ b/mms/OWNERS
@@ -12,3 +12,5 @@
shuoq@google.com
refuhoo@google.com
nazaninb@google.com
+sarahchin@google.com
+dbright@google.com
\ No newline at end of file
diff --git a/mms/java/android/telephony/MmsManager.java b/mms/java/android/telephony/MmsManager.java
index 4bcf046..6554267 100644
--- a/mms/java/android/telephony/MmsManager.java
+++ b/mms/java/android/telephony/MmsManager.java
@@ -97,22 +97,4 @@
// Ignore it
}
}
-
- /**
- * Get carrier-dependent configuration values.
- *
- * @param subId the subscription id
- * @return bundle key/values pairs of configuration values
- */
- public Bundle getCarrierConfigValues(int subId) {
- try {
- IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
- if (iMms != null) {
- return iMms.getCarrierConfigValues(subId);
- }
- } catch (RemoteException ex) {
- // ignore it
- }
- return null;
- }
}
diff --git a/mms/java/com/android/internal/telephony/IMms.aidl b/mms/java/com/android/internal/telephony/IMms.aidl
index fa5073e..8be5111 100644
--- a/mms/java/com/android/internal/telephony/IMms.aidl
+++ b/mms/java/com/android/internal/telephony/IMms.aidl
@@ -60,13 +60,6 @@
in PendingIntent downloadedIntent);
/**
- * Get carrier-dependent configuration values.
- *
- * @param subId the SIM id
- */
- Bundle getCarrierConfigValues(int subId);
-
- /**
* Import a text message into system's SMS store
*
* @param callingPkg the calling app's package name
diff --git a/opengl/java/android/opengl/EGL14.java b/opengl/java/android/opengl/EGL14.java
index 728e6e1..90b46fd 100644
--- a/opengl/java/android/opengl/EGL14.java
+++ b/opengl/java/android/opengl/EGL14.java
@@ -18,11 +18,11 @@
package android.opengl;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.SurfaceTexture;
import android.view.Surface;
-import android.view.SurfaceView;
import android.view.SurfaceHolder;
+import android.view.SurfaceView;
/**
* EGL 1.4
diff --git a/opengl/java/android/opengl/GLES20.java b/opengl/java/android/opengl/GLES20.java
index d66e7ac..e853e44 100644
--- a/opengl/java/android/opengl/GLES20.java
+++ b/opengl/java/android/opengl/GLES20.java
@@ -19,7 +19,7 @@
package android.opengl;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/** OpenGL ES 2.0
*/
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 8a3e6a0..75131b0 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -16,7 +16,7 @@
package android.opengl;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Trace;
import android.util.AttributeSet;
diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java
index f94f69f..b4ea0a6 100644
--- a/opengl/java/com/google/android/gles_jni/EGLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java
@@ -16,13 +16,12 @@
package com.google.android.gles_jni;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.SurfaceTexture;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 2a8d07f..3c808a6 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -20,14 +20,13 @@
package com.google.android.gles_jni;
import android.app.AppGlobals;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.os.Build;
import android.os.UserHandle;
import android.util.Log;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.nio.Buffer;
import javax.microedition.khronos.opengles.GL10;
diff --git a/opengl/java/javax/microedition/khronos/egl/EGL10.java b/opengl/java/javax/microedition/khronos/egl/EGL10.java
index 8a25170..ea571c7 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGL10.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGL10.java
@@ -16,8 +16,7 @@
package javax.microedition.khronos.egl;
-import android.annotation.UnsupportedAppUsage;
-import java.lang.String;
+import android.compat.annotation.UnsupportedAppUsage;
public interface EGL10 extends EGL {
int EGL_SUCCESS = 0x3000;
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
index 672879a..68da999 100644
--- a/packages/CarSystemUI/Android.bp
+++ b/packages/CarSystemUI/Android.bp
@@ -82,7 +82,7 @@
],
platform_apis: true,
- product_specific: true,
+ system_ext_specific: true,
certificate: "platform",
privileged: true,
diff --git a/packages/CarSystemUI/CleanSpec.mk b/packages/CarSystemUI/CleanSpec.mk
new file mode 100644
index 0000000..ceac67c
--- /dev/null
+++ b/packages/CarSystemUI/CleanSpec.mk
@@ -0,0 +1,50 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# *****************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
+# *****************************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/priv-app/CarSystemUI)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/priv-app/CarSystemUI)
+# ******************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
+# ******************************************************************
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 9e49826..9ccb837 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -56,6 +56,7 @@
import android.os.RemoteException;
import android.os.image.DynamicSystemClient;
import android.os.image.DynamicSystemManager;
+import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
@@ -74,6 +75,8 @@
// TODO (b/131866826): This is currently for test only. Will move this to System API.
static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED";
+ static final String KEY_DSU_SLOT = "KEY_DSU_SLOT";
+ static final String DEFAULT_DSU_SLOT = "dsu";
/*
* Intent actions
@@ -244,10 +247,15 @@
long systemSize = intent.getLongExtra(DynamicSystemClient.KEY_SYSTEM_SIZE, 0);
long userdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0);
mEnableWhenCompleted = intent.getBooleanExtra(KEY_ENABLE_WHEN_COMPLETED, false);
+ String dsuSlot = intent.getStringExtra(KEY_DSU_SLOT);
+ if (TextUtils.isEmpty(dsuSlot)) {
+ dsuSlot = DEFAULT_DSU_SLOT;
+ }
// TODO: better constructor or builder
- mInstallTask = new InstallationAsyncTask(
- url, systemSize, userdataSize, this, mDynSystem, this);
+ mInstallTask =
+ new InstallationAsyncTask(
+ url, dsuSlot, systemSize, userdataSize, this, mDynSystem, this);
mInstallTask.execute();
@@ -262,10 +270,11 @@
return;
}
+ stopForeground(true);
mJustCancelledByUser = true;
if (mInstallTask.cancel(false)) {
- // Will cleanup and post status in onResult()
+ // Will stopSelf() in onResult()
Log.d(TAG, "Cancel request filed successfully");
} else {
Log.e(TAG, "Trying to cancel installation while it's already completed.");
@@ -408,7 +417,9 @@
break;
case STATUS_READY:
- builder.setContentText(getString(R.string.notification_install_completed));
+ String msgCompleted = getString(R.string.notification_install_completed);
+ builder.setContentText(msgCompleted)
+ .setStyle(new Notification.BigTextStyle().bigText(msgCompleted));
builder.addAction(new Notification.Action.Builder(
null, getString(R.string.notification_action_discard),
@@ -421,7 +432,9 @@
break;
case STATUS_IN_USE:
- builder.setContentText(getString(R.string.notification_dynsystem_in_use));
+ String msgInUse = getString(R.string.notification_dynsystem_in_use);
+ builder.setContentText(msgInUse)
+ .setStyle(new Notification.BigTextStyle().bigText(msgInUse));
builder.addAction(new Notification.Action.Builder(
null, getString(R.string.notification_action_uninstall),
@@ -451,7 +464,49 @@
}
private void postStatus(int status, int cause, Throwable detail) {
- Log.d(TAG, "postStatus(): statusCode=" + status + ", causeCode=" + cause);
+ String statusString;
+ String causeString;
+
+ switch (status) {
+ case STATUS_NOT_STARTED:
+ statusString = "NOT_STARTED";
+ break;
+ case STATUS_IN_PROGRESS:
+ statusString = "IN_PROGRESS";
+ break;
+ case STATUS_READY:
+ statusString = "READY";
+ break;
+ case STATUS_IN_USE:
+ statusString = "IN_USE";
+ break;
+ default:
+ statusString = "UNKNOWN";
+ break;
+ }
+
+ switch (cause) {
+ case CAUSE_INSTALL_COMPLETED:
+ causeString = "INSTALL_COMPLETED";
+ break;
+ case CAUSE_INSTALL_CANCELLED:
+ causeString = "INSTALL_CANCELLED";
+ break;
+ case CAUSE_ERROR_IO:
+ causeString = "ERROR_IO";
+ break;
+ case CAUSE_ERROR_INVALID_URL:
+ causeString = "ERROR_INVALID_URL";
+ break;
+ case CAUSE_ERROR_EXCEPTION:
+ causeString = "ERROR_EXCEPTION";
+ break;
+ default:
+ causeString = "CAUSE_NOT_SPECIFIED";
+ break;
+ }
+
+ Log.d(TAG, "status=" + statusString + ", cause=" + causeString);
boolean notifyOnNotificationBar = true;
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index b206a1f..9aea0e7 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -89,10 +89,12 @@
interface ProgressListener {
void onProgressUpdate(Progress progress);
+
void onResult(int resultCode, Throwable detail);
}
private final String mUrl;
+ private final String mDsuSlot;
private final long mSystemSize;
private final long mUserdataSize;
private final Context mContext;
@@ -106,9 +108,16 @@
private InputStream mStream;
private ZipFile mZipFile;
- InstallationAsyncTask(String url, long systemSize, long userdataSize, Context context,
- DynamicSystemManager dynSystem, ProgressListener listener) {
+ InstallationAsyncTask(
+ String url,
+ String dsuSlot,
+ long systemSize,
+ long userdataSize,
+ Context context,
+ DynamicSystemManager dynSystem,
+ ProgressListener listener) {
mUrl = url;
+ mDsuSlot = dsuSlot;
mSystemSize = systemSize;
mUserdataSize = userdataSize;
mContext = context;
@@ -126,14 +135,17 @@
verifyAndPrepare();
- mDynSystem.startInstallation();
+ mDynSystem.startInstallation(mDsuSlot);
installUserdata();
if (isCancelled()) {
mDynSystem.remove();
return null;
}
-
+ if (mUrl == null) {
+ mDynSystem.finishInstallation();
+ return null;
+ }
installImages();
if (isCancelled()) {
mDynSystem.remove();
@@ -194,6 +206,9 @@
}
private void verifyAndPrepare() throws Exception {
+ if (mUrl == null) {
+ return;
+ }
String extension = mUrl.substring(mUrl.lastIndexOf('.') + 1);
if ("gz".equals(extension) || "gzip".equals(extension)) {
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
index 3b3933b..e42ded7 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
@@ -28,11 +28,9 @@
import android.util.FeatureFlagUtils;
import android.util.Log;
-
/**
- * This Activity starts KeyguardManager and ask the user to confirm
- * before any installation request. If the device is not protected by
- * a password, it approves the request by default.
+ * This Activity starts KeyguardManager and ask the user to confirm before any installation request.
+ * If the device is not protected by a password, it approves the request by default.
*/
public class VerificationActivity extends Activity {
@@ -88,11 +86,15 @@
Uri url = callingIntent.getData();
Bundle extras = callingIntent.getExtras();
- sVerifiedUrl = url.toString();
+ if (url != null) {
+ sVerifiedUrl = url.toString();
+ }
// start service
Intent intent = new Intent(this, DynamicSystemInstallationService.class);
- intent.setData(url);
+ if (url != null) {
+ intent.setData(url);
+ }
intent.setAction(DynamicSystemClient.ACTION_START_INSTALL);
intent.putExtras(extras);
@@ -106,6 +108,7 @@
}
static boolean isVerified(String url) {
+ if (url == null) return true;
return sVerifiedUrl != null && sVerifiedUrl.equals(url);
}
}
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 39c55fd..413211d 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -132,6 +132,20 @@
<item>avrcp16</item>
</string-array>
+ <!-- Titles for Bluetooth MAP Versions -->
+ <string-array name="bluetooth_map_versions">
+ <item>MAP 1.2 (Default)</item>
+ <item>MAP 1.3</item>
+ <item>MAP 1.4</item>
+ </string-array>
+
+ <!-- Values for Bluetooth MAP Versions -->
+ <string-array name="bluetooth_map_version_values">
+ <item>map12</item>
+ <item>map13</item>
+ <item>map14</item>
+ </string-array>
+
<!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=50] -->
<string-array name="bluetooth_a2dp_codec_titles">
<item>Use System Selection (Default)</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index bdfa217..8c2ff2c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -597,6 +597,11 @@
<!-- UI debug setting: Select Bluetooth AVRCP Version -->
<string name="bluetooth_select_avrcp_version_dialog_title">Select Bluetooth AVRCP Version</string>
+ <!-- UI debug setting: Select Bluetooth MAP Version [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_select_map_version_string">Bluetooth MAP Version</string>
+ <!-- UI debug setting: Select Bluetooth MAP Version [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_select_map_version_dialog_title">Select Bluetooth MAP Version</string>
+
<!-- UI debug setting: Trigger Bluetooth Audio Codec Selection -->
<string name="bluetooth_select_a2dp_codec_type">Bluetooth Audio Codec</string>
<!-- UI debug setting: Trigger Bluetooth Audio Codec Selection -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
index 69bd0ed..ff00fb3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
@@ -16,8 +16,6 @@
package com.android.settingslib;
-import static android.content.Context.TELEPHONY_SERVICE;
-
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -172,36 +170,38 @@
}
}
- public static String getFormattedPhoneNumber(Context context, SubscriptionInfo subscriptionInfo) {
+ /**
+ * Format a phone number.
+ * @param subscriptionInfo {@link SubscriptionInfo} subscription information.
+ * @return Returns formatted phone number.
+ */
+ public static String getFormattedPhoneNumber(Context context,
+ SubscriptionInfo subscriptionInfo) {
String formattedNumber = null;
if (subscriptionInfo != null) {
- final TelephonyManager telephonyManager =
- (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
- final String rawNumber =
- telephonyManager.getLine1Number(subscriptionInfo.getSubscriptionId());
+ final TelephonyManager telephonyManager = context.getSystemService(
+ TelephonyManager.class);
+ final String rawNumber = telephonyManager.createForSubscriptionId(
+ subscriptionInfo.getSubscriptionId()).getLine1Number();
if (!TextUtils.isEmpty(rawNumber)) {
formattedNumber = PhoneNumberUtils.formatNumber(rawNumber);
}
-
}
return formattedNumber;
}
public static String getFormattedPhoneNumbers(Context context,
- List<SubscriptionInfo> subscriptionInfo) {
+ List<SubscriptionInfo> subscriptionInfoList) {
StringBuilder sb = new StringBuilder();
- if (subscriptionInfo != null) {
- final TelephonyManager telephonyManager =
- (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
- final int count = subscriptionInfo.size();
- for (int i = 0; i < count; i++) {
- final String rawNumber = telephonyManager.getLine1Number(
- subscriptionInfo.get(i).getSubscriptionId());
+ if (subscriptionInfoList != null) {
+ final TelephonyManager telephonyManager = context.getSystemService(
+ TelephonyManager.class);
+ final int count = subscriptionInfoList.size();
+ for (SubscriptionInfo subscriptionInfo : subscriptionInfoList) {
+ final String rawNumber = telephonyManager.createForSubscriptionId(
+ subscriptionInfo.getSubscriptionId()).getLine1Number();
if (!TextUtils.isEmpty(rawNumber)) {
- sb.append(PhoneNumberUtils.formatNumber(rawNumber));
- if (i < count - 1) {
- sb.append("\n");
- }
+ sb.append(PhoneNumberUtils.formatNumber(rawNumber)).append("\n");
}
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index ee44d0a..1141daa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -421,7 +421,7 @@
// is not available. Note that we ignore the IWLAN service state
// because that state indicates the use of VoWIFI and not cell service
final int state = serviceState.getState();
- final int dataState = serviceState.getDataRegState();
+ final int dataState = serviceState.getDataRegistrationState();
if (state == ServiceState.STATE_OUT_OF_SERVICE
|| state == ServiceState.STATE_EMERGENCY_ONLY) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index abfee1d..9765074 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -184,13 +184,28 @@
}
}
+ /**
+ * Connect this device.
+ *
+ * @param connectAllProfiles {@code true} to connect all profile, {@code false} otherwise.
+ *
+ * @deprecated use {@link #connect()} instead.
+ */
+ @Deprecated
public void connect(boolean connectAllProfiles) {
+ connect();
+ }
+
+ /**
+ * Connect this device.
+ */
+ public void connect() {
if (!ensurePaired()) {
return;
}
mConnectAttempted = SystemClock.elapsedRealtime();
- connectWithoutResettingTimer(connectAllProfiles);
+ connectAllEnabledProfiles();
}
public long getHiSyncId() {
@@ -211,10 +226,10 @@
void onBondingDockConnect() {
// Attempt to connect if UUIDs are available. Otherwise,
// we will connect when the ACTION_UUID intent arrives.
- connect(false);
+ connect();
}
- private void connectWithoutResettingTimer(boolean connectAllProfiles) {
+ private void connectAllEnabledProfiles() {
synchronized (mProfileLock) {
// Try to initialize the profiles if they were not.
if (mProfiles.isEmpty()) {
@@ -229,36 +244,7 @@
return;
}
- int preferredProfiles = 0;
- for (LocalBluetoothProfile profile : mProfiles) {
- if (connectAllProfiles ? profile.accessProfileEnabled()
- : profile.isAutoConnectable()) {
- if (profile.isPreferred(mDevice)) {
- ++preferredProfiles;
- connectInt(profile);
- }
- }
- }
- if (BluetoothUtils.D) Log.d(TAG, "Preferred profiles = " + preferredProfiles);
-
- if (preferredProfiles == 0) {
- connectAutoConnectableProfiles();
- }
- }
- }
-
- private void connectAutoConnectableProfiles() {
- if (!ensurePaired()) {
- return;
- }
-
- synchronized (mProfileLock) {
- for (LocalBluetoothProfile profile : mProfiles) {
- if (profile.isAutoConnectable()) {
- profile.setPreferred(mDevice, true);
- connectInt(profile);
- }
- }
+ mLocalAdapter.connectAllEnabledProfiles(mDevice);
}
}
@@ -625,7 +611,7 @@
*/
if (!mProfiles.isEmpty()
&& ((mConnectAttempted + timeout) > SystemClock.elapsedRealtime())) {
- connectWithoutResettingTimer(false);
+ connectAllEnabledProfiles();
}
dispatchAttributesChanged();
@@ -644,7 +630,7 @@
refresh();
if (bondState == BluetoothDevice.BOND_BONDED && mDevice.isBondingInitiatedLocally()) {
- connect(false);
+ connect();
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 4e16c66..56b14c6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -116,7 +116,7 @@
final CachedBluetoothDevice cachedDevice =
((BluetoothMediaDevice) device).getCachedDevice();
if (!cachedDevice.isConnected() && !cachedDevice.isBusy()) {
- cachedDevice.connect(true);
+ cachedDevice.connect();
return;
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
index 23e29493..d5ff1ee 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -38,7 +38,7 @@
final SubscriptionManager subscriptionManager = context.getSystemService(
SubscriptionManager.class);
final NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(
- telephonyManager.getSubscriberId(subId));
+ telephonyManager.createForSubscriptionId(subId).getSubscriberId());
if (!subscriptionManager.isActiveSubId(subId)) {
Log.i(TAG, "Subscription is not active: " + subId);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index b11585a..8bd5f57f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -90,7 +90,7 @@
public void setListening(boolean listening) {
if (listening) {
mNetworkScoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
- mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
+ mWifiNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_CURRENT_NETWORK);
mWifiNetworkScoreCache.registerListener(mCacheListener);
mConnectivityManager.registerNetworkCallback(
mNetworkRequest, mNetworkCallback, mHandler);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 3e359d2..f713139 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -359,7 +359,7 @@
mNetworkScoreManager.registerNetworkScoreCache(
NetworkKey.TYPE_WIFI,
mScoreCache,
- NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
+ NetworkScoreManager.SCORE_FILTER_SCAN_RESULTS);
}
private void requestScoresForNetworkKeys(Collection<NetworkKey> keys) {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/OWNER b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/OWNER
new file mode 100644
index 0000000..5c2a7b8
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/OWNER
@@ -0,0 +1,4 @@
+# People who can approve changes for submission
+arcwang@google.com
+govenliu@google.com
+qal@google.com
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index 51806e0..4948987 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -227,7 +227,7 @@
@Test
public void isInService_voiceOutOfServiceDataInService_returnTrue() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
@@ -243,7 +243,7 @@
AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
assertThat(Utils.isInService(mServiceState)).isFalse();
}
@@ -251,7 +251,8 @@
@Test
public void isInService_voiceOutOfServiceDataOutOfService_returnFalse() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(
+ ServiceState.STATE_OUT_OF_SERVICE);
assertThat(Utils.isInService(mServiceState)).isFalse();
}
@@ -288,7 +289,7 @@
@Test
public void getCombinedServiceState_voiceOutOfServiceDataInService_returnInService() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
@@ -301,7 +302,7 @@
@Test
public void getCombinedServiceState_voiceOutOfServiceDataInServiceOnIwLan_returnOutOfService() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
@@ -314,7 +315,8 @@
@Test
public void getCombinedServiceState_voiceOutOfServiceDataOutOfService_returnOutOfService() {
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState.getDataRegistrationState()).thenReturn(
+ ServiceState.STATE_OUT_OF_SERVICE);
assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
ServiceState.STATE_OUT_OF_SERVICE);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
index 98bb74a..4b9f6c2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
@@ -127,7 +127,7 @@
mLocalMediaManager.registerCallback(mCallback);
mLocalMediaManager.connectDevice(device);
- verify(cachedDevice).connect(true);
+ verify(cachedDevice).connect();
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/OWNER b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/OWNER
new file mode 100644
index 0000000..5c2a7b8
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/OWNER
@@ -0,0 +1,4 @@
+# People who can approve changes for submission
+arcwang@google.com
+govenliu@google.com
+qal@google.com
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index efd31ca..af2569d 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -186,6 +186,9 @@
<uses-permission android:name="android.permission.MANAGE_APPOPS" />
+ <!-- Permission required for storage tests - FuseDaemonHostTest -->
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
+
<!-- Permission needed to run network tests in CTS -->
<uses-permission android:name="android.permission.MANAGE_TEST_NETWORKS" />
<!-- Permission needed to test tcp keepalive offload. -->
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index d674be4..dbfaca0 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -142,7 +142,7 @@
resource_dirs: [],
platform_apis: true,
- product_specific: true,
+ system_ext_specific: true,
certificate: "platform",
privileged: true,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 403e894..262365d 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -72,7 +72,7 @@
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
- <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
<uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
diff --git a/packages/SystemUI/CleanSpec.mk b/packages/SystemUI/CleanSpec.mk
new file mode 100644
index 0000000..2a2e4e4
--- /dev/null
+++ b/packages/SystemUI/CleanSpec.mk
@@ -0,0 +1,50 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# *****************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
+# *****************************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product/priv-app/SystemUI)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/priv-app/SystemUI)
+# ******************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
+# ******************************************************************
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid_item.xml b/packages/SystemUI/res/layout-land/global_actions_grid_item.xml
index bc12338..0f9deaa 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid_item.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid_item.xml
@@ -57,15 +57,5 @@
android:textColor="@color/global_actions_text"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
-
- <TextView
- android:visibility="gone"
- android:id="@*android:id/status"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:textColor="@color/global_actions_text"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item.xml b/packages/SystemUI/res/layout/global_actions_grid_item.xml
index 4404c874..31c7cbf 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_item.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_item.xml
@@ -56,15 +56,5 @@
android:textColor="@color/global_actions_text"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
-
- <TextView
- android:visibility="gone"
- android:id="@*android:id/status"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:textColor="@color/global_actions_text"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 9d9cad8..8631e86 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -348,7 +348,7 @@
}
if (simState == IccCardConstants.State.READY) {
ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId);
- if (ss != null && ss.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
+ if (ss != null && ss.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE) {
// hack for WFC (IWLAN) not turning off immediately once
// Wi-Fi is disassociated or disabled
if (ss.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 367a7bd..0ffe05d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -26,8 +26,6 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -37,7 +35,6 @@
import android.view.WindowManager;
import android.widget.ImageView;
-import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.PhoneConstants;
@@ -254,12 +251,22 @@
@Override
public void run() {
- try {
- if (DEBUG) {
- Log.v(TAG, "call supplyPinReportResultForSubscriber(subid=" + mSubId + ")");
- }
- final int[] result = ITelephony.Stub.asInterface(ServiceManager
- .checkService("phone")).supplyPinReportResultForSubscriber(mSubId, mPin);
+ if (DEBUG) {
+ Log.v(TAG, "call supplyPinReportResultForSubscriber(subid=" + mSubId + ")");
+ }
+ TelephonyManager telephonyManager =
+ ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE))
+ .createForSubscriptionId(mSubId);
+ final int[] result = telephonyManager.supplyPinReportResult(mPin);
+ if (result == null || result.length == 0) {
+ Log.e(TAG, "Error result for supplyPinReportResult.");
+ post(new Runnable() {
+ @Override
+ public void run() {
+ onSimCheckResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
+ }
+ });
+ } else {
if (DEBUG) {
Log.v(TAG, "supplyPinReportResult returned: " + result[0] + " " + result[1]);
}
@@ -269,14 +276,6 @@
onSimCheckResponse(result[0], result[1]);
}
});
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException for supplyPinReportResult:", e);
- post(new Runnable() {
- @Override
- public void run() {
- onSimCheckResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
- }
- });
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 81f8c67..abadcfd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -25,8 +25,6 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -36,7 +34,6 @@
import android.view.WindowManager;
import android.widget.ImageView;
-import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.PhoneConstants;
@@ -314,10 +311,20 @@
@Override
public void run() {
- try {
- if (DEBUG) Log.v(TAG, "call supplyPukReportResult()");
- final int[] result = ITelephony.Stub.asInterface(ServiceManager
- .checkService("phone")).supplyPukReportResultForSubscriber(mSubId, mPuk, mPin);
+ if (DEBUG) Log.v(TAG, "call supplyPukReportResult()");
+ TelephonyManager telephonyManager =
+ ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE))
+ .createForSubscriptionId(mSubId);
+ final int[] result = telephonyManager.supplyPukReportResult(mPuk, mPin);
+ if (result == null || result.length == 0) {
+ Log.e(TAG, "Error result for supplyPukReportResult.");
+ post(new Runnable() {
+ @Override
+ public void run() {
+ onSimLockChangedResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
+ }
+ });
+ } else {
if (DEBUG) {
Log.v(TAG, "supplyPukReportResult returned: " + result[0] + " " + result[1]);
}
@@ -327,14 +334,6 @@
onSimLockChangedResponse(result[0], result[1]);
}
});
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException for supplyPukReportResult:", e);
- post(new Runnable() {
- @Override
- public void run() {
- onSimLockChangedResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
- }
- });
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 8d858dc..1fb50a9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1061,7 +1061,7 @@
// keep compatibility with apps that aren't direct boot aware.
// SysUI should just ignore this broadcast because it was already received
// and processed previously.
- if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
+ if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
// Guarantee mTelephonyCapable state after SysUI crash and restart
if (args.simState == State.ABSENT) {
mHandler.obtainMessage(MSG_TELEPHONY_CAPABLE, true).sendToTarget();
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index ff02e71..589b24a 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1145,13 +1145,6 @@
TextView messageView = (TextView) v.findViewById(R.id.message);
messageView.setSelected(true); // necessary for marquee to work
- TextView statusView = (TextView) v.findViewById(R.id.status);
- final String status = getStatus();
- if (!TextUtils.isEmpty(status)) {
- statusView.setText(status);
- } else {
- statusView.setVisibility(View.GONE);
- }
if (mIcon != null) {
icon.setImageDrawable(mIcon);
icon.setScaleType(ScaleType.CENTER_CROP);
@@ -1236,32 +1229,26 @@
LayoutInflater inflater) {
willCreate();
- View v = inflater.inflate(R
- .layout.global_actions_item, parent, false);
+ View v = inflater.inflate(com.android.systemui.R
+ .layout.global_actions_grid_item, parent, false);
ImageView icon = (ImageView) v.findViewById(R.id.icon);
TextView messageView = (TextView) v.findViewById(R.id.message);
- TextView statusView = (TextView) v.findViewById(R.id.status);
final boolean enabled = isEnabled();
+ boolean on = ((mState == State.On) || (mState == State.TurningOn));
if (messageView != null) {
- messageView.setText(mMessageResId);
+ messageView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
messageView.setEnabled(enabled);
messageView.setSelected(true); // necessary for marquee to work
}
- boolean on = ((mState == State.On) || (mState == State.TurningOn));
if (icon != null) {
icon.setImageDrawable(context.getDrawable(
(on ? mEnabledIconResId : mDisabledIconResid)));
icon.setEnabled(enabled);
}
- if (statusView != null) {
- statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
- statusView.setVisibility(View.VISIBLE);
- statusView.setEnabled(enabled);
- }
v.setEnabled(enabled);
return v;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 4700baa..18d436f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -421,7 +421,7 @@
}
/** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
- private static class AnimateCloseListener extends AnimatorListenerAdapter {
+ private class AnimateCloseListener extends AnimatorListenerAdapter {
final View mView;
private final GutsContent mGutsContent;
@@ -433,8 +433,10 @@
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- mView.setVisibility(View.GONE);
- mGutsContent.onFinishedClosing();
+ if (!isExposed()) {
+ mView.setVisibility(View.GONE);
+ mGutsContent.onFinishedClosing();
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 8f7671a..719ec32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -100,6 +100,7 @@
protected String mKeyToRemoveOnGutsClosed;
private StatusBar mStatusBar;
+ private Runnable mOpenRunnable;
@Inject
public NotificationGutsManager(
@@ -343,6 +344,7 @@
public void closeAndSaveGuts(boolean removeLeavebehinds, boolean force, boolean removeControls,
int x, int y, boolean resetMenu) {
if (mNotificationGutsExposed != null) {
+ mNotificationGutsExposed.removeCallbacks(mOpenRunnable);
mNotificationGutsExposed.closeControls(removeLeavebehinds, removeControls, x, y, force);
}
if (resetMenu) {
@@ -445,7 +447,7 @@
// ensure that it's laid but not visible until actually laid out
guts.setVisibility(View.INVISIBLE);
// Post to ensure the the guts are properly laid out.
- guts.post(new Runnable() {
+ mOpenRunnable = new Runnable() {
@Override
public void run() {
if (row.getWindowToken() == null) {
@@ -470,7 +472,8 @@
mListContainer.onHeightChanged(row, true /* needsAnimation */);
mGutsMenuItem = menuItem;
}
- });
+ };
+ guts.post(mOpenRunnable);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index f4635d1..f7b8a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -67,6 +67,9 @@
}
private fun updateListeningState() {
+ if (pickupSensor == null) {
+ return
+ }
val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible &&
!statusBarStateController.isDozing
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 17c200e..b2f4f16 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -605,8 +605,7 @@
break;
case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
// Avoid rebroadcast because SysUI is direct boot aware.
- if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK,
- false)) {
+ if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
break;
}
updateSimState(intent);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 0c47d14..68ee8bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -62,6 +62,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import androidx.annotation.VisibleForTesting;
+
/**
* Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
* via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
@@ -161,6 +163,7 @@
private boolean mLastLockVisible;
private OnDismissAction mAfterKeyguardGoneAction;
+ private Runnable mKeyguardGoneCancelAction;
private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
// Dismiss action to be launched when we stop dozing or the keyguard is gone.
@@ -328,10 +331,20 @@
return false;
}
- private void hideBouncer(boolean destroyView) {
+ @VisibleForTesting
+ void hideBouncer(boolean destroyView) {
if (mBouncer == null) {
return;
}
+ if (mShowing) {
+ // If we were showing the bouncer and then aborting, we need to also clear out any
+ // potential actions unless we actually unlocked.
+ mAfterKeyguardGoneAction = null;
+ if (mKeyguardGoneCancelAction != null) {
+ mKeyguardGoneCancelAction.run();
+ mKeyguardGoneCancelAction = null;
+ }
+ }
mBouncer.hide(destroyView);
cancelPendingWakeupAction();
}
@@ -364,6 +377,7 @@
mBouncer.showWithDismissAction(r, cancelAction);
} else {
mAfterKeyguardGoneAction = r;
+ mKeyguardGoneCancelAction = cancelAction;
mBouncer.show(false /* resetSecuritySelection */);
}
}
@@ -671,6 +685,7 @@
mAfterKeyguardGoneAction.onDismiss();
mAfterKeyguardGoneAction = null;
}
+ mKeyguardGoneCancelAction = null;
for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
mAfterKeyguardGoneRunnables.get(i).run();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 582775e..1c646b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -15,6 +15,9 @@
*/
package com.android.systemui.statusbar.policy;
+import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
+import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
+
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
@@ -703,12 +706,16 @@
@Override
public void onServiceStateChanged(ServiceState state) {
if (DEBUG) {
- Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
- + " dataState=" + state.getDataRegState());
+ Log.d(mTag, "onServiceStateChanged voiceState=" + state.getState()
+ + " dataState=" + state.getDataRegistrationState());
}
mServiceState = state;
if (mServiceState != null) {
- updateDataNetType(mServiceState.getDataNetworkType());
+ NetworkRegistrationInfo regInfo = mServiceState.getNetworkRegistrationInfo(
+ DOMAIN_PS, TRANSPORT_TYPE_WWAN);
+ if (regInfo != null) {
+ updateDataNetType(regInfo.getAccessNetworkTechnology());
+ }
}
updateTelephony();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 7a09455..4523374 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -517,7 +517,7 @@
break;
case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
// Avoid rebroadcast because SysUI is direct boot aware.
- if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
+ if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
break;
}
// Might have different subscriptions now.
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index efb4ff0..a897b00 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -35,7 +35,6 @@
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_VR_MANAGER" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
<uses-permission android:name="android.permission.CONTROL_VPN" />
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index cfa5645..4d9ea29 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -339,7 +339,7 @@
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
ServiceState ss = mock(ServiceState.class);
- when(ss.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(ss.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE);
mKeyguardUpdateMonitor.mServiceStates.put(TEST_SUBSCRIPTION_NULL.getSubscriptionId(), ss);
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index db6177a..21585ed 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -133,7 +133,7 @@
Assert.assertTrue("onSimStateChanged not called",
mKeyguardUpdateMonitor.hasSimStateJustChanged());
- intent.putExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, true);
+ intent.putExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, true);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(), intent);
mTestableLooper.processAllMessages();
Assert.assertFalse("onSimStateChanged should have been skipped",
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 63f653b..0da0e76 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -221,6 +221,31 @@
verify(mStatusBar, never()).animateKeyguardUnoccluding();
}
+ @Test
+ public void testHiding_cancelsGoneRunnable() {
+ OnDismissAction action = mock(OnDismissAction.class);
+ Runnable cancelAction = mock(Runnable.class);
+ mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
+ true /* afterKeyguardGone */);
+
+ mStatusBarKeyguardViewManager.hideBouncer(true);
+ mStatusBarKeyguardViewManager.hide(0, 30);
+ verify(action, never()).onDismiss();
+ verify(cancelAction).run();
+ }
+
+ @Test
+ public void testHiding_doesntCancelWhenShowing() {
+ OnDismissAction action = mock(OnDismissAction.class);
+ Runnable cancelAction = mock(Runnable.class);
+ mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
+ true /* afterKeyguardGone */);
+
+ mStatusBarKeyguardViewManager.hide(0, 30);
+ verify(action).onDismiss();
+ verify(cancelAction, never()).run();
+ }
+
private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
public TestableStatusBarKeyguardViewManager(Context context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 354aa83..59270d8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.policy;
+import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
+import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
@@ -39,6 +42,7 @@
import android.os.Handler;
import android.provider.Settings;
import android.provider.Settings.Global;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
@@ -298,12 +302,12 @@
}
public void setVoiceRegState(int voiceRegState) {
- when(mServiceState.getVoiceRegState()).thenReturn(voiceRegState);
+ when(mServiceState.getState()).thenReturn(voiceRegState);
updateServiceState();
}
public void setDataRegState(int dataRegState) {
- when(mServiceState.getDataRegState()).thenReturn(dataRegState);
+ when(mServiceState.getDataRegistrationState()).thenReturn(dataRegState);
updateServiceState();
}
@@ -347,7 +351,13 @@
}
public void updateDataConnectionState(int dataState, int dataNetType) {
- when(mServiceState.getDataNetworkType()).thenReturn(dataNetType);
+ NetworkRegistrationInfo fakeRegInfo = new NetworkRegistrationInfo.Builder()
+ .setTransportType(TRANSPORT_TYPE_WWAN)
+ .setDomain(DOMAIN_PS)
+ .setAccessNetworkTechnology(dataNetType)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN))
+ .thenReturn(fakeRegInfo);
mPhoneStateListener.onDataConnectionStateChanged(dataState, dataNetType);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 99e5a76..47e0c3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -1,5 +1,8 @@
package com.android.systemui.statusbar.policy;
+import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
+import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyInt;
@@ -418,7 +421,13 @@
// State from NR_5G to NONE NR_STATE_RESTRICTED, showing corresponding icon
doReturn(NetworkRegistrationInfo.NR_STATE_RESTRICTED).when(mServiceState).getNrState();
- doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ NetworkRegistrationInfo fakeRegInfo = new NetworkRegistrationInfo.Builder()
+ .setTransportType(TRANSPORT_TYPE_WWAN)
+ .setDomain(DOMAIN_PS)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .build();
+ doReturn(fakeRegInfo).when(mServiceState)
+ .getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN);
mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
TelephonyManager.NETWORK_TYPE_LTE);
@@ -480,8 +489,13 @@
verifyDataIndicators(TelephonyIcons.ICON_LTE);
- when(mServiceState.getDataNetworkType())
- .thenReturn(TelephonyManager.NETWORK_TYPE_HSPA);
+ NetworkRegistrationInfo fakeRegInfo = new NetworkRegistrationInfo.Builder()
+ .setTransportType(TRANSPORT_TYPE_WWAN)
+ .setDomain(DOMAIN_PS)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_HSPA)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN))
+ .thenReturn(fakeRegInfo);
updateServiceState();
verifyDataIndicators(TelephonyIcons.ICON_H);
}
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 08552cb..1315ed0 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -20,7 +20,7 @@
srcs: [
"src/**/*.java",
":framework-tethering-shared-srcs",
- ":net-module-utils-srcs",
+ ":tethering-module-utils-srcs",
":services-tethering-shared-srcs",
],
static_libs: [
@@ -32,8 +32,9 @@
],
libs: [
"framework-tethering",
+ "unsupportedappusage",
],
-
+ plugins: ["java_api_finder"],
manifest: "AndroidManifestBase.xml",
}
@@ -45,9 +46,9 @@
// Due to b/143733063, APK can't access a jni lib that is in APEX (but not in the APK).
cc_library {
- name: "libtetheroffloadjni",
+ name: "libtetherutilsjni",
srcs: [
- "jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
+ "jni/android_net_util_TetheringUtils.cpp",
],
shared_libs: [
"libcgrouprc",
@@ -87,7 +88,7 @@
"libcgrouprc",
"libnativehelper_compat_libc++",
"libvndksupport",
- "libtetheroffloadjni",
+ "libtetherutilsjni",
],
resource_dirs: [
"res",
@@ -122,4 +123,5 @@
use_embedded_native_libs: true,
// The permission configuration *must* be included to ensure security of the device
required: ["NetworkPermissionConfig"],
+ apex_available: ["com.android.tethering"],
}
diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml
index 87a8c3f..c71d0d7 100644
--- a/packages/Tethering/AndroidManifest.xml
+++ b/packages/Tethering/AndroidManifest.xml
@@ -32,8 +32,11 @@
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MANAGE_USB" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
+ <uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
+ <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index 5785707..264ce44 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -47,6 +47,16 @@
libs: [
"android_system_stubs_current",
],
+
+ hostdex: true, // for hiddenapi check
+ visibility: [
+ "//frameworks/base/packages/Tethering:__subpackages__",
+ //TODO(b/147200698) remove below lines when the platform is built with stubs
+ "//frameworks/base",
+ "//frameworks/base/services",
+ "//frameworks/base/services/core",
+ ],
+ apex_available: ["com.android.tethering"],
}
filegroup {
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index a49ab85..11e5718 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -15,8 +15,6 @@
*/
package android.net;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-
import android.annotation.NonNull;
import android.content.Context;
import android.net.ConnectivityManager.OnTetheringEventCallback;
@@ -52,6 +50,103 @@
private TetheringConfigurationParcel mTetheringConfiguration;
private TetherStatesParcel mTetherStatesParcel;
+ /**
+ * Broadcast Action: A tetherable connection has come or gone.
+ * Uses {@code TetheringManager.EXTRA_AVAILABLE_TETHER},
+ * {@code TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY},
+ * {@code TetheringManager.EXTRA_ACTIVE_TETHER}, and
+ * {@code TetheringManager.EXTRA_ERRORED_TETHER} to indicate
+ * the current state of tethering. Each include a list of
+ * interface names in that state (may be empty).
+ */
+ public static final String ACTION_TETHER_STATE_CHANGED =
+ "android.net.conn.TETHER_STATE_CHANGED";
+
+ /**
+ * gives a String[] listing all the interfaces configured for
+ * tethering and currently available for tethering.
+ */
+ public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
+
+ /**
+ * gives a String[] listing all the interfaces currently in local-only
+ * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
+ */
+ public static final String EXTRA_ACTIVE_LOCAL_ONLY = "localOnlyArray";
+
+ /**
+ * gives a String[] listing all the interfaces currently tethered
+ * (ie, has DHCPv4 support and packets potentially forwarded/NATed)
+ */
+ public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
+
+ /**
+ * gives a String[] listing all the interfaces we tried to tether and
+ * failed. Use {@link #getLastTetherError} to find the error code
+ * for any interfaces listed here.
+ */
+ public static final String EXTRA_ERRORED_TETHER = "erroredArray";
+
+ /**
+ * Invalid tethering type.
+ * @see #startTethering.
+ */
+ public static final int TETHERING_INVALID = -1;
+
+ /**
+ * Wifi tethering type.
+ * @see #startTethering.
+ */
+ public static final int TETHERING_WIFI = 0;
+
+ /**
+ * USB tethering type.
+ * @see #startTethering.
+ */
+ public static final int TETHERING_USB = 1;
+
+ /**
+ * Bluetooth tethering type.
+ * @see #startTethering.
+ */
+ public static final int TETHERING_BLUETOOTH = 2;
+
+ /**
+ * Wifi P2p tethering type.
+ * Wifi P2p tethering is set through events automatically, and don't
+ * need to start from #startTethering.
+ */
+ public static final int TETHERING_WIFI_P2P = 3;
+
+ /**
+ * Extra used for communicating with the TetherService. Includes the type of tethering to
+ * enable if any.
+ */
+ public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
+
+ /**
+ * Extra used for communicating with the TetherService. Includes the type of tethering for
+ * which to cancel provisioning.
+ */
+ public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
+
+ /**
+ * Extra used for communicating with the TetherService. True to schedule a recheck of tether
+ * provisioning.
+ */
+ public static final String EXTRA_SET_ALARM = "extraSetAlarm";
+
+ /**
+ * Tells the TetherService to run a provision check now.
+ */
+ public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
+
+ /**
+ * Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
+ * which will receive provisioning results. Can be left empty.
+ */
+ public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
+
public static final int TETHER_ERROR_NO_ERROR = 0;
public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2;
@@ -470,7 +565,7 @@
* failed. Re-attempting to tether may cause them to reset to the Tethered
* state. Alternatively, causing the interface to be destroyed and recreated
* may cause them to reset to the available state.
- * {@link ConnectivityManager#getLastTetherError} can be used to get more
+ * {@link TetheringManager#getLastTetherError} can be used to get more
* information on the cause of the errors.
*
* @return an array of 0 or more String indicating the interface names
diff --git a/packages/Tethering/jarjar-rules.txt b/packages/Tethering/jarjar-rules.txt
index dd9eab7..c6efa41 100644
--- a/packages/Tethering/jarjar-rules.txt
+++ b/packages/Tethering/jarjar-rules.txt
@@ -11,5 +11,8 @@
rule com.android.internal.util.Preconditions* com.android.networkstack.tethering.util.Preconditions@1
rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
+rule com.android.internal.util.TrafficStatsConstants* com.android.networkstack.tethering.util.TrafficStatsConstants@1
rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
+
+rule android.net.shared.Inet4AddressUtils* com.android.networkstack.tethering.shared.Inet4AddressUtils@1
diff --git a/packages/Tethering/jni/android_net_util_TetheringUtils.cpp b/packages/Tethering/jni/android_net_util_TetheringUtils.cpp
new file mode 100644
index 0000000..1cf8f98
--- /dev/null
+++ b/packages/Tethering/jni/android_net_util_TetheringUtils.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <error.h>
+#include <hidl/HidlSupport.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netlink.h>
+#include <net/if.h>
+#include <netinet/icmp6.h>
+#include <sys/socket.h>
+#include <android-base/unique_fd.h>
+#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
+
+#define LOG_TAG "TetheringUtils"
+#include <utils/Log.h>
+
+namespace android {
+
+using hardware::hidl_handle;
+using hardware::hidl_string;
+using hardware::tetheroffload::config::V1_0::IOffloadConfig;
+
+namespace {
+
+inline const sockaddr * asSockaddr(const sockaddr_nl *nladdr) {
+ return reinterpret_cast<const sockaddr *>(nladdr);
+}
+
+int conntrackSocket(unsigned groups) {
+ base::unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_NETFILTER));
+ if (s.get() < 0) return -errno;
+
+ const struct sockaddr_nl bind_addr = {
+ .nl_family = AF_NETLINK,
+ .nl_pad = 0,
+ .nl_pid = 0,
+ .nl_groups = groups,
+ };
+ if (bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) != 0) {
+ return -errno;
+ }
+
+ const struct sockaddr_nl kernel_addr = {
+ .nl_family = AF_NETLINK,
+ .nl_pad = 0,
+ .nl_pid = 0,
+ .nl_groups = groups,
+ };
+ if (connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
+ return -errno;
+ }
+
+ return s.release();
+}
+
+// Return a hidl_handle that owns the file descriptor owned by fd, and will
+// auto-close it (otherwise there would be double-close problems).
+//
+// Rely upon the compiler to eliminate the constexprs used for clarity.
+hidl_handle handleFromFileDescriptor(base::unique_fd fd) {
+ hidl_handle h;
+
+ static constexpr int kNumFds = 1;
+ static constexpr int kNumInts = 0;
+ native_handle_t *nh = native_handle_create(kNumFds, kNumInts);
+ nh->data[0] = fd.release();
+
+ static constexpr bool kTakeOwnership = true;
+ h.setTo(nh, kTakeOwnership);
+
+ return h;
+}
+
+} // namespace
+
+static jboolean android_net_util_configOffload(
+ JNIEnv* /* env */) {
+ sp<IOffloadConfig> configInterface = IOffloadConfig::getService();
+ if (configInterface.get() == nullptr) {
+ ALOGD("Could not find IOffloadConfig service.");
+ return false;
+ }
+
+ // Per the IConfigOffload definition:
+ //
+ // fd1 A file descriptor bound to the following netlink groups
+ // (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY).
+ //
+ // fd2 A file descriptor bound to the following netlink groups
+ // (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
+ base::unique_fd
+ fd1(conntrackSocket(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY)),
+ fd2(conntrackSocket(NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY));
+ if (fd1.get() < 0 || fd2.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ return false;
+ }
+
+ hidl_handle h1(handleFromFileDescriptor(std::move(fd1))),
+ h2(handleFromFileDescriptor(std::move(fd2)));
+
+ bool rval(false);
+ hidl_string msg;
+ const auto status = configInterface->setHandles(h1, h2,
+ [&rval, &msg](bool success, const hidl_string& errMsg) {
+ rval = success;
+ msg = errMsg;
+ });
+ if (!status.isOk() || !rval) {
+ ALOGE("IOffloadConfig::setHandles() error: '%s' / '%s'",
+ status.description().c_str(), msg.c_str());
+ // If status is somehow not ok, make sure rval captures this too.
+ rval = false;
+ }
+
+ return rval;
+}
+
+static void android_net_util_setupRaSocket(JNIEnv *env, jobject clazz, jobject javaFd,
+ jint ifIndex)
+{
+ static const int kLinkLocalHopLimit = 255;
+
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+
+ // Set an ICMPv6 filter that only passes Router Solicitations.
+ struct icmp6_filter rs_only;
+ ICMP6_FILTER_SETBLOCKALL(&rs_only);
+ ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &rs_only);
+ socklen_t len = sizeof(rs_only);
+ if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &rs_only, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(ICMP6_FILTER): %s", strerror(errno));
+ return;
+ }
+
+ // Most/all of the rest of these options can be set via Java code, but
+ // because we're here on account of setting an icmp6_filter go ahead
+ // and do it all natively for now.
+
+ // Set the multicast hoplimit to 255 (link-local only).
+ int hops = kLinkLocalHopLimit;
+ len = sizeof(hops);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno));
+ return;
+ }
+
+ // Set the unicast hoplimit to 255 (link-local only).
+ hops = kLinkLocalHopLimit;
+ len = sizeof(hops);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno));
+ return;
+ }
+
+ // Explicitly disable multicast loopback.
+ int off = 0;
+ len = sizeof(off);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_MULTICAST_LOOP): %s", strerror(errno));
+ return;
+ }
+
+ // Specify the IPv6 interface to use for outbound multicast.
+ len = sizeof(ifIndex);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_MULTICAST_IF): %s", strerror(errno));
+ return;
+ }
+
+ // Additional options to be considered:
+ // - IPV6_TCLASS
+ // - IPV6_RECVPKTINFO
+ // - IPV6_RECVHOPLIMIT
+
+ // Bind to [::].
+ const struct sockaddr_in6 sin6 = {
+ .sin6_family = AF_INET6,
+ .sin6_port = 0,
+ .sin6_flowinfo = 0,
+ .sin6_addr = IN6ADDR_ANY_INIT,
+ .sin6_scope_id = 0,
+ };
+ auto sa = reinterpret_cast<const struct sockaddr *>(&sin6);
+ len = sizeof(sin6);
+ if (bind(fd, sa, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "bind(IN6ADDR_ANY): %s", strerror(errno));
+ return;
+ }
+
+ // Join the all-routers multicast group, ff02::2%index.
+ struct ipv6_mreq all_rtrs = {
+ .ipv6mr_multiaddr = {{{0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2}}},
+ .ipv6mr_interface = ifIndex,
+ };
+ len = sizeof(all_rtrs);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &all_rtrs, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_JOIN_GROUP): %s", strerror(errno));
+ return;
+ }
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "configOffload", "()Z", (void*) android_net_util_configOffload },
+ { "setupRaSocket", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_util_setupRaSocket },
+};
+
+int register_android_net_util_TetheringUtils(JNIEnv* env) {
+ return jniRegisterNativeMethods(env,
+ "android/net/util/TetheringUtils",
+ gMethods, NELEM(gMethods));
+}
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+ JNIEnv *env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ ALOGE("ERROR: GetEnv failed");
+ return JNI_ERR;
+ }
+
+ if (register_android_net_util_TetheringUtils(env) < 0) {
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_1_6;
+}
+
+}; // namespace android
diff --git a/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
deleted file mode 100644
index 663154a..0000000
--- a/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
+++ /dev/null
@@ -1,162 +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.
- */
-
-#include <errno.h>
-#include <error.h>
-#include <hidl/HidlSupport.h>
-#include <jni.h>
-#include <nativehelper/JNIHelp.h>
-#include <linux/netfilter/nfnetlink.h>
-#include <linux/netlink.h>
-#include <sys/socket.h>
-#include <android-base/unique_fd.h>
-#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
-
-#define LOG_TAG "OffloadHardwareInterface"
-#include <utils/Log.h>
-
-namespace android {
-
-using hardware::hidl_handle;
-using hardware::hidl_string;
-using hardware::tetheroffload::config::V1_0::IOffloadConfig;
-
-namespace {
-
-inline const sockaddr * asSockaddr(const sockaddr_nl *nladdr) {
- return reinterpret_cast<const sockaddr *>(nladdr);
-}
-
-int conntrackSocket(unsigned groups) {
- base::unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_NETFILTER));
- if (s.get() < 0) return -errno;
-
- const struct sockaddr_nl bind_addr = {
- .nl_family = AF_NETLINK,
- .nl_pad = 0,
- .nl_pid = 0,
- .nl_groups = groups,
- };
- if (bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) != 0) {
- return -errno;
- }
-
- const struct sockaddr_nl kernel_addr = {
- .nl_family = AF_NETLINK,
- .nl_pad = 0,
- .nl_pid = 0,
- .nl_groups = groups,
- };
- if (connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
- return -errno;
- }
-
- return s.release();
-}
-
-// Return a hidl_handle that owns the file descriptor owned by fd, and will
-// auto-close it (otherwise there would be double-close problems).
-//
-// Rely upon the compiler to eliminate the constexprs used for clarity.
-hidl_handle handleFromFileDescriptor(base::unique_fd fd) {
- hidl_handle h;
-
- static constexpr int kNumFds = 1;
- static constexpr int kNumInts = 0;
- native_handle_t *nh = native_handle_create(kNumFds, kNumInts);
- nh->data[0] = fd.release();
-
- static constexpr bool kTakeOwnership = true;
- h.setTo(nh, kTakeOwnership);
-
- return h;
-}
-
-} // namespace
-
-static jboolean android_server_connectivity_tethering_OffloadHardwareInterface_configOffload(
- JNIEnv* /* env */) {
- sp<IOffloadConfig> configInterface = IOffloadConfig::getService();
- if (configInterface.get() == nullptr) {
- ALOGD("Could not find IOffloadConfig service.");
- return false;
- }
-
- // Per the IConfigOffload definition:
- //
- // fd1 A file descriptor bound to the following netlink groups
- // (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY).
- //
- // fd2 A file descriptor bound to the following netlink groups
- // (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
- base::unique_fd
- fd1(conntrackSocket(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY)),
- fd2(conntrackSocket(NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY));
- if (fd1.get() < 0 || fd2.get() < 0) {
- ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
- return false;
- }
-
- hidl_handle h1(handleFromFileDescriptor(std::move(fd1))),
- h2(handleFromFileDescriptor(std::move(fd2)));
-
- bool rval(false);
- hidl_string msg;
- const auto status = configInterface->setHandles(h1, h2,
- [&rval, &msg](bool success, const hidl_string& errMsg) {
- rval = success;
- msg = errMsg;
- });
- if (!status.isOk() || !rval) {
- ALOGE("IOffloadConfig::setHandles() error: '%s' / '%s'",
- status.description().c_str(), msg.c_str());
- // If status is somehow not ok, make sure rval captures this too.
- rval = false;
- }
-
- return rval;
-}
-
-/*
- * JNI registration.
- */
-static const JNINativeMethod gMethods[] = {
- /* name, signature, funcPtr */
- { "configOffload", "()Z",
- (void*) android_server_connectivity_tethering_OffloadHardwareInterface_configOffload },
-};
-
-int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv* env) {
- return jniRegisterNativeMethods(env,
- "com/android/server/connectivity/tethering/OffloadHardwareInterface",
- gMethods, NELEM(gMethods));
-}
-
-extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
- JNIEnv *env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- ALOGE("ERROR: GetEnv failed");
- return JNI_ERR;
- }
-
- if (register_android_server_connectivity_tethering_OffloadHardwareInterface(env) < 0) {
- return JNI_ERR;
- }
-
- return JNI_VERSION_1_6;
-}
-
-}; // namespace android
diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml
index 37e679d..6fa1f77 100644
--- a/packages/Tethering/res/values/config.xml
+++ b/packages/Tethering/res/values/config.xml
@@ -1,7 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
<resources>
<!--
OEMs that wish to change the below settings must do so via a runtime resource overlay package
and *NOT* by changing this file. This file is part of the tethering mainline module.
+ TODO: define two resources for each config item: a default_* resource and a config_* resource,
+ config_* is empty by default but may be overridden by RROs.
-->
+ <!-- List of regexpressions describing the interface (if any) that represent tetherable
+ USB interfaces. If the device doesn't want to support tethering over USB this should
+ be empty. An example would be "usb.*" -->
+ <string-array translatable="false" name="config_tether_usb_regexs">
+ <item>"usb\\d"</item>
+ <item>"rndis\\d"</item>
+ </string-array>
+
+ <!-- List of regexpressions describing the interface (if any) that represent tetherable
+ Wifi interfaces. If the device doesn't want to support tethering over Wifi this
+ should be empty. An example would be "softap.*" -->
+ <string-array translatable="false" name="config_tether_wifi_regexs">
+ <item>"wlan\\d"</item>
+ <item>"softap\\d"</item>
+ </string-array>
+
+ <!-- List of regexpressions describing the interface (if any) that represent tetherable
+ Wifi P2P interfaces. If the device doesn't want to support tethering over Wifi P2p this
+ should be empty. An example would be "p2p-p2p.*" -->
+ <string-array translatable="false" name="config_tether_wifi_p2p_regexs">
+ </string-array>
+
+ <!-- List of regexpressions describing the interface (if any) that represent tetherable
+ bluetooth interfaces. If the device doesn't want to support tethering over bluetooth this
+ should be empty. -->
+ <string-array translatable="false" name="config_tether_bluetooth_regexs">
+ <item>"bt-pan"</item>
+ </string-array>
+
+ <!-- Use the old dnsmasq DHCP server for tethering instead of the framework implementation. -->
+ <bool translatable="false" name="config_tether_enable_legacy_dhcp_server">false</bool>
+
+ <!-- Dhcp range (min, max) to use for tethering purposes -->
+ <string-array translatable="false" name="config_tether_dhcp_range">
+ </string-array>
+
+ <!-- Array of ConnectivityManager.TYPE_{BLUETOOTH, ETHERNET, MOBILE, MOBILE_DUN, MOBILE_HIPRI,
+ WIFI} values allowable for tethering.
+
+ Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or
+ [1,7,0] for TYPE_WIFI, TYPE_BLUETOOTH, and TYPE_MOBILE.
+
+ This list is also modified by code within the framework, including:
+
+ - TYPE_ETHERNET (9) is prepended to this list, and
+
+ - the return value of TelephonyManager.isTetheringApnRequired()
+ determines how the array is further modified:
+
+ * TRUE (DUN REQUIRED).
+ TYPE_MOBILE is removed (if present).
+ TYPE_MOBILE_HIPRI is removed (if present).
+ TYPE_MOBILE_DUN is appended (if not already present).
+
+ * FALSE (DUN NOT REQUIRED).
+ TYPE_MOBILE_DUN is removed (if present).
+ If both of TYPE_MOBILE{,_HIPRI} are not present:
+ TYPE_MOBILE is appended.
+ TYPE_MOBILE_HIPRI is appended.
+
+ For other changes applied to this list, now and in the future, see
+ com.android.server.connectivity.tethering.TetheringConfiguration.
+
+ Note also: the order of this is important. The first upstream type
+ for which a satisfying network exists is used.
+ -->
+ <integer-array translatable="false" name="config_tether_upstream_types">
+ </integer-array>
+
+ <!-- When true, the tethering upstream network follows the current default
+ Internet network (except when the current default network is mobile,
+ in which case a DUN network will be used if required).
+
+ When true, overrides the config_tether_upstream_types setting above.
+ -->
+ <bool translatable="false" name="config_tether_upstream_automatic">true</bool>
+
+
+ <!-- If the mobile hotspot feature requires provisioning, a package name and class name
+ can be provided to launch a supported application that provisions the devices.
+ EntitlementManager will send an intent to Settings with the specified package name and
+ class name in extras to launch provision app.
+ TODO: note what extras here.
+
+ See EntitlementManager#runUiTetherProvisioning and
+ packages/apps/Settings/src/com/android/settings/network/TetherProvisioningActivity.java
+ for more details.
+
+ For ui-less/periodic recheck support see config_mobile_hotspot_provision_app_no_ui
+ -->
+ <!-- The first element is the package name and the second element is the class name
+ of the provisioning app -->
+ <string-array translatable="false" name="config_mobile_hotspot_provision_app">
+ <!--
+ <item>com.example.provisioning</item>
+ <item>com.example.provisioning.Activity</item>
+ -->
+ </string-array>
+
+ <!-- If the mobile hotspot feature requires provisioning, an action can be provided
+ that will be broadcast in non-ui cases for checking the provisioning status.
+ EntitlementManager will pass the specified name to Settings and Settings would
+ launch provisioning app by sending an intent with the package name.
+
+ A second broadcast, action defined by config_mobile_hotspot_provision_response,
+ will be sent back to notify if provisioning succeeded or not. The response will
+ match that of the activity in config_mobile_hotspot_provision_app, but instead
+ contained within the int extra "EntitlementResult".
+ TODO: provide the system api for "EntitlementResult" extra and note it here.
+
+ See EntitlementManager#runSilentTetherProvisioning and
+ packages/apps/Settings/src/com/android/settings/wifi/tether/TetherService.java for more
+ details.
+ -->
+ <string translatable="false" name="config_mobile_hotspot_provision_app_no_ui"></string>
+
+ <!-- Sent in response to a provisioning check. The caller must hold the
+ permission android.permission.TETHER_PRIVILEGED for Settings to
+ receive this response.
+
+ See config_mobile_hotspot_provision_response
+ -->
+ <string translatable="false" name="config_mobile_hotspot_provision_response"></string>
+
+ <!-- Number of hours between each background provisioning call -->
+ <integer translatable="false" name="config_mobile_hotspot_provision_check_period">24</integer>
+
+ <!-- ComponentName of the service used to run no ui tether provisioning. -->
+ <string translatable="false" name="config_wifi_tether_enable">com.android.settings/.wifi.tether.TetherService</string>
</resources>
diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml
new file mode 100644
index 0000000..e089d9d
--- /dev/null
+++ b/packages/Tethering/res/values/overlayable.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <overlayable name="TetheringConfig">
+ <policy type="product|system|vendor">
+ <item type="array" name="config_tether_usb_regexs"/>
+ <item type="array" name="config_tether_wifi_regexs"/>
+ <item type="array" name="config_tether_wifi_p2p_regexs"/>
+ <item type="array" name="config_tether_bluetooth_regexs"/>
+ <item type="array" name="config_tether_dhcp_range"/>
+ <item type="bool" name="config_tether_enable_legacy_dhcp_server"/>
+ <item type="array" name="config_tether_upstream_types"/>
+ <item type="bool" name="config_tether_upstream_automatic"/>
+ <!-- Configuration values for tethering entitlement check -->
+ <item type="array" name="config_mobile_hotspot_provision_app"/>
+ <item type="string" name="config_mobile_hotspot_provision_app_no_ui"/>
+ <item type="string" name="config_mobile_hotspot_provision_response"/>
+ <item type="integer" name="config_mobile_hotspot_provision_check_period"/>
+ <item type="string" name="config_wifi_tether_enable"/>
+ </policy>
+ </overlayable>
+</resources>
diff --git a/packages/Tethering/res/values/strings.xml b/packages/Tethering/res/values/strings.xml
index ca866a9..792bce9 100644
--- a/packages/Tethering/res/values/strings.xml
+++ b/packages/Tethering/res/values/strings.xml
@@ -1,4 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
<resources>
<!-- Shown when the device is tethered -->
<!-- Strings for tethered notification title [CHAR LIMIT=200] -->
@@ -9,8 +23,11 @@
<!-- This notification is shown when tethering has been disabled on a user's device.
The device is managed by the user's employer. Tethering can't be turned on unless the
IT administrator allows it. The noun "admin" is another reference for "IT administrator." -->
- <!-- Strings for tether disabling notification title [CHAR LIMIT=200] -->
+ <!-- Strings for tether disabling notification title [CHAR LIMIT=200] -->
<string name="disable_tether_notification_title">Tethering is disabled</string>
- <!-- Strings for tether disabling notification message [CHAR LIMIT=200] -->
+ <!-- Strings for tether disabling notification message [CHAR LIMIT=200] -->
<string name="disable_tether_notification_message">Contact your admin for details</string>
+
+ <!-- Strings for tether notification channel name [CHAR LIMIT=200] -->
+ <string name="notification_channel_tethering_status">Hotspot & tethering status</string>
</resources>
\ No newline at end of file
diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
index 1fe2328..d6bc063 100644
--- a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
+++ b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
@@ -20,11 +20,11 @@
import android.annotation.NonNull;
import android.net.LinkAddress;
-
-import com.google.android.collect.Sets;
+import android.util.ArraySet;
import java.net.Inet4Address;
import java.util.Collection;
+import java.util.Collections;
import java.util.Set;
/**
@@ -68,7 +68,7 @@
* but it must always be set explicitly.
*/
public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Inet4Address... defaultRouters) {
- return setDefaultRouters(Sets.newArraySet(defaultRouters));
+ return setDefaultRouters(newArraySet(defaultRouters));
}
/**
@@ -96,7 +96,7 @@
* <p>This may be an empty list of servers, but it must always be set explicitly.
*/
public DhcpServingParamsParcelExt setDnsServers(@NonNull Inet4Address... dnsServers) {
- return setDnsServers(Sets.newArraySet(dnsServers));
+ return setDnsServers(newArraySet(dnsServers));
}
/**
@@ -126,7 +126,7 @@
* and do not need to be set here.
*/
public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Inet4Address... excludedAddrs) {
- return setExcludedAddrs(Sets.newArraySet(excludedAddrs));
+ return setExcludedAddrs(newArraySet(excludedAddrs));
}
/**
@@ -169,4 +169,10 @@
}
return res;
}
+
+ private static ArraySet<Inet4Address> newArraySet(Inet4Address... addrs) {
+ ArraySet<Inet4Address> addrSet = new ArraySet<>(addrs.length);
+ Collections.addAll(addrSet, addrs);
+ return addrSet;
+ }
}
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 8fde520..0491ad7 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -17,40 +17,38 @@
package android.net.ip;
import static android.net.InetAddresses.parseNumericAddress;
+import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.util.NetworkConstants.FF;
import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
import static android.net.util.NetworkConstants.asByte;
+import static android.net.util.TetheringMessageBase.BASE_IPSERVER;
-import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.INetworkStackStatusCallback;
-import android.net.INetworkStatsService;
-import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.RouteInfo;
+import android.net.TetheringManager;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.DhcpServingParamsParcelExt;
import android.net.dhcp.IDhcpServer;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
+import android.net.shared.NetdUtils;
+import android.net.shared.RouteUtils;
import android.net.util.InterfaceParams;
import android.net.util.InterfaceSet;
-import android.net.util.NetdService;
import android.net.util.SharedLog;
-import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.util.Log;
-import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.util.MessageUtils;
-import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -119,7 +117,7 @@
*
* @param who the calling instance of IpServer
* @param state one of STATE_*
- * @param lastError one of ConnectivityManager.TETHER_ERROR_*
+ * @param lastError one of TetheringManager.TETHER_ERROR_*
*/
public void updateInterfaceState(IpServer who, int state, int lastError) { }
@@ -144,36 +142,31 @@
return InterfaceParams.getByName(ifName);
}
- public INetd getNetdService() {
- return NetdService.getInstance();
- }
-
/** Create a DhcpServer instance to be used by IpServer. */
public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
DhcpServerCallbacks cb);
}
- private static final int BASE_IFACE = Protocol.BASE_TETHERING + 100;
// request from the user that it wants to tether
- public static final int CMD_TETHER_REQUESTED = BASE_IFACE + 2;
+ public static final int CMD_TETHER_REQUESTED = BASE_IPSERVER + 1;
// request from the user that it wants to untether
- public static final int CMD_TETHER_UNREQUESTED = BASE_IFACE + 3;
+ public static final int CMD_TETHER_UNREQUESTED = BASE_IPSERVER + 2;
// notification that this interface is down
- public static final int CMD_INTERFACE_DOWN = BASE_IFACE + 4;
+ public static final int CMD_INTERFACE_DOWN = BASE_IPSERVER + 3;
// notification from the master SM that it had trouble enabling IP Forwarding
- public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IFACE + 7;
+ public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IPSERVER + 4;
// notification from the master SM that it had trouble disabling IP Forwarding
- public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IFACE + 8;
+ public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IPSERVER + 5;
// notification from the master SM that it had trouble starting tethering
- public static final int CMD_START_TETHERING_ERROR = BASE_IFACE + 9;
+ public static final int CMD_START_TETHERING_ERROR = BASE_IPSERVER + 6;
// notification from the master SM that it had trouble stopping tethering
- public static final int CMD_STOP_TETHERING_ERROR = BASE_IFACE + 10;
+ public static final int CMD_STOP_TETHERING_ERROR = BASE_IPSERVER + 7;
// notification from the master SM that it had trouble setting the DNS forwarders
- public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IFACE + 11;
+ public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IPSERVER + 8;
// the upstream connection has changed
- public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IFACE + 12;
+ public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IPSERVER + 9;
// new IPv6 tethering parameters need to be processed
- public static final int CMD_IPV6_TETHER_UPDATE = BASE_IFACE + 13;
+ public static final int CMD_IPV6_TETHER_UPDATE = BASE_IPSERVER + 10;
private final State mInitialState;
private final State mLocalHotspotState;
@@ -181,9 +174,7 @@
private final State mUnavailableState;
private final SharedLog mLog;
- private final INetworkManagementService mNMService;
private final INetd mNetd;
- private final INetworkStatsService mStatsService;
private final Callback mCallback;
private final InterfaceController mInterfaceCtrl;
@@ -211,16 +202,14 @@
private int mDhcpServerStartIndex = 0;
private IDhcpServer mDhcpServer;
private RaParams mLastRaParams;
+ private LinkAddress mIpv4Address;
public IpServer(
String ifaceName, Looper looper, int interfaceType, SharedLog log,
- INetworkManagementService nMService, INetworkStatsService statsService,
- Callback callback, boolean usingLegacyDhcp, Dependencies deps) {
+ INetd netd, Callback callback, boolean usingLegacyDhcp, Dependencies deps) {
super(ifaceName, looper);
mLog = log.forSubComponent(ifaceName);
- mNMService = nMService;
- mNetd = deps.getNetdService();
- mStatsService = statsService;
+ mNetd = netd;
mCallback = callback;
mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog);
mIfaceName = ifaceName;
@@ -229,7 +218,7 @@
mUsingLegacyDhcp = usingLegacyDhcp;
mDeps = deps;
resetLinkProperties();
- mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
mServingMode = STATE_AVAILABLE;
mInitialState = new InitialState();
@@ -250,7 +239,7 @@
}
/**
- * Tethering downstream type. It would be one of ConnectivityManager#TETHERING_*.
+ * Tethering downstream type. It would be one of TetheringManager#TETHERING_*.
*/
public int interfaceType() {
return mInterfaceType;
@@ -348,13 +337,13 @@
}
});
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw new IllegalStateException(e);
}
});
}
private void handleError() {
- mLastError = ConnectivityManager.TETHER_ERROR_DHCPSERVER_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
transitionTo(mInitialState);
}
}
@@ -389,14 +378,15 @@
public void callback(int statusCode) {
if (statusCode != STATUS_SUCCESS) {
mLog.e("Error stopping DHCP server: " + statusCode);
- mLastError = ConnectivityManager.TETHER_ERROR_DHCPSERVER_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
// Not much more we can do here
}
}
});
mDhcpServer = null;
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ mLog.e("Error stopping DHCP", e);
+ // Not much more we can do here
}
}
}
@@ -415,83 +405,70 @@
// NOTE: All of configureIPv4() will be refactored out of existence
// into calls to InterfaceController, shared with startIPv4().
mInterfaceCtrl.clearIPv4Address();
+ mIpv4Address = null;
}
- // TODO: Refactor this in terms of calls to InterfaceController.
private boolean configureIPv4(boolean enabled) {
if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");
// TODO: Replace this hard-coded information with dynamically selected
// config passed down to us by a higher layer IP-coordinating element.
- String ipAsString = null;
+ final Inet4Address srvAddr;
int prefixLen = 0;
- if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
- ipAsString = USB_NEAR_IFACE_ADDR;
- prefixLen = USB_PREFIX_LENGTH;
- } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
- ipAsString = getRandomWifiIPv4Address();
- prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
- } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) {
- ipAsString = WIFI_P2P_IFACE_ADDR;
- prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
- } else {
- // BT configures the interface elsewhere: only start DHCP.
- final Inet4Address srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
- return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
+ try {
+ if (mInterfaceType == TetheringManager.TETHERING_USB) {
+ srvAddr = (Inet4Address) parseNumericAddress(USB_NEAR_IFACE_ADDR);
+ prefixLen = USB_PREFIX_LENGTH;
+ } else if (mInterfaceType == TetheringManager.TETHERING_WIFI) {
+ srvAddr = (Inet4Address) parseNumericAddress(getRandomWifiIPv4Address());
+ prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
+ } else if (mInterfaceType == TetheringManager.TETHERING_WIFI_P2P) {
+ srvAddr = (Inet4Address) parseNumericAddress(WIFI_P2P_IFACE_ADDR);
+ prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
+ } else {
+ // BT configures the interface elsewhere: only start DHCP.
+ // TODO: make all tethering types behave the same way, and delete the bluetooth
+ // code that calls into NetworkManagementService directly.
+ srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
+ mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
+ return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
+ }
+ mIpv4Address = new LinkAddress(srvAddr, prefixLen);
+ } catch (IllegalArgumentException e) {
+ mLog.e("Error selecting ipv4 address", e);
+ if (!enabled) stopDhcp();
+ return false;
}
- final LinkAddress linkAddr;
- try {
- final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName);
- if (ifcg == null) {
- mLog.e("Received null interface config");
- return false;
- }
+ final Boolean setIfaceUp;
+ if (mInterfaceType == TetheringManager.TETHERING_WIFI
+ || mInterfaceType == TetheringManager.TETHERING_WIFI_P2P) {
+ // The WiFi stack has ownership of the interface up/down state.
+ // It is unclear whether the Bluetooth or USB stacks will manage their own
+ // state.
+ setIfaceUp = null;
+ } else {
+ setIfaceUp = enabled;
+ }
+ if (!mInterfaceCtrl.setInterfaceConfiguration(mIpv4Address, setIfaceUp)) {
+ mLog.e("Error configuring interface");
+ if (!enabled) stopDhcp();
+ return false;
+ }
- InetAddress addr = parseNumericAddress(ipAsString);
- linkAddr = new LinkAddress(addr, prefixLen);
- ifcg.setLinkAddress(linkAddr);
- if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
- // The WiFi stack has ownership of the interface up/down state.
- // It is unclear whether the Bluetooth or USB stacks will manage their own
- // state.
- ifcg.ignoreInterfaceUpDownStatus();
- } else {
- if (enabled) {
- ifcg.setInterfaceUp();
- } else {
- ifcg.setInterfaceDown();
- }
- }
- ifcg.clearFlag("running");
-
- // TODO: this may throw if the interface is already gone. Do proper handling and
- // simplify the DHCP server start/stop.
- mNMService.setInterfaceConfig(mIfaceName, ifcg);
-
- if (!configureDhcp(enabled, (Inet4Address) addr, prefixLen)) {
- return false;
- }
- } catch (Exception e) {
- mLog.e("Error configuring interface " + e);
- if (!enabled) {
- try {
- // Calling stopDhcp several times is fine
- stopDhcp();
- } catch (Exception dhcpError) {
- mLog.e("Error stopping DHCP", dhcpError);
- }
- }
+ if (!configureDhcp(enabled, srvAddr, prefixLen)) {
return false;
}
// Directly-connected route.
- final RouteInfo route = new RouteInfo(linkAddr);
+ final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
+ mIpv4Address.getPrefixLength());
+ final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST);
if (enabled) {
- mLinkProperties.addLinkAddress(linkAddr);
+ mLinkProperties.addLinkAddress(mIpv4Address);
mLinkProperties.addRoute(route);
} else {
- mLinkProperties.removeLinkAddress(linkAddr);
+ mLinkProperties.removeLinkAddress(mIpv4Address);
mLinkProperties.removeRoute(route);
}
return true;
@@ -583,14 +560,12 @@
if (!deprecatedPrefixes.isEmpty()) {
final ArrayList<RouteInfo> toBeRemoved =
getLocalRoutesFor(mIfaceName, deprecatedPrefixes);
- try {
- final int removalFailures = mNMService.removeRoutesFromLocalNetwork(toBeRemoved);
- if (removalFailures > 0) {
- mLog.e(String.format("Failed to remove %d IPv6 routes from local table.",
- removalFailures));
- }
- } catch (RemoteException e) {
- mLog.e("Failed to remove IPv6 routes from local table: " + e);
+ // Remove routes from local network.
+ final int removalFailures = RouteUtils.removeRoutesFromLocalNetwork(
+ mNetd, toBeRemoved);
+ if (removalFailures > 0) {
+ mLog.e(String.format("Failed to remove %d IPv6 routes from local table.",
+ removalFailures));
}
for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route);
@@ -607,13 +582,18 @@
final ArrayList<RouteInfo> toBeAdded =
getLocalRoutesFor(mIfaceName, addedPrefixes);
try {
- // It's safe to call addInterfaceToLocalNetwork() even if
- // the interface is already in the local_network. Note also
- // that adding routes that already exist does not cause an
- // error (EEXIST is silently ignored).
- mNMService.addInterfaceToLocalNetwork(mIfaceName, toBeAdded);
- } catch (Exception e) {
- mLog.e("Failed to add IPv6 routes to local table: " + e);
+ // It's safe to call networkAddInterface() even if
+ // the interface is already in the local_network.
+ mNetd.networkAddInterface(INetd.LOCAL_NET_ID, mIfaceName);
+ try {
+ // Add routes from local network. Note that adding routes that
+ // already exist does not cause an error (EEXIST is silently ignored).
+ RouteUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded);
+ } catch (IllegalStateException e) {
+ mLog.e("Failed to add IPv6 routes to local table: " + e);
+ }
+ } catch (ServiceSpecificException | RemoteException e) {
+ mLog.e("Failed to add " + mIfaceName + " to local table: ", e);
}
for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route);
@@ -727,7 +707,7 @@
logMessage(this, message.what);
switch (message.what) {
case CMD_TETHER_REQUESTED:
- mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
switch (message.arg1) {
case STATE_LOCAL_ONLY:
transitionTo(mLocalHotspotState);
@@ -756,15 +736,17 @@
@Override
public void enter() {
if (!startIPv4()) {
- mLastError = ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
return;
}
try {
- mNMService.tetherInterface(mIfaceName);
- } catch (Exception e) {
+ final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
+ mIpv4Address.getPrefixLength());
+ NetdUtils.tetherInterface(mNetd, mIfaceName, ipv4Prefix);
+ } catch (RemoteException | ServiceSpecificException e) {
mLog.e("Error Tethering: " + e);
- mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
return;
}
@@ -783,9 +765,9 @@
stopIPv6();
try {
- mNMService.untetherInterface(mIfaceName);
- } catch (Exception e) {
- mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
+ NetdUtils.untetherInterface(mNetd, mIfaceName);
+ } catch (RemoteException | ServiceSpecificException e) {
+ mLastError = TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
mLog.e("Failed to untether interface: " + e);
}
@@ -815,7 +797,7 @@
case CMD_START_TETHERING_ERROR:
case CMD_STOP_TETHERING_ERROR:
case CMD_SET_DNS_FORWARDERS_ERROR:
- mLastError = ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_MASTER_ERROR;
transitionTo(mInitialState);
break;
default:
@@ -834,7 +816,7 @@
@Override
public void enter() {
super.enter();
- if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+ if (mLastError != TetheringManager.TETHER_ERROR_NO_ERROR) {
transitionTo(mInitialState);
}
@@ -870,7 +852,7 @@
@Override
public void enter() {
super.enter();
- if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+ if (mLastError != TetheringManager.TETHER_ERROR_NO_ERROR) {
transitionTo(mInitialState);
}
@@ -897,20 +879,14 @@
// to remove their rules, which generates errors.
// Just do the best we can.
try {
- // About to tear down NAT; gather remaining statistics.
- mStatsService.forceUpdate();
- } catch (Exception e) {
- if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
+ mNetd.ipfwdRemoveInterfaceForward(mIfaceName, upstreamIface);
+ } catch (RemoteException | ServiceSpecificException e) {
+ mLog.e("Exception in ipfwdRemoveInterfaceForward: " + e.toString());
}
try {
- mNMService.stopInterfaceForwarding(mIfaceName, upstreamIface);
- } catch (Exception e) {
- if (VDBG) Log.e(TAG, "Exception in removeInterfaceForward: " + e.toString());
- }
- try {
- mNMService.disableNat(mIfaceName, upstreamIface);
- } catch (Exception e) {
- if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
+ mNetd.tetherRemoveForward(mIfaceName, upstreamIface);
+ } catch (RemoteException | ServiceSpecificException e) {
+ mLog.e("Exception in disableNat: " + e.toString());
}
}
@@ -946,12 +922,12 @@
for (String ifname : added) {
try {
- mNMService.enableNat(mIfaceName, ifname);
- mNMService.startInterfaceForwarding(mIfaceName, ifname);
- } catch (Exception e) {
- mLog.e("Exception enabling NAT: " + e);
+ mNetd.tetherAddForward(mIfaceName, ifname);
+ mNetd.ipfwdAddInterfaceForward(mIfaceName, ifname);
+ } catch (RemoteException | ServiceSpecificException e) {
+ mLog.e("Exception enabling NAT: " + e.toString());
cleanupUpstream();
- mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_ENABLE_NAT_ERROR;
transitionTo(mInitialState);
return true;
}
@@ -996,7 +972,7 @@
class UnavailableState extends State {
@Override
public void enter() {
- mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
sendInterfaceState(STATE_UNAVAILABLE);
}
}
@@ -1007,7 +983,7 @@
String ifname, HashSet<IpPrefix> prefixes) {
final ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>();
for (IpPrefix ipp : prefixes) {
- localRoutes.add(new RouteInfo(ipp, null, ifname));
+ localRoutes.add(new RouteInfo(ipp, null, ifname, RTN_UNICAST));
}
return localRoutes;
}
@@ -1019,7 +995,7 @@
try {
return Inet6Address.getByAddress(null, dnsBytes, 0);
} catch (UnknownHostException e) {
- Slog.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix);
+ Log.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix);
return null;
}
}
diff --git a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
index 4147413..6f017dc 100644
--- a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
+++ b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
@@ -22,14 +22,14 @@
import static android.system.OsConstants.IPPROTO_ICMPV6;
import static android.system.OsConstants.SOCK_RAW;
import static android.system.OsConstants.SOL_SOCKET;
-import static android.system.OsConstants.SO_BINDTODEVICE;
import static android.system.OsConstants.SO_SNDTIMEO;
import android.net.IpPrefix;
import android.net.LinkAddress;
-import android.net.NetworkUtils;
import android.net.TrafficStats;
import android.net.util.InterfaceParams;
+import android.net.util.SocketUtils;
+import android.net.util.TetheringUtils;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructTimeval;
@@ -38,8 +38,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.TrafficStatsConstants;
-import libcore.io.IoBridge;
-
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.Inet6Address;
@@ -611,9 +609,8 @@
// Setting SNDTIMEO is purely for defensive purposes.
Os.setsockoptTimeval(
mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(send_timout_ms));
- Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mInterface.name);
- NetworkUtils.protectFromVpn(mSocket);
- NetworkUtils.setupRaSocket(mSocket, mInterface.index);
+ SocketUtils.bindSocketToInterface(mSocket, mInterface.name);
+ TetheringUtils.setupRaSocket(mSocket, mInterface.index);
} catch (ErrnoException | IOException e) {
Log.e(TAG, "Failed to create RA daemon socket: " + e);
return false;
@@ -627,7 +624,7 @@
private void closeSocket() {
if (mSocket != null) {
try {
- IoBridge.closeAndSignalBlockedThreads(mSocket);
+ SocketUtils.closeSocket(mSocket);
} catch (IOException ignored) { }
}
mSocket = null;
@@ -671,7 +668,7 @@
}
private final class UnicastResponder extends Thread {
- private final InetSocketAddress mSolicitor = new InetSocketAddress();
+ private final InetSocketAddress mSolicitor = new InetSocketAddress(0);
// The recycled buffer for receiving Router Solicitations from clients.
// If the RS is larger than IPV6_MIN_MTU the packets are truncated.
// This is fine since currently only byte 0 is examined anyway.
diff --git a/core/java/android/net/NetworkMisc.aidl b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
similarity index 64%
copy from core/java/android/net/NetworkMisc.aidl
copy to packages/Tethering/src/android/net/util/TetheringMessageBase.java
index c65583f..1b763ce 100644
--- a/core/java/android/net/NetworkMisc.aidl
+++ b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -13,7 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package android.net.util;
-package android.net;
+/**
+ * This class defines Message.what base addresses for various state machine.
+ */
+public class TetheringMessageBase {
+ public static final int BASE_MASTER = 0;
+ public static final int BASE_IPSERVER = 100;
-parcelable NetworkMisc;
+}
diff --git a/packages/Tethering/src/android/net/util/TetheringUtils.java b/packages/Tethering/src/android/net/util/TetheringUtils.java
new file mode 100644
index 0000000..fa543bd
--- /dev/null
+++ b/packages/Tethering/src/android/net/util/TetheringUtils.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.util;
+
+import java.io.FileDescriptor;
+import java.net.SocketException;
+
+/**
+ * Native methods for tethering utilization.
+ *
+ * {@hide}
+ */
+public class TetheringUtils {
+
+ /**
+ * Offload management process need to know conntrack rules to support NAT, but it may not have
+ * permission to create netlink netfilter sockets. Create two netlink netfilter sockets and
+ * share them with offload management process.
+ */
+ public static native boolean configOffload();
+
+ /**
+ * Configures a socket for receiving ICMPv6 router solicitations and sending advertisements.
+ * @param fd the socket's {@link FileDescriptor}.
+ * @param ifIndex the interface index.
+ */
+ public static native void setupRaSocket(FileDescriptor fd, int ifIndex)
+ throws SocketException;
+
+ /**
+ * Read s as an unsigned 16-bit integer.
+ */
+ public static int uint16(short s) {
+ return s & 0xffff;
+ }
+}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
index ba5d08d..1cabc8d 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -16,18 +16,16 @@
package com.android.server.connectivity.tethering;
-import static android.net.ConnectivityManager.EXTRA_ADD_TETHER_TYPE;
-import static android.net.ConnectivityManager.EXTRA_PROVISION_CALLBACK;
-import static android.net.ConnectivityManager.EXTRA_RUN_PROVISION;
-import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
-import static android.net.ConnectivityManager.TETHERING_INVALID;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
-
-import static com.android.internal.R.string.config_wifi_tether_enable;
+import static android.net.TetheringManager.EXTRA_ADD_TETHER_TYPE;
+import static android.net.TetheringManager.EXTRA_PROVISION_CALLBACK;
+import static android.net.TetheringManager.EXTRA_RUN_PROVISION;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_INVALID;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -36,9 +34,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Resources;
import android.net.util.SharedLog;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -48,7 +44,6 @@
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.util.ArraySet;
@@ -56,12 +51,13 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.StateMachine;
+import com.android.networkstack.tethering.R;
import java.io.PrintWriter;
/**
* Re-check tethering provisioning for enabled downstream tether types.
- * Reference ConnectivityManager.TETHERING_{@code *} for each tether type.
+ * Reference TetheringManager.TETHERING_{@code *} for each tether type.
*
* All methods of this class must be accessed from the thread of tethering
* state machine.
@@ -77,9 +73,7 @@
"com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM";
private static final String EXTRA_SUBID = "subId";
- // {@link ComponentName} of the Service used to run tether provisioning.
- private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(
- Resources.getSystem().getString(config_wifi_tether_enable));
+ private final ComponentName mSilentProvisioningService;
private static final int MS_PER_HOUR = 60 * 60 * 1000;
private static final int EVENT_START_PROVISIONING = 0;
private static final int EVENT_STOP_PROVISIONING = 1;
@@ -88,9 +82,9 @@
private static final int EVENT_GET_ENTITLEMENT_VALUE = 4;
// The ArraySet contains enabled downstream types, ex:
- // {@link ConnectivityManager.TETHERING_WIFI}
- // {@link ConnectivityManager.TETHERING_USB}
- // {@link ConnectivityManager.TETHERING_BLUETOOTH}
+ // {@link TetheringManager.TETHERING_WIFI}
+ // {@link TetheringManager.TETHERING_USB}
+ // {@link TetheringManager.TETHERING_BLUETOOTH}
private final ArraySet<Integer> mCurrentTethers;
private final Context mContext;
private final int mPermissionChangeMessageCode;
@@ -98,8 +92,8 @@
private final SparseIntArray mEntitlementCacheValue;
private final EntitlementHandler mHandler;
private final StateMachine mTetherMasterSM;
- // Key: ConnectivityManager.TETHERING_*(downstream).
- // Value: ConnectivityManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
+ // Key: TetheringManager.TETHERING_*(downstream).
+ // Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
private final SparseIntArray mCellularPermitted;
private PendingIntent mProvisioningRecheckAlarm;
private boolean mCellularUpstreamPermitted = true;
@@ -124,6 +118,8 @@
mHandler = new EntitlementHandler(masterHandler.getLooper());
mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PROVISIONING_ALARM),
null, mHandler);
+ mSilentProvisioningService = ComponentName.unflattenFromString(
+ mContext.getResources().getString(R.string.config_wifi_tether_enable));
}
public void setOnUiEntitlementFailedListener(final OnUiEntitlementFailedListener listener) {
@@ -135,7 +131,7 @@
/**
* Ui entitlement check fails in |downstream|.
*
- * @param downstream tethering type from ConnectivityManager.TETHERING_{@code *}.
+ * @param downstream tethering type from TetheringManager.TETHERING_{@code *}.
*/
void onUiEntitlementFailed(int downstream);
}
@@ -171,7 +167,7 @@
* This is called when tethering starts.
* Launch provisioning app if upstream is cellular.
*
- * @param downstreamType tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param downstreamType tethering type from TetheringManager.TETHERING_{@code *}
* @param showProvisioningUi a boolean indicating whether to show the
* provisioning app UI if there is one.
*/
@@ -196,9 +192,9 @@
// till upstream change to cellular.
if (mUsingCellularAsUpstream) {
if (showProvisioningUi) {
- runUiTetherProvisioning(type, config.subId);
+ runUiTetherProvisioning(type, config.activeDataSubId);
} else {
- runSilentTetherProvisioning(type, config.subId);
+ runSilentTetherProvisioning(type, config.activeDataSubId);
}
mNeedReRunProvisioningUi = false;
} else {
@@ -212,7 +208,7 @@
/**
* Tell EntitlementManager that a given type of tethering has been disabled
*
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
*/
public void stopProvisioningIfNeeded(int type) {
mHandler.sendMessage(mHandler.obtainMessage(EVENT_STOP_PROVISIONING, type, 0));
@@ -270,9 +266,9 @@
if (mCellularPermitted.indexOfKey(downstream) < 0) {
if (mNeedReRunProvisioningUi) {
mNeedReRunProvisioningUi = false;
- runUiTetherProvisioning(downstream, config.subId);
+ runUiTetherProvisioning(downstream, config.activeDataSubId);
} else {
- runSilentTetherProvisioning(downstream, config.subId);
+ runSilentTetherProvisioning(downstream, config.activeDataSubId);
}
}
}
@@ -298,7 +294,7 @@
/**
* Re-check tethering provisioning for all enabled tether types.
- * Reference ConnectivityManager.TETHERING_{@code *} for each tether type.
+ * Reference TetheringManager.TETHERING_{@code *} for each tether type.
*
* @param config an object that encapsulates the various tethering configuration elements.
* Note: this method is only called from TetherMaster on the handler thread.
@@ -336,7 +332,8 @@
.getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configManager == null) return null;
- final PersistableBundle carrierConfig = configManager.getConfigForSubId(config.subId);
+ final PersistableBundle carrierConfig = configManager.getConfigForSubId(
+ config.activeDataSubId);
if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) {
return carrierConfig;
@@ -364,7 +361,7 @@
/**
* Run no UI tethering provisioning check.
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
* @param subId default data subscription ID.
*/
@VisibleForTesting
@@ -378,13 +375,10 @@
intent.putExtra(EXTRA_RUN_PROVISION, true);
intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
intent.putExtra(EXTRA_SUBID, subId);
- intent.setComponent(TETHER_SERVICE);
- final long ident = Binder.clearCallingIdentity();
- try {
- mContext.startServiceAsUser(intent, UserHandle.CURRENT);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ intent.setComponent(mSilentProvisioningService);
+ // Only admin user can change tethering and SilentTetherProvisioning don't need to
+ // show UI, it is fine to always start setting's background service as system user.
+ mContext.startService(intent);
}
private void runUiTetherProvisioning(int type, int subId) {
@@ -394,7 +388,7 @@
/**
* Run the UI-enabled tethering provisioning check.
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
* @param subId default data subscription ID.
* @param receiver to receive entitlement check result.
*/
@@ -402,17 +396,14 @@
protected void runUiTetherProvisioning(int type, int subId, ResultReceiver receiver) {
if (DBG) mLog.i("runUiTetherProvisioning: " + type);
- Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
+ Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING_UI);
intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
intent.putExtra(EXTRA_SUBID, subId);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- final long ident = Binder.clearCallingIdentity();
- try {
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ // Only launch entitlement UI for system user. Entitlement UI should not appear for other
+ // user because only admin user is allowed to change tethering.
+ mContext.startActivity(intent);
}
// Not needed to check if this don't run on the handler thread because it's private.
@@ -468,7 +459,7 @@
* Add the mapping between provisioning result and tethering type.
* Notify UpstreamNetworkMonitor if Cellular permission changes.
*
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
* @param resultCode Provisioning result
*/
protected void addDownstreamMapping(int type, int resultCode) {
@@ -483,7 +474,7 @@
/**
* Remove the mapping for input tethering type.
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
*/
protected void removeDownstreamMapping(int type) {
mLog.i("removeDownstreamMapping: " + type);
@@ -632,7 +623,7 @@
/**
* Update the last entitlement value to internal cache
*
- * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
+ * @param type tethering type from TetheringManager.TETHERING_{@code *}
* @param resultCode last entitlement value
* @return the last updated entitlement value
*/
@@ -671,7 +662,7 @@
receiver.send(cacheValue, null);
} else {
ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver);
- runUiTetherProvisioning(downstream, config.subId, proxy);
+ runUiTetherProvisioning(downstream, config.activeDataSubId, proxy);
}
}
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
index 9305414..66b9ade 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
@@ -29,6 +29,7 @@
import java.net.Inet6Address;
import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
@@ -257,7 +258,7 @@
final LinkProperties lp = new LinkProperties();
final IpPrefix local48 = makeUniqueLocalPrefix(ulp, (short) 0, 48);
- lp.addRoute(new RouteInfo(local48, null, null));
+ lp.addRoute(new RouteInfo(local48, null, null, RouteInfo.RTN_UNICAST));
final IpPrefix local64 = makeUniqueLocalPrefix(ulp, subnetId, 64);
// Because this is a locally-generated ULA, we don't have an upstream
@@ -273,7 +274,13 @@
final byte[] bytes = Arrays.copyOf(in6addr, in6addr.length);
bytes[7] = (byte) (subnetId >> 8);
bytes[8] = (byte) subnetId;
- return new IpPrefix(bytes, prefixlen);
+ final InetAddress addr;
+ try {
+ addr = InetAddress.getByAddress(bytes);
+ } catch (UnknownHostException e) {
+ throw new IllegalStateException("Invalid address length: " + bytes.length, e);
+ }
+ return new IpPrefix(addr, prefixlen);
}
// Generates a Unique Locally-assigned Prefix:
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
index 16734d8..cc36f4a 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
@@ -16,35 +16,40 @@
package com.android.server.connectivity.tethering;
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
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.NetworkStats.UID_ALL;
-import static android.net.TrafficStats.UID_TETHERING;
+import static android.net.NetworkStats.UID_TETHERING;
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.usage.NetworkStatsManager;
import android.content.ContentResolver;
-import android.net.ITetheringStatsProvider;
+import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkStats;
+import android.net.NetworkStats.Entry;
import android.net.RouteInfo;
import android.net.netlink.ConntrackMessage;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkSocket;
-import android.net.util.IpUtils;
+import android.net.netstats.provider.AbstractNetworkStatsProvider;
+import android.net.netstats.provider.NetworkStatsProviderCallback;
import android.net.util.SharedLog;
import android.os.Handler;
-import android.os.INetworkManagementService;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.SystemClock;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.text.TextUtils;
+import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
@@ -73,13 +78,19 @@
private static final String ANYIP = "0.0.0.0";
private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
+ @VisibleForTesting
+ enum StatsType {
+ STATS_PER_IFACE,
+ STATS_PER_UID,
+ }
+
private enum UpdateType { IF_NEEDED, FORCE };
private final Handler mHandler;
private final OffloadHardwareInterface mHwInterface;
private final ContentResolver mContentResolver;
- private final INetworkManagementService mNms;
- private final ITetheringStatsProvider mStatsProvider;
+ private final @NonNull OffloadTetheringStatsProvider mStatsProvider;
+ private final @Nullable NetworkStatsProviderCallback mStatsProviderCb;
private final SharedLog mLog;
private final HashMap<String, LinkProperties> mDownstreams;
private boolean mConfigInitialized;
@@ -109,22 +120,23 @@
private int mNatUpdateNetlinkErrors;
public OffloadController(Handler h, OffloadHardwareInterface hwi,
- ContentResolver contentResolver, INetworkManagementService nms, SharedLog log) {
+ ContentResolver contentResolver, NetworkStatsManager nsm, SharedLog log) {
mHandler = h;
mHwInterface = hwi;
mContentResolver = contentResolver;
- mNms = nms;
mStatsProvider = new OffloadTetheringStatsProvider();
mLog = log.forSubComponent(TAG);
mDownstreams = new HashMap<>();
mExemptPrefixes = new HashSet<>();
mLastLocalPrefixStrs = new HashSet<>();
-
+ NetworkStatsProviderCallback providerCallback = null;
try {
- mNms.registerTetheringStatsProvider(mStatsProvider, getClass().getSimpleName());
- } catch (RemoteException e) {
- mLog.e("Cannot register offload stats provider: " + e);
+ providerCallback = nsm.registerNetworkStatsProvider(
+ getClass().getSimpleName(), mStatsProvider);
+ } catch (RuntimeException e) {
+ Log.wtf(TAG, "Cannot register offload stats provider: " + e);
}
+ mStatsProviderCb = providerCallback;
}
/** Start hardware offload. */
@@ -173,7 +185,7 @@
// and we need to synchronize stats and limits between
// software and hardware forwarding.
updateStatsForAllUpstreams();
- forceTetherStatsPoll();
+ mStatsProvider.pushTetherStats();
}
@Override
@@ -186,7 +198,7 @@
// limits set take into account any software tethering
// traffic that has been happening in the meantime.
updateStatsForAllUpstreams();
- forceTetherStatsPoll();
+ mStatsProvider.pushTetherStats();
// [2] (Re)Push all state.
computeAndPushLocalPrefixes(UpdateType.FORCE);
pushAllDownstreamState();
@@ -204,14 +216,11 @@
// the HAL queued the callback.
// TODO: rev the HAL so that it provides an interface name.
- // Fetch current stats, so that when our notification reaches
- // NetworkStatsService and triggers a poll, we will respond with
- // current data (which will be above the limit that was reached).
- // Note that if we just changed upstream, this is unnecessary but harmless.
- // The stats for the previous upstream were already updated on this thread
- // just after the upstream was changed, so they are also up-to-date.
updateStatsForCurrentUpstream();
- forceTetherStatsPoll();
+ mStatsProvider.pushTetherStats();
+ // Push stats to service does not cause the service react to it immediately.
+ // Inform the service about limit reached.
+ if (mStatsProviderCb != null) mStatsProviderCb.onLimitReached();
}
@Override
@@ -253,42 +262,37 @@
return mConfigInitialized && mControlInitialized;
}
- private class OffloadTetheringStatsProvider extends ITetheringStatsProvider.Stub {
- @Override
- public NetworkStats getTetherStats(int how) {
- // getTetherStats() is the only function in OffloadController that can be called from
- // a different thread. Do not attempt to update stats by querying the offload HAL
- // synchronously from a different thread than our Handler thread. http://b/64771555.
- Runnable updateStats = () -> {
- updateStatsForCurrentUpstream();
- };
- if (Looper.myLooper() == mHandler.getLooper()) {
- updateStats.run();
- } else {
- mHandler.post(updateStats);
- }
+ @VisibleForTesting
+ class OffloadTetheringStatsProvider extends AbstractNetworkStatsProvider {
+ // These stats must only ever be touched on the handler thread.
+ @NonNull
+ private NetworkStats mIfaceStats = new NetworkStats(0L, 0);
+ @NonNull
+ private NetworkStats mUidStats = new NetworkStats(0L, 0);
- NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
- NetworkStats.Entry entry = new NetworkStats.Entry();
- entry.set = SET_DEFAULT;
- entry.tag = TAG_NONE;
- entry.uid = (how == STATS_PER_UID) ? UID_TETHERING : UID_ALL;
+ @VisibleForTesting
+ @NonNull
+ NetworkStats getTetherStats(@NonNull StatsType how) {
+ NetworkStats stats = new NetworkStats(0L, 0);
+ final int uid = (how == StatsType.STATS_PER_UID) ? UID_TETHERING : UID_ALL;
- for (Map.Entry<String, ForwardedStats> kv : mForwardedStats.entrySet()) {
- ForwardedStats value = kv.getValue();
- entry.iface = kv.getKey();
- entry.rxBytes = value.rxBytes;
- entry.txBytes = value.txBytes;
- stats.addValues(entry);
+ for (final Map.Entry<String, ForwardedStats> kv : mForwardedStats.entrySet()) {
+ final ForwardedStats value = kv.getValue();
+ final Entry entry = new Entry(kv.getKey(), uid, SET_DEFAULT, TAG_NONE, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, value.rxBytes, 0L, value.txBytes, 0L, 0L);
+ stats = stats.addValues(entry);
}
return stats;
}
@Override
- public void setInterfaceQuota(String iface, long quotaBytes) {
+ public void setLimit(String iface, long quotaBytes) {
+ mLog.i("setLimit: " + iface + "," + quotaBytes);
+ // Listen for all iface is necessary since upstream might be changed after limit
+ // is set.
mHandler.post(() -> {
- if (quotaBytes == ITetheringStatsProvider.QUOTA_UNLIMITED) {
+ if (quotaBytes == QUOTA_UNLIMITED) {
mInterfaceQuotas.remove(iface);
} else {
mInterfaceQuotas.put(iface, quotaBytes);
@@ -296,6 +300,42 @@
maybeUpdateDataLimit(iface);
});
}
+
+ /**
+ * Push stats to service, but does not cause a force polling. Note that this can only be
+ * called on the handler thread.
+ */
+ public void pushTetherStats() {
+ // TODO: remove the accumulated stats and report the diff from HAL directly.
+ if (null == mStatsProviderCb) return;
+ final NetworkStats ifaceDiff =
+ getTetherStats(StatsType.STATS_PER_IFACE).subtract(mIfaceStats);
+ final NetworkStats uidDiff =
+ getTetherStats(StatsType.STATS_PER_UID).subtract(mUidStats);
+ try {
+ mStatsProviderCb.onStatsUpdated(0 /* token */, ifaceDiff, uidDiff);
+ mIfaceStats = mIfaceStats.add(ifaceDiff);
+ mUidStats = mUidStats.add(uidDiff);
+ } catch (RuntimeException e) {
+ mLog.e("Cannot report network stats: ", e);
+ }
+ }
+
+ @Override
+ public void requestStatsUpdate(int token) {
+ mLog.i("requestStatsUpdate: " + token);
+ // Do not attempt to update stats by querying the offload HAL
+ // synchronously from a different thread than the Handler thread. http://b/64771555.
+ mHandler.post(() -> {
+ updateStatsForCurrentUpstream();
+ pushTetherStats();
+ });
+ }
+
+ @Override
+ public void setAlert(long quotaBytes) {
+ // TODO: Ask offload HAL to notify alert without stopping traffic.
+ }
}
private String currentUpstreamInterface() {
@@ -353,14 +393,6 @@
}
}
- private void forceTetherStatsPoll() {
- try {
- mNms.tetherLimitReached(mStatsProvider);
- } catch (RemoteException e) {
- mLog.e("Cannot report data limit reached: " + e);
- }
- }
-
/** Set current tethering upstream LinkProperties. */
public void setUpstreamLinkProperties(LinkProperties lp) {
if (!started() || Objects.equals(mUpstreamLinkProperties, lp)) return;
@@ -477,9 +509,10 @@
if (!ri.hasGateway()) continue;
final String gateway = ri.getGateway().getHostAddress();
- if (ri.isIPv4Default()) {
+ final InetAddress address = ri.getDestination().getAddress();
+ if (ri.isDefaultRoute() && address instanceof Inet4Address) {
v4gateway = gateway;
- } else if (ri.isIPv6Default()) {
+ } else if (ri.isDefaultRoute() && address instanceof Inet6Address) {
v6gateways.add(gateway);
}
}
@@ -547,7 +580,10 @@
private static boolean shouldIgnoreDownstreamRoute(RouteInfo route) {
// Ignore any link-local routes.
- if (!route.getDestinationLinkAddress().isGlobalPreferred()) return true;
+ final IpPrefix destination = route.getDestination();
+ final LinkAddress linkAddr = new LinkAddress(destination.getAddress(),
+ destination.getPrefixLength());
+ if (!linkAddr.isGlobalPreferred()) return true;
return false;
}
@@ -588,7 +624,7 @@
return;
}
- if (!IpUtils.isValidUdpOrTcpPort(srcPort)) {
+ if (!isValidUdpOrTcpPort(srcPort)) {
mLog.e("Invalid src port: " + srcPort);
return;
}
@@ -599,7 +635,7 @@
return;
}
- if (!IpUtils.isValidUdpOrTcpPort(dstPort)) {
+ if (!isValidUdpOrTcpPort(dstPort)) {
mLog.e("Invalid dst port: " + dstPort);
return;
}
@@ -628,7 +664,7 @@
private static Inet4Address parseIPv4Address(String addrString) {
try {
- final InetAddress ip = InetAddress.parseNumericAddress(addrString);
+ final InetAddress ip = InetAddresses.parseNumericAddress(addrString);
// TODO: Consider other sanitization steps here, including perhaps:
// not eql to 0.0.0.0
// not within 169.254.0.0/16
@@ -668,4 +704,8 @@
return 180;
}
}
+
+ private static boolean isValidUdpOrTcpPort(int port) {
+ return port > 0 && port < 65536;
+ }
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 00a6773..90b9d3f 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -16,7 +16,7 @@
package com.android.server.connectivity.tethering;
-import static com.android.internal.util.BitUtils.uint16;
+import static android.net.util.TetheringUtils.uint16;
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
@@ -24,10 +24,13 @@
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
import android.net.util.SharedLog;
+import android.net.util.TetheringUtils;
import android.os.Handler;
import android.os.RemoteException;
import android.system.OsConstants;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
@@ -47,8 +50,6 @@
private static final String NO_IPV4_ADDRESS = "";
private static final String NO_IPV4_GATEWAY = "";
- private static native boolean configOffload();
-
private final Handler mHandler;
private final SharedLog mLog;
private IOffloadControl mOffloadControl;
@@ -92,6 +93,12 @@
txBytes = 0;
}
+ @VisibleForTesting
+ public ForwardedStats(long rxBytes, long txBytes) {
+ this.rxBytes = rxBytes;
+ this.txBytes = txBytes;
+ }
+
/** Add Tx/Rx bytes. */
public void add(ForwardedStats other) {
rxBytes += other.rxBytes;
@@ -107,8 +114,6 @@
public OffloadHardwareInterface(Handler h, SharedLog log) {
mHandler = h;
mLog = log.forSubComponent(TAG);
-
- System.loadLibrary("tetheroffloadjni");
}
/** Get default value indicating whether offload is supported. */
@@ -118,7 +123,7 @@
/** Configure offload management process. */
public boolean initOffloadConfig() {
- return configOffload();
+ return TetheringUtils.configOffload();
}
/** Initialize the tethering offload HAL. */
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 3116321..5bf41ce 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -20,23 +20,25 @@
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
-import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
+import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
-import static android.net.ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY;
-import static android.net.ConnectivityManager.EXTRA_ACTIVE_TETHER;
-import static android.net.ConnectivityManager.EXTRA_AVAILABLE_TETHER;
-import static android.net.ConnectivityManager.EXTRA_ERRORED_TETHER;
import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
-import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
-import static android.net.ConnectivityManager.TETHERING_INVALID;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHERING_WIFI_P2P;
-import static android.net.ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
-import static android.net.ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
-import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
+import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
+import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
+import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER;
+import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER;
+import static android.net.TetheringManager.EXTRA_ERRORED_TETHER;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_INVALID;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+import static android.net.TetheringManager.TETHER_ERROR_MASTER_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
+import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
+import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
+import static android.net.util.TetheringMessageBase.BASE_MASTER;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
@@ -49,8 +51,10 @@
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
@@ -61,19 +65,18 @@
import android.content.IntentFilter;
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
+import android.net.ConnectivityManager;
import android.net.INetd;
-import android.net.INetworkPolicyManager;
-import android.net.INetworkStatsService;
import android.net.ITetheringEventCallback;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkInfo;
-import android.net.NetworkUtils;
import android.net.TetherStatesParcel;
import android.net.TetheringConfigurationParcel;
import android.net.ip.IpServer;
+import android.net.shared.NetdUtils;
import android.net.util.BaseNetdUnsolicitedEventListener;
import android.net.util.InterfaceSet;
import android.net.util.PrefixUtils;
@@ -86,12 +89,12 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
-import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.PhoneStateListener;
@@ -101,12 +104,12 @@
import android.util.Log;
import android.util.SparseArray;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
-import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.networkstack.tethering.R;
@@ -120,6 +123,8 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
/**
*
@@ -137,6 +142,8 @@
};
private static final SparseArray<String> sMagicDecoderRing =
MessageUtils.findMessageNames(sMessageClasses);
+ // Keep in sync with NETID_UNSET in system/netd/include/netid_client.h
+ private static final int NETID_UNSET = 0;
private static class TetherState {
public final IpServer ipServer;
@@ -170,10 +177,6 @@
private final Context mContext;
private final ArrayMap<String, TetherState> mTetherStates;
private final BroadcastReceiver mStateReceiver;
- // Stopship: replace mNMService before production.
- private final INetworkManagementService mNMService;
- private final INetworkStatsService mStatsService;
- private final INetworkPolicyManager mPolicyManager;
private final Looper mLooper;
private final StateMachine mTetherMasterSM;
private final OffloadController mOffloadController;
@@ -185,10 +188,10 @@
private final TetheringDependencies mDeps;
private final EntitlementManager mEntitlementMgr;
private final Handler mHandler;
- private final PhoneStateListener mPhoneStateListener;
private final INetd mNetd;
private final NetdCallback mNetdCallback;
private final UserRestrictionActionListener mTetheringRestriction;
+ private final ActiveDataSubIdListener mActiveDataSubIdListener;
private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
// All the usage of mTetheringEventCallback should run in the same thread.
private ITetheringEventCallback mTetheringEventCallback = null;
@@ -203,14 +206,13 @@
private boolean mWifiTetherRequested;
private Network mTetherUpstream;
private TetherStatesParcel mTetherStatesParcel;
+ private boolean mDataSaverEnabled = false;
+ private String mWifiP2pTetherInterface = null;
public Tethering(TetheringDependencies deps) {
mLog.mark("Tethering.constructed");
mDeps = deps;
mContext = mDeps.getContext();
- mNMService = mDeps.getINetworkManagementService();
- mStatsService = mDeps.getINetworkStatsService();
- mPolicyManager = mDeps.getINetworkPolicyManager();
mNetd = mDeps.getINetd(mContext);
mLooper = mDeps.getTetheringLooper();
@@ -221,12 +223,13 @@
mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper, deps);
mTetherMasterSM.start();
+ final NetworkStatsManager statsManager =
+ (NetworkStatsManager) mContext.getSystemService(Context.NETWORK_STATS_SERVICE);
mHandler = mTetherMasterSM.getHandler();
mOffloadController = new OffloadController(mHandler,
- mDeps.getOffloadHardwareInterface(mHandler, mLog),
- mContext.getContentResolver(), mNMService,
- mLog);
- mUpstreamNetworkMonitor = deps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
+ mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(),
+ statsManager, mLog);
+ mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
mForwardedDownstreams = new HashSet<>();
@@ -252,26 +255,6 @@
mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
});
- mPhoneStateListener = new PhoneStateListener(mLooper) {
- @Override
- public void onActiveDataSubscriptionIdChanged(int subId) {
- mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId
- + " to " + subId);
- if (subId == mActiveDataSubId) return;
-
- mActiveDataSubId = subId;
- updateConfiguration();
- // To avoid launching unexpected provisioning checks, ignore re-provisioning when
- // no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() will be
- // triggered again when CarrierConfig is loaded.
- if (mEntitlementMgr.getCarrierConfig(mConfig) != null) {
- mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
- } else {
- mLog.log("IGNORED reevaluate provisioning due to no carrier config loaded");
- }
- }
- };
-
mStateReceiver = new StateReceiver();
mNetdCallback = new NetdCallback();
@@ -282,8 +265,10 @@
}
final UserManager userManager = (UserManager) mContext.getSystemService(
- Context.USER_SERVICE);
+ Context.USER_SERVICE);
mTetheringRestriction = new UserRestrictionActionListener(userManager, this);
+ final TetheringThreadExecutor executor = new TetheringThreadExecutor(mHandler);
+ mActiveDataSubIdListener = new ActiveDataSubIdListener(executor);
// Load tethering configuration.
updateConfiguration();
@@ -294,8 +279,8 @@
private void startStateMachineUpdaters(Handler handler) {
mCarrierConfigChange.startListening();
- mContext.getSystemService(TelephonyManager.class).listen(
- mPhoneStateListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+ mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener,
+ PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_STATE);
@@ -304,14 +289,45 @@
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
+ filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED);
mContext.registerReceiver(mStateReceiver, filter, null, handler);
+ }
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_MEDIA_SHARED);
- filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
- filter.addDataScheme("file");
- mContext.registerReceiver(mStateReceiver, filter, null, handler);
+ private class TetheringThreadExecutor implements Executor {
+ private final Handler mTetherHandler;
+ TetheringThreadExecutor(Handler handler) {
+ mTetherHandler = handler;
+ }
+ @Override
+ public void execute(Runnable command) {
+ if (!mTetherHandler.post(command)) {
+ throw new RejectedExecutionException(mTetherHandler + " is shutting down");
+ }
+ }
+ }
+ private class ActiveDataSubIdListener extends PhoneStateListener {
+ ActiveDataSubIdListener(Executor executor) {
+ super(executor);
+ }
+
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId
+ + " to " + subId);
+ if (subId == mActiveDataSubId) return;
+
+ mActiveDataSubId = subId;
+ updateConfiguration();
+ // To avoid launching unexpected provisioning checks, ignore re-provisioning
+ // when no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning()
+ // ill be triggered again when CarrierConfig is loaded.
+ if (mEntitlementMgr.getCarrierConfig(mConfig) != null) {
+ mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
+ } else {
+ mLog.log("IGNORED reevaluate provisioning, no carrier config loaded");
+ }
+ }
}
private WifiManager getWifiManager() {
@@ -326,8 +342,7 @@
}
private void maybeDunSettingChanged() {
- final boolean isDunRequired = TetheringConfiguration.checkDunRequired(
- mContext, mActiveDataSubId);
+ final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext);
if (isDunRequired == mConfig.isDunRequired) return;
updateConfiguration();
}
@@ -401,7 +416,6 @@
}
}
-
void interfaceRemoved(String iface) {
if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
synchronized (mPublicSync) {
@@ -472,7 +486,7 @@
}
private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
- final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ final BluetoothAdapter adapter = mDeps.getBluetoothAdapter();
if (adapter == null || !adapter.isEnabled()) {
Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: "
+ (adapter == null));
@@ -633,8 +647,7 @@
reportTetherStateChanged(mTetherStatesParcel);
final Intent bcast = new Intent(ACTION_TETHER_STATE_CHANGED);
- bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
- | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
bcast.putStringArrayListExtra(EXTRA_AVAILABLE_TETHER, availableList);
bcast.putStringArrayListExtra(EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
bcast.putStringArrayListExtra(EXTRA_ACTIVE_TETHER, tetherList);
@@ -651,19 +664,19 @@
if (usbTethered) {
if (wifiTethered || bluetoothTethered) {
- showTetheredNotification(SystemMessage.NOTE_TETHER_GENERAL);
+ showTetheredNotification(R.drawable.stat_sys_tether_general);
} else {
- showTetheredNotification(SystemMessage.NOTE_TETHER_USB);
+ showTetheredNotification(R.drawable.stat_sys_tether_usb);
}
} else if (wifiTethered) {
if (bluetoothTethered) {
- showTetheredNotification(SystemMessage.NOTE_TETHER_GENERAL);
+ showTetheredNotification(R.drawable.stat_sys_tether_general);
} else {
/* We now have a status bar icon for WifiTethering, so drop the notification */
clearTetheredNotification();
}
} else if (bluetoothTethered) {
- showTetheredNotification(SystemMessage.NOTE_TETHER_BLUETOOTH);
+ showTetheredNotification(R.drawable.stat_sys_tether_bluetooth);
} else {
clearTetheredNotification();
}
@@ -676,30 +689,22 @@
@VisibleForTesting
protected void showTetheredNotification(int id, boolean tetheringOn) {
NotificationManager notificationManager =
- (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ (NotificationManager) mContext.createContextAsUser(UserHandle.ALL, 0)
+ .getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) {
return;
}
- int icon = 0;
- switch(id) {
- case SystemMessage.NOTE_TETHER_USB:
- icon = R.drawable.stat_sys_tether_usb;
- break;
- case SystemMessage.NOTE_TETHER_BLUETOOTH:
- icon = R.drawable.stat_sys_tether_bluetooth;
- break;
- case SystemMessage.NOTE_TETHER_GENERAL:
- default:
- icon = R.drawable.stat_sys_tether_general;
- break;
- }
+ final NotificationChannel channel = new NotificationChannel(
+ "TETHERING_STATUS",
+ mContext.getResources().getString(R.string.notification_channel_tethering_status),
+ NotificationManager.IMPORTANCE_LOW);
+ notificationManager.createNotificationChannel(channel);
if (mLastNotificationId != 0) {
- if (mLastNotificationId == icon) {
+ if (mLastNotificationId == id) {
return;
}
- notificationManager.cancelAsUser(null, mLastNotificationId,
- UserHandle.ALL);
+ notificationManager.cancel(null, mLastNotificationId);
mLastNotificationId = 0;
}
@@ -707,8 +712,8 @@
intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
- PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
- null, UserHandle.CURRENT);
+ PendingIntent pi = PendingIntent.getActivity(
+ mContext.createContextAsUser(UserHandle.CURRENT, 0), 0, intent, 0, null);
Resources r = mContext.getResources();
final CharSequence title;
@@ -723,32 +728,30 @@
}
if (mTetheredNotificationBuilder == null) {
- mTetheredNotificationBuilder = new Notification.Builder(mContext,
- SystemNotificationChannels.NETWORK_STATUS);
+ mTetheredNotificationBuilder = new Notification.Builder(mContext, channel.getId());
mTetheredNotificationBuilder.setWhen(0)
.setOngoing(true)
.setColor(mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color))
+ android.R.color.system_notification_accent_color))
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setCategory(Notification.CATEGORY_STATUS);
}
- mTetheredNotificationBuilder.setSmallIcon(icon)
+ mTetheredNotificationBuilder.setSmallIcon(id)
.setContentTitle(title)
.setContentText(message)
.setContentIntent(pi);
mLastNotificationId = id;
- notificationManager.notifyAsUser(null, mLastNotificationId,
- mTetheredNotificationBuilder.buildInto(new Notification()), UserHandle.ALL);
+ notificationManager.notify(null, mLastNotificationId, mTetheredNotificationBuilder.build());
}
@VisibleForTesting
protected void clearTetheredNotification() {
NotificationManager notificationManager =
- (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ (NotificationManager) mContext.createContextAsUser(UserHandle.ALL, 0)
+ .getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null && mLastNotificationId != 0) {
- notificationManager.cancelAsUser(null, mLastNotificationId,
- UserHandle.ALL);
+ notificationManager.cancel(null, mLastNotificationId);
mLastNotificationId = 0;
}
}
@@ -773,6 +776,9 @@
} else if (action.equals(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)) {
mLog.log("OBSERVED user restrictions changed");
handleUserRestrictionAction();
+ } else if (action.equals(ACTION_RESTRICT_BACKGROUND_CHANGED)) {
+ mLog.log("OBSERVED data saver changed");
+ handleDataSaverChanged();
}
}
@@ -847,6 +853,11 @@
}
}
+ private boolean isGroupOwner(WifiP2pGroup group) {
+ return group != null && group.isGroupOwner()
+ && !TextUtils.isEmpty(group.getInterface());
+ }
+
private void handleWifiP2pAction(Intent intent) {
if (mConfig.isWifiP2pLegacyTetheringMode()) return;
@@ -859,30 +870,51 @@
Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group);
}
- if (p2pInfo == null) return;
- // When a p2p group is disconnected, p2pInfo would be cleared.
- // group is still valid for detecting whether this device is group owner.
- if (group == null || !group.isGroupOwner()
- || TextUtils.isEmpty(group.getInterface())) return;
-
synchronized (Tethering.this.mPublicSync) {
- // Enter below only if this device is Group Owner with a valid interface.
- if (p2pInfo.groupFormed) {
- TetherState tetherState = mTetherStates.get(group.getInterface());
- if (tetherState == null
- || (tetherState.lastState != IpServer.STATE_TETHERED
- && tetherState.lastState != IpServer.STATE_LOCAL_ONLY)) {
- enableWifiIpServingLocked(group.getInterface(), IFACE_IP_MODE_LOCAL_ONLY);
- }
- } else {
- disableWifiP2pIpServingLocked(group.getInterface());
+ // if no group is formed, bring it down if needed.
+ if (p2pInfo == null || !p2pInfo.groupFormed) {
+ disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface);
+ mWifiP2pTetherInterface = null;
+ return;
}
+
+ // If there is a group but the device is not the owner, bail out.
+ if (!isGroupOwner(group)) return;
+
+ // If already serving from the correct interface, nothing to do.
+ if (group.getInterface().equals(mWifiP2pTetherInterface)) return;
+
+ // If already serving from another interface, turn it down first.
+ if (!TextUtils.isEmpty(mWifiP2pTetherInterface)) {
+ mLog.w("P2P tethered interface " + mWifiP2pTetherInterface
+ + "is different from current interface "
+ + group.getInterface() + ", re-tether it");
+ disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface);
+ }
+
+ // Finally bring up serving on the new interface
+ mWifiP2pTetherInterface = group.getInterface();
+ enableWifiIpServingLocked(mWifiP2pTetherInterface, IFACE_IP_MODE_LOCAL_ONLY);
}
}
private void handleUserRestrictionAction() {
mTetheringRestriction.onUserRestrictionsChanged();
}
+
+ private void handleDataSaverChanged() {
+ final ConnectivityManager connMgr = (ConnectivityManager) mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ final boolean isDataSaverEnabled = connMgr.getRestrictBackgroundStatus()
+ != ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
+
+ if (mDataSaverEnabled == isDataSaverEnabled) return;
+
+ mDataSaverEnabled = isDataSaverEnabled;
+ if (mDataSaverEnabled) {
+ untetherAll();
+ }
+ }
}
@VisibleForTesting
@@ -960,7 +992,9 @@
disableWifiIpServingLockedCommon(TETHERING_WIFI, ifname, apState);
}
- private void disableWifiP2pIpServingLocked(String ifname) {
+ private void disableWifiP2pIpServingLockedIfNeeded(String ifname) {
+ if (TextUtils.isEmpty(ifname)) return;
+
disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* dummy */ 0);
}
@@ -1003,8 +1037,8 @@
String[] ifaces = null;
try {
- ifaces = mNMService.listInterfaces();
- } catch (Exception e) {
+ ifaces = mNetd.interfaceGetList();
+ } catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "Error listing Interfaces", e);
return;
}
@@ -1163,7 +1197,6 @@
}
class TetherMasterSM extends StateMachine {
- private static final int BASE_MASTER = Protocol.BASE_TETHERING;
// an interface SM has requested Tethering/Local Hotspot
static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MASTER + 1;
// an interface SM has unrequested Tethering/Local Hotspot
@@ -1180,7 +1213,6 @@
static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MASTER + 7;
// Events from EntitlementManager to choose upstream again.
static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MASTER + 8;
-
private final State mInitialState;
private final State mTetherModeAliveState;
@@ -1265,25 +1297,25 @@
protected boolean turnOnMasterTetherSettings() {
final TetheringConfiguration cfg = mConfig;
try {
- mNMService.setIpForwardingEnabled(true);
- } catch (Exception e) {
+ mNetd.ipfwdEnableForwarding(TAG);
+ } catch (RemoteException | ServiceSpecificException e) {
mLog.e(e);
transitionTo(mSetIpForwardingEnabledErrorState);
return false;
}
+
// TODO: Randomize DHCPv4 ranges, especially in hotspot mode.
// Legacy DHCP server is disabled if passed an empty ranges array
final String[] dhcpRanges = cfg.enableLegacyDhcpServer
- ? cfg.legacyDhcpRanges
- : new String[0];
+ ? cfg.legacyDhcpRanges : new String[0];
try {
- // TODO: Find a more accurate method name (startDHCPv4()?).
- mNMService.startTethering(dhcpRanges);
- } catch (Exception e) {
+ NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges);
+ } catch (RemoteException | ServiceSpecificException e) {
try {
- mNMService.stopTethering();
- mNMService.startTethering(dhcpRanges);
- } catch (Exception ee) {
+ // Stop and retry.
+ mNetd.tetherStop();
+ NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges);
+ } catch (RemoteException | ServiceSpecificException ee) {
mLog.e(ee);
transitionTo(mStartTetheringErrorState);
return false;
@@ -1295,15 +1327,15 @@
protected boolean turnOffMasterTetherSettings() {
try {
- mNMService.stopTethering();
- } catch (Exception e) {
+ mNetd.tetherStop();
+ } catch (RemoteException | ServiceSpecificException e) {
mLog.e(e);
transitionTo(mStopTetheringErrorState);
return false;
}
try {
- mNMService.setIpForwardingEnabled(false);
- } catch (Exception e) {
+ mNetd.ipfwdDisableForwarding(TAG);
+ } catch (RemoteException | ServiceSpecificException e) {
mLog.e(e);
transitionTo(mSetIpForwardingDisabledErrorState);
return false;
@@ -1366,19 +1398,25 @@
protected void setDnsForwarders(final Network network, final LinkProperties lp) {
// TODO: Set v4 and/or v6 DNS per available connectivity.
- String[] dnsServers = mConfig.defaultIPv4DNS;
final Collection<InetAddress> dnses = lp.getDnsServers();
// TODO: Properly support the absence of DNS servers.
+ final String[] dnsServers;
if (dnses != null && !dnses.isEmpty()) {
- // TODO: remove this invocation of NetworkUtils.makeStrings().
- dnsServers = NetworkUtils.makeStrings(dnses);
+ dnsServers = new String[dnses.size()];
+ int i = 0;
+ for (InetAddress dns : dnses) {
+ dnsServers[i++] = dns.getHostAddress();
+ }
+ } else {
+ dnsServers = mConfig.defaultIPv4DNS;
}
+ final int netId = (network != null) ? network.netId : NETID_UNSET;
try {
- mNMService.setDnsForwarders(network, dnsServers);
+ mNetd.tetherDnsSet(netId, dnsServers);
mLog.log(String.format(
"SET DNS forwarders: network=%s dnsServers=%s",
network, Arrays.toString(dnsServers)));
- } catch (Exception e) {
+ } catch (RemoteException | ServiceSpecificException e) {
// TODO: Investigate how this can fail and what exactly
// happens if/when such failures occur.
mLog.e("setting DNS forwarders failed, " + e);
@@ -1681,8 +1719,8 @@
Log.e(TAG, "Error in startTethering");
notify(IpServer.CMD_START_TETHERING_ERROR);
try {
- mNMService.setIpForwardingEnabled(false);
- } catch (Exception e) { }
+ mNetd.ipfwdDisableForwarding(TAG);
+ } catch (RemoteException | ServiceSpecificException e) { }
}
}
@@ -1692,8 +1730,8 @@
Log.e(TAG, "Error in stopTethering");
notify(IpServer.CMD_STOP_TETHERING_ERROR);
try {
- mNMService.setIpForwardingEnabled(false);
- } catch (Exception e) { }
+ mNetd.ipfwdDisableForwarding(TAG);
+ } catch (RemoteException | ServiceSpecificException e) { }
}
}
@@ -1703,11 +1741,11 @@
Log.e(TAG, "Error in setDnsForwarders");
notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR);
try {
- mNMService.stopTethering();
- } catch (Exception e) { }
+ mNetd.tetherStop();
+ } catch (RemoteException | ServiceSpecificException e) { }
try {
- mNMService.setIpForwardingEnabled(false);
- } catch (Exception e) { }
+ mNetd.ipfwdDisableForwarding(TAG);
+ } catch (RemoteException | ServiceSpecificException e) { }
}
}
@@ -1867,7 +1905,7 @@
}
}
- void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
// Binder.java closes the resource for us.
@SuppressWarnings("resource")
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -1976,15 +2014,6 @@
mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
- try {
- // Notify that we're tethering (or not) this interface.
- // This is how data saver for instance knows if the user explicitly
- // turned on tethering (thus keeping us from being in data saver mode).
- mPolicyManager.onTetheringChanged(iface, state == IpServer.STATE_TETHERED);
- } catch (RemoteException e) {
- // Not really very much we can do here.
- }
-
// If TetherMasterSM is in ErrorState, TetherMasterSM stays there.
// Thus we give a chance for TetherMasterSM to recover to InitialState
// by sending CMD_CLEAR_ERROR
@@ -2048,7 +2077,7 @@
mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
final TetherState tetherState = new TetherState(
- new IpServer(iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
+ new IpServer(iface, mLooper, interfaceType, mLog, mNetd,
makeControlCallback(), mConfig.enableLegacyDhcpServer,
mDeps.getIpServerDependencies()));
mTetherStates.put(iface, tetherState);
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 0ab4d63..068c346 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -21,31 +21,19 @@
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.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
-import static com.android.internal.R.array.config_mobile_hotspot_provision_app;
-import static com.android.internal.R.array.config_tether_bluetooth_regexs;
-import static com.android.internal.R.array.config_tether_dhcp_range;
-import static com.android.internal.R.array.config_tether_upstream_types;
-import static com.android.internal.R.array.config_tether_usb_regexs;
-import static com.android.internal.R.array.config_tether_wifi_p2p_regexs;
-import static com.android.internal.R.array.config_tether_wifi_regexs;
-import static com.android.internal.R.bool.config_tether_upstream_automatic;
-import static com.android.internal.R.integer.config_mobile_hotspot_provision_check_period;
-import static com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui;
-
-import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
-import android.net.ConnectivityManager;
import android.net.TetheringConfigurationParcel;
import android.net.util.SharedLog;
-import android.provider.Settings;
+import android.provider.DeviceConfig;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.networkstack.tethering.R;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -85,6 +73,12 @@
private static final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"};
+ /**
+ * Use the old dnsmasq DHCP server for tethering instead of the framework implementation.
+ */
+ public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER =
+ "tether_enable_legacy_dhcp_server";
+
public final String[] tetherableUsbRegexs;
public final String[] tetherableWifiRegexs;
public final String[] tetherableWifiP2pRegexs;
@@ -100,35 +94,38 @@
public final String provisioningAppNoUi;
public final int provisioningCheckPeriod;
- public final int subId;
+ public final int activeDataSubId;
public TetheringConfiguration(Context ctx, SharedLog log, int id) {
final SharedLog configLog = log.forSubComponent("config");
- subId = id;
- Resources res = getResources(ctx, subId);
+ activeDataSubId = id;
+ Resources res = getResources(ctx, activeDataSubId);
- tetherableUsbRegexs = getResourceStringArray(res, config_tether_usb_regexs);
+ tetherableUsbRegexs = getResourceStringArray(res, R.array.config_tether_usb_regexs);
// TODO: Evaluate deleting this altogether now that Wi-Fi always passes
// us an interface name. Careful consideration needs to be given to
// implications for Settings and for provisioning checks.
- tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs);
- tetherableWifiP2pRegexs = getResourceStringArray(res, config_tether_wifi_p2p_regexs);
- tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);
+ tetherableWifiRegexs = getResourceStringArray(res, R.array.config_tether_wifi_regexs);
+ tetherableWifiP2pRegexs = getResourceStringArray(
+ res, R.array.config_tether_wifi_p2p_regexs);
+ tetherableBluetoothRegexs = getResourceStringArray(
+ res, R.array.config_tether_bluetooth_regexs);
- isDunRequired = checkDunRequired(ctx, subId);
+ isDunRequired = checkDunRequired(ctx);
- chooseUpstreamAutomatically = getResourceBoolean(res, config_tether_upstream_automatic);
+ chooseUpstreamAutomatically = getResourceBoolean(
+ res, R.bool.config_tether_upstream_automatic);
preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
legacyDhcpRanges = getLegacyDhcpRanges(res);
defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
- enableLegacyDhcpServer = getEnableLegacyDhcpServer(ctx);
+ enableLegacyDhcpServer = getEnableLegacyDhcpServer(res);
- provisioningApp = getResourceStringArray(res, config_mobile_hotspot_provision_app);
+ provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app);
provisioningAppNoUi = getProvisioningAppNoUi(res);
provisioningCheckPeriod = getResourceInteger(res,
- config_mobile_hotspot_provision_check_period,
+ R.integer.config_mobile_hotspot_provision_check_period,
0 /* No periodic re-check */);
configLog.log(toString());
@@ -166,8 +163,8 @@
/** Does the dumping.*/
public void dump(PrintWriter pw) {
- pw.print("subId: ");
- pw.println(subId);
+ pw.print("activeDataSubId: ");
+ pw.println(activeDataSubId);
dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
@@ -179,8 +176,8 @@
pw.print("chooseUpstreamAutomatically: ");
pw.println(chooseUpstreamAutomatically);
- dumpStringArray(pw, "preferredUpstreamIfaceTypes",
- preferredUpstreamNames(preferredUpstreamIfaceTypes));
+ pw.print("legacyPreredUpstreamIfaceTypes: ");
+ pw.println(Arrays.toString(toIntArray(preferredUpstreamIfaceTypes)));
dumpStringArray(pw, "legacyDhcpRanges", legacyDhcpRanges);
dumpStringArray(pw, "defaultIPv4DNS", defaultIPv4DNS);
@@ -196,7 +193,7 @@
/** Returns the string representation of this object.*/
public String toString() {
final StringJoiner sj = new StringJoiner(" ");
- sj.add(String.format("subId:%d", subId));
+ sj.add(String.format("activeDataSubId:%d", activeDataSubId));
sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs)));
sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs)));
sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs)));
@@ -205,7 +202,7 @@
sj.add(String.format("isDunRequired:%s", isDunRequired));
sj.add(String.format("chooseUpstreamAutomatically:%s", chooseUpstreamAutomatically));
sj.add(String.format("preferredUpstreamIfaceTypes:%s",
- makeString(preferredUpstreamNames(preferredUpstreamIfaceTypes))));
+ toIntArray(preferredUpstreamIfaceTypes)));
sj.add(String.format("provisioningApp:%s", makeString(provisioningApp)));
sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi));
sj.add(String.format("enableLegacyDhcpServer:%s", enableLegacyDhcpServer));
@@ -234,29 +231,16 @@
return sj.toString();
}
- private static String[] preferredUpstreamNames(Collection<Integer> upstreamTypes) {
- String[] upstreamNames = null;
-
- if (upstreamTypes != null) {
- upstreamNames = new String[upstreamTypes.size()];
- int i = 0;
- for (Integer netType : upstreamTypes) {
- upstreamNames[i] = ConnectivityManager.getNetworkTypeName(netType);
- i++;
- }
- }
-
- return upstreamNames;
- }
-
/** Check whether dun is required. */
- public static boolean checkDunRequired(Context ctx, int id) {
+ public static boolean checkDunRequired(Context ctx) {
final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
- return (tm != null) ? tm.isTetheringApnRequired(id) : false;
+ // TelephonyManager would uses the active data subscription, which should be the one used
+ // by tethering.
+ return (tm != null) ? tm.isTetheringApnRequired() : false;
}
private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
- final int[] ifaceTypes = res.getIntArray(config_tether_upstream_types);
+ final int[] ifaceTypes = res.getIntArray(R.array.config_tether_upstream_types);
final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
for (int i : ifaceTypes) {
switch (i) {
@@ -306,7 +290,7 @@
}
private static String[] getLegacyDhcpRanges(Resources res) {
- final String[] fromResource = getResourceStringArray(res, config_tether_dhcp_range);
+ final String[] fromResource = getResourceStringArray(res, R.array.config_tether_dhcp_range);
if ((fromResource.length > 0) && (fromResource.length % 2 == 0)) {
return fromResource;
}
@@ -315,7 +299,7 @@
private static String getProvisioningAppNoUi(Resources res) {
try {
- return res.getString(config_mobile_hotspot_provision_app_no_ui);
+ return res.getString(R.string.config_mobile_hotspot_provision_app_no_ui);
} catch (Resources.NotFoundException e) {
return "";
}
@@ -346,10 +330,14 @@
}
}
- private static boolean getEnableLegacyDhcpServer(Context ctx) {
- final ContentResolver cr = ctx.getContentResolver();
- final int intVal = Settings.Global.getInt(cr, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
- return intVal != 0;
+ private boolean getEnableLegacyDhcpServer(final Resources res) {
+ return getResourceBoolean(res, R.bool.config_tether_enable_legacy_dhcp_server)
+ || getDeviceConfigBoolean(TETHER_ENABLE_LEGACY_DHCP_SERVER);
+ }
+
+ @VisibleForTesting
+ protected boolean getDeviceConfigBoolean(final String name) {
+ return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, false /** defaultValue */);
}
private Resources getResources(Context ctx, int subId) {
@@ -386,24 +374,28 @@
return false;
}
+ private static int[] toIntArray(Collection<Integer> values) {
+ final int[] result = new int[values.size()];
+ int index = 0;
+ for (Integer value : values) {
+ result[index++] = value;
+ }
+ return result;
+ }
+
/**
* Convert this TetheringConfiguration to a TetheringConfigurationParcel.
*/
public TetheringConfigurationParcel toStableParcelable() {
final TetheringConfigurationParcel parcel = new TetheringConfigurationParcel();
- parcel.subId = subId;
+ parcel.subId = activeDataSubId;
parcel.tetherableUsbRegexs = tetherableUsbRegexs;
parcel.tetherableWifiRegexs = tetherableWifiRegexs;
parcel.tetherableBluetoothRegexs = tetherableBluetoothRegexs;
parcel.isDunRequired = isDunRequired;
parcel.chooseUpstreamAutomatically = chooseUpstreamAutomatically;
- int[] preferredTypes = new int[preferredUpstreamIfaceTypes.size()];
- int index = 0;
- for (Integer type : preferredUpstreamIfaceTypes) {
- preferredTypes[index++] = type;
- }
- parcel.preferredUpstreamIfaceTypes = preferredTypes;
+ parcel.preferredUpstreamIfaceTypes = toIntArray(preferredUpstreamIfaceTypes);
parcel.legacyDhcpRanges = legacyDhcpRanges;
parcel.defaultIPv4DNS = defaultIPv4DNS;
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
index b16b329..e019c3a 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -16,18 +16,15 @@
package com.android.server.connectivity.tethering;
+import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.net.INetd;
-import android.net.INetworkPolicyManager;
-import android.net.INetworkStatsService;
import android.net.NetworkRequest;
import android.net.ip.IpServer;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.IBinder;
-import android.os.INetworkManagementService;
import android.os.Looper;
-import android.os.ServiceManager;
import com.android.internal.util.StateMachine;
@@ -97,33 +94,6 @@
}
/**
- * Get a reference to INetworkManagementService to registerTetheringStatsProvider from
- * OffloadController. Note: This should be removed soon by Usage refactor work in R
- * development cycle.
- */
- public INetworkManagementService getINetworkManagementService() {
- return INetworkManagementService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
- }
-
- /**
- * Get a reference to INetworkStatsService to force update tethering usage.
- * Note: This should be removed in R development cycle.
- */
- public INetworkStatsService getINetworkStatsService() {
- return INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
- }
-
- /**
- * Get a reference to INetworkPolicyManager to be used by tethering.
- */
- public INetworkPolicyManager getINetworkPolicyManager() {
- return INetworkPolicyManager.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
- }
-
- /**
* Get a reference to INetd to be used by tethering.
*/
public INetd getINetd(Context context) {
@@ -140,4 +110,9 @@
* Get Context of TetheringSerice.
*/
public abstract Context getContext();
+
+ /**
+ * Get a reference to BluetoothAdapter to be used by tethering.
+ */
+ public abstract BluetoothAdapter getBluetoothAdapter();
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
index 6334c20..d5cdd8a 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
@@ -22,14 +22,17 @@
import android.net.RouteInfo;
import android.net.util.InterfaceSet;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
import java.net.InetAddress;
+import java.net.UnknownHostException;
/**
* @hide
*/
public final class TetheringInterfaceUtils {
+ private static final InetAddress IN6ADDR_ANY = getByAddress(
+ new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
+ private static final InetAddress INADDR_ANY = getByAddress(new byte[] {0, 0, 0, 0});
+
/**
* Get upstream interfaces for tethering based on default routes for IPv4/IPv6.
* @return null if there is no usable interface, or a set of at least one interface otherwise.
@@ -40,7 +43,7 @@
}
final LinkProperties lp = ns.linkProperties;
- final String if4 = getInterfaceForDestination(lp, Inet4Address.ANY);
+ final String if4 = getInterfaceForDestination(lp, INADDR_ANY);
final String if6 = getIPv6Interface(ns);
return (if4 == null && if6 == null) ? null : new InterfaceSet(if4, if6);
@@ -76,7 +79,7 @@
&& ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
return canTether
- ? getInterfaceForDestination(ns.linkProperties, Inet6Address.ANY)
+ ? getInterfaceForDestination(ns.linkProperties, IN6ADDR_ANY)
: null;
}
@@ -86,4 +89,12 @@
: null;
return (ri != null) ? ri.getInterface() : null;
}
+
+ private static InetAddress getByAddress(final byte[] addr) {
+ try {
+ return InetAddress.getByAddress(null, addr);
+ } catch (UnknownHostException e) {
+ throw new AssertionError("illegal address length" + addr.length);
+ }
+ }
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
index ba30845..cb7d392 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
@@ -21,15 +21,17 @@
import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
+import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
-import android.net.ConnectivityManager;
import android.net.IIntResultListener;
import android.net.INetworkStackConnector;
import android.net.ITetheringConnector;
import android.net.ITetheringEventCallback;
+import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
@@ -41,7 +43,6 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.ResultReceiver;
-import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserManager;
import android.provider.Settings;
@@ -84,6 +85,7 @@
*/
@VisibleForTesting
public Tethering makeTethering(TetheringDependencies deps) {
+ System.loadLibrary("tetherutilsjni");
return new Tethering(deps);
}
@@ -305,9 +307,15 @@
mDeps = new TetheringDependencies() {
@Override
public NetworkRequest getDefaultNetworkRequest() {
- ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- return cm.getDefaultRequest();
+ // TODO: b/147280869, add a proper system API to replace this.
+ final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder()
+ .clearCapabilities()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build();
+ return trackDefaultRequest;
}
@Override
@@ -339,7 +347,10 @@
service.makeDhcpServer(ifName, params, cb);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ Log.e(TAG, "Fail to make dhcp server");
+ try {
+ cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null);
+ } catch (RemoteException re) { }
}
}
};
@@ -352,7 +363,7 @@
IBinder connector;
try {
final long before = System.currentTimeMillis();
- while ((connector = ServiceManager.getService(
+ while ((connector = (IBinder) mContext.getSystemService(
Context.NETWORK_STACK_SERVICE)) == null) {
if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector");
@@ -366,6 +377,11 @@
}
return INetworkStackConnector.Stub.asInterface(connector);
}
+
+ @Override
+ public BluetoothAdapter getBluetoothAdapter() {
+ return BluetoothAdapter.getDefaultAdapter();
+ }
};
}
return mDeps;
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index dc38c49a..2875f71 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -16,11 +16,15 @@
package com.android.server.connectivity.tethering;
+import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
+import static android.net.ConnectivityManager.TYPE_ETHERNET;
+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_NONE;
-import static android.net.ConnectivityManager.getNetworkTypeName;
+import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -35,10 +39,11 @@
import android.net.util.PrefixUtils;
import android.net.util.SharedLog;
import android.os.Handler;
-import android.os.Process;
import android.util.Log;
+import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.StateMachine;
import java.util.HashMap;
@@ -79,11 +84,25 @@
public static final int EVENT_ON_LINKPROPERTIES = 2;
public static final int EVENT_ON_LOST = 3;
public static final int NOTIFY_LOCAL_PREFIXES = 10;
+ // This value is used by deprecated preferredUpstreamIfaceTypes selection which is default
+ // disabled.
+ @VisibleForTesting
+ public static final int TYPE_NONE = -1;
private static final int CALLBACK_LISTEN_ALL = 1;
private static final int CALLBACK_DEFAULT_INTERNET = 2;
private static final int CALLBACK_MOBILE_REQUEST = 3;
+ private static final SparseIntArray sLegacyTypeToTransport = new SparseIntArray();
+ static {
+ sLegacyTypeToTransport.put(TYPE_MOBILE, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_MOBILE_DUN, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_MOBILE_HIPRI, NetworkCapabilities.TRANSPORT_CELLULAR);
+ sLegacyTypeToTransport.put(TYPE_WIFI, NetworkCapabilities.TRANSPORT_WIFI);
+ sLegacyTypeToTransport.put(TYPE_BLUETOOTH, NetworkCapabilities.TRANSPORT_BLUETOOTH);
+ sLegacyTypeToTransport.put(TYPE_ETHERNET, NetworkCapabilities.TRANSPORT_ETHERNET);
+ }
+
private final Context mContext;
private final SharedLog mLog;
private final StateMachine mTarget;
@@ -130,15 +149,15 @@
*/
public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest,
EntitlementManager entitle) {
- // This is not really a "request", just a way of tracking the system default network.
- // It's guaranteed not to actually bring up any networks because it's the same request
- // as the ConnectivityService default request, and thus shares fate with it. We can't
- // use registerDefaultNetworkCallback because it will not track the system default
- // network if there is a VPN that applies to our UID.
+
+ // defaultNetworkRequest is not really a "request", just a way of tracking the system
+ // default network. It's guaranteed not to actually bring up any networks because it's
+ // the should be the same request as the ConnectivityService default request, and thus
+ // shares fate with it. We can't use registerDefaultNetworkCallback because it will not
+ // track the system default network if there is a VPN that applies to our UID.
if (mDefaultNetworkCallback == null) {
- final NetworkRequest trackDefaultRequest = new NetworkRequest(defaultNetworkRequest);
mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET);
- cm().requestNetwork(trackDefaultRequest, mDefaultNetworkCallback, mHandler);
+ cm().requestNetwork(defaultNetworkRequest, mDefaultNetworkCallback, mHandler);
}
if (mEntitlementMgr == null) {
mEntitlementMgr = entitle;
@@ -198,19 +217,28 @@
mLog.e("registerMobileNetworkRequest() already registered");
return;
}
- // The following use of the legacy type system cannot be removed until
- // after upstream selection no longer finds networks by legacy type.
- // See also http://b/34364553 .
- final int legacyType = mDunRequired ? TYPE_MOBILE_DUN : TYPE_MOBILE_HIPRI;
- final NetworkRequest mobileUpstreamRequest = new NetworkRequest.Builder()
- .setCapabilities(ConnectivityManager.networkCapabilitiesForType(legacyType))
- .build();
+ final NetworkRequest mobileUpstreamRequest;
+ if (mDunRequired) {
+ mobileUpstreamRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_DUN)
+ .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ } else {
+ mobileUpstreamRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ }
// The existing default network and DUN callbacks will be notified.
// Therefore, to avoid duplicate notifications, we only register a no-op.
mMobileNetworkCallback = new UpstreamNetworkCallback(CALLBACK_MOBILE_REQUEST);
+ // The following use of the legacy type system cannot be removed until
+ // upstream selection no longer finds networks by legacy type.
+ // See also http://b/34364553 .
+ final int legacyType = mDunRequired ? TYPE_MOBILE_DUN : TYPE_MOBILE_HIPRI;
+
// TODO: Change the timeout from 0 (no onUnavailable callback) to some
// moderate callback timeout. This might be useful for updating some UI.
// Additionally, we log a message to aid in any subsequent debugging.
@@ -239,7 +267,7 @@
final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType(
mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted());
- mLog.log("preferred upstream type: " + getNetworkTypeName(typeStatePair.type));
+ mLog.log("preferred upstream type: " + typeStatePair.type);
switch (typeStatePair.type) {
case TYPE_MOBILE_DUN:
@@ -328,13 +356,6 @@
network, newNc));
}
- // Log changes in upstream network signal strength, if available.
- if (network.equals(mTetheringUpstreamNetwork) && newNc.hasSignalStrength()) {
- final int newSignal = newNc.getSignalStrength();
- final String prevSignal = getSignalStrength(prev.networkCapabilities);
- mLog.logf("upstream network signal strength: %s -> %s", prevSignal, newSignal);
- }
-
mNetworkMap.put(network, new UpstreamNetworkState(
prev.linkProperties, newNc, network));
// TODO: If sufficient information is available to select a more
@@ -363,16 +384,6 @@
notifyTarget(EVENT_ON_LINKPROPERTIES, network);
}
- private void handleSuspended(Network network) {
- if (!network.equals(mTetheringUpstreamNetwork)) return;
- mLog.log("SUSPENDED current upstream: " + network);
- }
-
- private void handleResumed(Network network) {
- if (!network.equals(mTetheringUpstreamNetwork)) return;
- mLog.log("RESUMED current upstream: " + network);
- }
-
private void handleLost(Network network) {
// There are few TODOs within ConnectivityService's rematching code
// pertaining to spurious onLost() notifications.
@@ -462,20 +473,6 @@
}
@Override
- public void onNetworkSuspended(Network network) {
- if (mCallbackType == CALLBACK_LISTEN_ALL) {
- handleSuspended(network);
- }
- }
-
- @Override
- public void onNetworkResumed(Network network) {
- if (mCallbackType == CALLBACK_LISTEN_ALL) {
- handleResumed(network);
- }
- }
-
- @Override
public void onLost(Network network) {
if (mCallbackType == CALLBACK_DEFAULT_INTERNET) {
mDefaultInternetNetwork = null;
@@ -519,18 +516,15 @@
for (int type : preferredTypes) {
NetworkCapabilities nc;
try {
- nc = ConnectivityManager.networkCapabilitiesForType(type);
+ nc = networkCapabilitiesForType(type);
} catch (IllegalArgumentException iae) {
- Log.e(TAG, "No NetworkCapabilities mapping for legacy type: "
- + ConnectivityManager.getNetworkTypeName(type));
+ Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + type);
continue;
}
if (!isCellularUpstreamPermitted && isCellular(nc)) {
continue;
}
- nc.setSingleUid(Process.myUid());
-
for (UpstreamNetworkState value : netStates) {
if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) {
continue;
@@ -557,11 +551,6 @@
return prefixSet;
}
- private static String getSignalStrength(NetworkCapabilities nc) {
- if (nc == null || !nc.hasSignalStrength()) return "unknown";
- return Integer.toString(nc.getSignalStrength());
- }
-
private static boolean isCellular(UpstreamNetworkState ns) {
return (ns != null) && isCellular(ns.networkCapabilities);
}
@@ -589,4 +578,28 @@
return null;
}
+
+ /**
+ * Given a legacy type (TYPE_WIFI, ...) returns the corresponding NetworkCapabilities instance.
+ * This function is used for deprecated legacy type and be disabled by default.
+ */
+ @VisibleForTesting
+ public static NetworkCapabilities networkCapabilitiesForType(int type) {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+
+ // Map from type to transports.
+ final int notFound = -1;
+ final int transport = sLegacyTypeToTransport.get(type, notFound);
+ Preconditions.checkArgument(transport != notFound, "unknown legacy type: " + type);
+ nc.addTransportType(transport);
+
+ if (type == TYPE_MOBILE_DUN) {
+ nc.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
+ // DUN is restricted network, see NetworkCapabilities#FORCE_RESTRICTED_CAPABILITIES.
+ nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ } else {
+ nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ }
+ return nc;
+ }
}
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
index 81a0548..53782fed 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -20,7 +20,11 @@
srcs: [
"src/**/*.java",
],
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "mts",
+ ],
+ compile_multilib: "both",
static_libs: [
"androidx.test.rules",
"frameworks-base-testutils",
diff --git a/packages/Tethering/tests/unit/jarjar-rules.txt b/packages/Tethering/tests/unit/jarjar-rules.txt
index 64fdebd..921fbed 100644
--- a/packages/Tethering/tests/unit/jarjar-rules.txt
+++ b/packages/Tethering/tests/unit/jarjar-rules.txt
@@ -7,5 +7,6 @@
rule com.android.internal.util.Preconditions* com.android.networkstack.tethering.util.Preconditions@1
rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
+rule com.android.internal.util.TrafficStatsConstants* com.android.networkstack.tethering.util.TrafficStatsConstants@1
rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
diff --git a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
index e01ac7f..e8add98 100644
--- a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
@@ -18,8 +18,6 @@
import static android.net.InetAddresses.parseNumericAddress;
-import static com.google.android.collect.Sets.newHashSet;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -34,6 +32,8 @@
import org.junit.runner.RunWith;
import java.net.Inet4Address;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -47,9 +47,10 @@
private static final int TEST_LEASE_TIME_SECS = 120;
private static final int TEST_MTU = 1000;
private static final Set<Inet4Address> TEST_ADDRESS_SET =
- newHashSet(inet4Addr("192.168.1.123"), inet4Addr("192.168.1.124"));
+ new HashSet<Inet4Address>(Arrays.asList(
+ new Inet4Address[] {inet4Addr("192.168.1.123"), inet4Addr("192.168.1.124")}));
private static final Set<Integer> TEST_ADDRESS_SET_PARCELED =
- newHashSet(0xc0a8017b, 0xc0a8017c);
+ new HashSet<Integer>(Arrays.asList(new Integer[] {0xc0a8017b, 0xc0a8017c}));
private DhcpServingParamsParcelExt mParcel;
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 4358cd6..f29ad78 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -16,13 +16,14 @@
package android.net.ip;
-import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHERING_WIFI_P2P;
-import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
+import static android.net.INetd.IF_STATE_UP;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+import static android.net.TetheringManager.TETHER_ERROR_ENABLE_NAT_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.ip.IpServer.STATE_AVAILABLE;
import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
@@ -51,8 +52,7 @@
import static org.mockito.Mockito.when;
import android.net.INetd;
-import android.net.INetworkStatsService;
-import android.net.InterfaceConfiguration;
+import android.net.InterfaceConfigurationParcel;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -64,7 +64,6 @@
import android.net.util.InterfaceParams;
import android.net.util.InterfaceSet;
import android.net.util.SharedLog;
-import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.text.TextUtils;
@@ -89,6 +88,8 @@
private static final String IFACE_NAME = "testnet1";
private static final String UPSTREAM_IFACE = "upstream0";
private static final String UPSTREAM_IFACE2 = "upstream1";
+ private static final String BLUETOOTH_IFACE_ADDR = "192.168.42.1";
+ private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
private static final int DHCP_LEASE_TIME_SECS = 3600;
private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
@@ -96,11 +97,8 @@
private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000;
- @Mock private INetworkManagementService mNMService;
@Mock private INetd mNetd;
- @Mock private INetworkStatsService mStatsService;
@Mock private IpServer.Callback mCallback;
- @Mock private InterfaceConfiguration mInterfaceConfiguration;
@Mock private SharedLog mSharedLog;
@Mock private IDhcpServer mDhcpServer;
@Mock private RouterAdvertisementDaemon mRaDaemon;
@@ -112,6 +110,7 @@
private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
ArgumentCaptor.forClass(LinkProperties.class);
private IpServer mIpServer;
+ private InterfaceConfigurationParcel mInterfaceConfiguration;
private void initStateMachine(int interfaceType) throws Exception {
initStateMachine(interfaceType, false /* usingLegacyDhcp */);
@@ -131,17 +130,20 @@
}).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
- when(mDependencies.getNetdService()).thenReturn(mNetd);
-
+ mInterfaceConfiguration = new InterfaceConfigurationParcel();
+ mInterfaceConfiguration.flags = new String[0];
+ if (interfaceType == TETHERING_BLUETOOTH) {
+ mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR;
+ mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH;
+ }
mIpServer = new IpServer(
- IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog,
- mNMService, mStatsService, mCallback, usingLegacyDhcp, mDependencies);
+ IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd,
+ mCallback, usingLegacyDhcp, mDependencies);
mIpServer.start();
// Starting the state machine always puts us in a consistent state and notifies
// the rest of the world that we've changed from an unknown to available state.
mLooper.dispatchAll();
- reset(mNMService, mStatsService, mCallback);
- when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
+ reset(mNetd, mCallback);
when(mRaDaemon.start()).thenReturn(true);
}
@@ -158,8 +160,7 @@
if (upstreamIface != null) {
dispatchTetherConnectionChanged(upstreamIface);
}
- reset(mNMService, mStatsService, mCallback);
- when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
+ reset(mNetd, mCallback);
}
@Before public void setUp() throws Exception {
@@ -169,15 +170,14 @@
@Test
public void startsOutAvailable() {
- mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(),
- TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mCallback,
- false /* usingLegacyDhcp */, mDependencies);
+ mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
+ mNetd, mCallback, false /* usingLegacyDhcp */, mDependencies);
mIpServer.start();
mLooper.dispatchAll();
verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mCallback, mNMService, mStatsService);
+ verifyNoMoreInteractions(mCallback, mNetd);
}
@Test
@@ -196,7 +196,7 @@
// None of these commands should trigger us to request action from
// the rest of the system.
dispatchCommand(command);
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mCallback);
}
}
@@ -208,7 +208,7 @@
verify(mCallback).updateInterfaceState(
mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mCallback);
}
@Test
@@ -216,13 +216,17 @@
initStateMachine(TETHERING_BLUETOOTH);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- InOrder inOrder = inOrder(mCallback, mNMService);
- inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
+ InOrder inOrder = inOrder(mCallback, mNetd);
+ inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
+ inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
+ // One for ipv4 route, one for ipv6 link local route.
+ inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
+ any(), any());
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mCallback);
}
@Test
@@ -230,14 +234,16 @@
initTetheredStateMachine(TETHERING_BLUETOOTH, null);
dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
- InOrder inOrder = inOrder(mNMService, mNetd, mStatsService, mCallback);
- inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
+ InOrder inOrder = inOrder(mNetd, mCallback);
+ inOrder.verify(mNetd).tetherApplyDnsInterfaces();
+ inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
+ inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mCallback);
}
@Test
@@ -245,16 +251,19 @@
initStateMachine(TETHERING_USB);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- InOrder inOrder = inOrder(mCallback, mNMService);
- inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
- inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
- inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
+ InOrder inOrder = inOrder(mCallback, mNetd);
+ inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
+ IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
+ inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
+ inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
+ inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
+ any(), any());
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), mLinkPropertiesCaptor.capture());
assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mCallback);
}
@Test
@@ -262,16 +271,19 @@
initStateMachine(TETHERING_WIFI_P2P);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
- InOrder inOrder = inOrder(mCallback, mNMService);
- inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
- inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
- inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
+ InOrder inOrder = inOrder(mCallback, mNetd);
+ inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
+ IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP)));
+ inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
+ inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
+ inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
+ any(), any());
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), mLinkPropertiesCaptor.capture());
assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mCallback);
}
@Test
@@ -281,10 +293,10 @@
// Telling the state machine about its upstream interface triggers
// a little more configuration.
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
- InOrder inOrder = inOrder(mNMService);
- inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ InOrder inOrder = inOrder(mNetd);
+ inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
+ verifyNoMoreInteractions(mNetd, mCallback);
}
@Test
@@ -292,49 +304,44 @@
initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
- InOrder inOrder = inOrder(mNMService, mStatsService);
- inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ InOrder inOrder = inOrder(mNetd);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
+ verifyNoMoreInteractions(mNetd, mCallback);
}
@Test
public void handlesChangingUpstreamNatFailure() throws Exception {
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
- doThrow(RemoteException.class).when(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
+ doThrow(RemoteException.class).when(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
- InOrder inOrder = inOrder(mNMService, mStatsService);
- inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2);
+ InOrder inOrder = inOrder(mNetd);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
}
@Test
public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception {
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
- doThrow(RemoteException.class).when(mNMService).startInterfaceForwarding(
+ doThrow(RemoteException.class).when(mNetd).ipfwdAddInterfaceForward(
IFACE_NAME, UPSTREAM_IFACE2);
dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
- InOrder inOrder = inOrder(mNMService, mStatsService);
- inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2);
+ InOrder inOrder = inOrder(mNetd);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE2);
}
@Test
@@ -342,17 +349,18 @@
initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
- InOrder inOrder = inOrder(mNMService, mNetd, mStatsService, mCallback);
- inOrder.verify(mStatsService).forceUpdate();
- inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
- inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
+ InOrder inOrder = inOrder(mNetd, mCallback);
+ inOrder.verify(mNetd).ipfwdRemoveInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
+ inOrder.verify(mNetd).tetherApplyDnsInterfaces();
+ inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
+ inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
inOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), any(LinkProperties.class));
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mCallback);
}
@Test
@@ -361,13 +369,14 @@
initTetheredStateMachine(TETHERING_USB, null);
if (shouldThrow) {
- doThrow(RemoteException.class).when(mNMService).untetherInterface(IFACE_NAME);
+ doThrow(RemoteException.class).when(mNetd).tetherInterfaceRemove(IFACE_NAME);
}
dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
- InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
- usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
- usbTeardownOrder.verify(mNMService).setInterfaceConfig(
- IFACE_NAME, mInterfaceConfiguration);
+ InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
+ // Currently IpServer interfaceSetCfg twice to stop IPv4. One just set interface down
+ // Another one is set IPv4 to 0.0.0.0/0 as clearng ipv4 address.
+ usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
+ argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
usbTeardownOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
usbTeardownOrder.verify(mCallback).updateLinkProperties(
@@ -380,12 +389,15 @@
public void usbShouldBeTornDownOnTetherError() throws Exception {
initStateMachine(TETHERING_USB);
- doThrow(RemoteException.class).when(mNMService).tetherInterface(IFACE_NAME);
+ doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
- InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
- usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
- usbTeardownOrder.verify(mNMService).setInterfaceConfig(
- IFACE_NAME, mInterfaceConfiguration);
+ InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
+ usbTeardownOrder.verify(mNetd).interfaceSetCfg(
+ argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
+ usbTeardownOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
+
+ usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
+ argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
usbTeardownOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
usbTeardownOrder.verify(mCallback).updateLinkProperties(
@@ -397,11 +409,13 @@
public void shouldTearDownUsbOnUpstreamError() throws Exception {
initTetheredStateMachine(TETHERING_USB, null);
- doThrow(RemoteException.class).when(mNMService).enableNat(anyString(), anyString());
+ doThrow(RemoteException.class).when(mNetd).tetherAddForward(anyString(), anyString());
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
- InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mCallback);
- usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
- usbTeardownOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
+ InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
+ usbTeardownOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
+
+ usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
+ argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
usbTeardownOrder.verify(mCallback).updateInterfaceState(
mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
usbTeardownOrder.verify(mCallback).updateLinkProperties(
@@ -413,11 +427,11 @@
public void ignoresDuplicateUpstreamNotifications() throws Exception {
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mCallback);
for (int i = 0; i < 5; i++) {
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
- verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+ verifyNoMoreInteractions(mNetd, mCallback);
}
}
@@ -510,8 +524,10 @@
}
assertNotNull("missing IPv4 address", addr4);
+ final IpPrefix destination = new IpPrefix(addr4.getAddress(), addr4.getPrefixLength());
// Assert the presence of the associated directly connected route.
- final RouteInfo directlyConnected = new RouteInfo(addr4, null, lp.getInterfaceName());
+ final RouteInfo directlyConnected = new RouteInfo(destination, null, lp.getInterfaceName(),
+ RouteInfo.RTN_UNICAST);
assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'",
lp.getRoutes().contains(directlyConnected));
}
@@ -523,4 +539,22 @@
// never see an empty interface name in any LinkProperties update.
assertFalse(TextUtils.isEmpty(lp.getInterfaceName()));
}
+
+ private boolean assertContainsFlag(String[] flags, String match) {
+ for (String flag : flags) {
+ if (flag.equals(match)) return true;
+ }
+ fail("Missing flag: " + match);
+ return false;
+ }
+
+ private boolean assertNotContainsFlag(String[] flags, String match) {
+ for (String flag : flags) {
+ if (flag.equals(match)) {
+ fail("Unexpected flag: " + match);
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index 99cf9e9..4f07461 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -16,12 +16,13 @@
package com.android.server.connectivity.tethering;
-import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -39,7 +40,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.net.util.SharedLog;
@@ -49,18 +49,16 @@
import android.os.ResultReceiver;
import android.os.SystemProperties;
import android.os.test.TestLooper;
-import android.provider.Settings;
+import android.provider.DeviceConfig;
import android.telephony.CarrierConfigManager;
-import android.test.mock.MockContentResolver;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.R;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.test.BroadcastInterceptingContext;
-import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.networkstack.tethering.R;
import org.junit.After;
import org.junit.Before;
@@ -94,7 +92,6 @@
private final PersistableBundle mCarrierConfig = new PersistableBundle();
private final TestLooper mLooper = new TestLooper();
private Context mMockContext;
- private MockContentResolver mContentResolver;
private TestStateMachine mSM;
private WrappedEntitlementManager mEnMgr;
@@ -110,11 +107,6 @@
public Resources getResources() {
return mResources;
}
-
- @Override
- public ContentResolver getContentResolver() {
- return mContentResolver;
- }
}
public class WrappedEntitlementManager extends EntitlementManager {
@@ -151,28 +143,33 @@
MockitoAnnotations.initMocks(this);
mMockingSession = mockitoSession()
.initMocks(this)
- .spyStatic(SystemProperties.class)
+ .mockStatic(SystemProperties.class)
+ .mockStatic(DeviceConfig.class)
.strictness(Strictness.WARN)
.startMocking();
// Don't disable tethering provisioning unless requested.
doReturn(false).when(
() -> SystemProperties.getBoolean(
eq(EntitlementManager.DISABLE_PROVISIONING_SYSPROP_KEY), anyBoolean()));
+ doReturn(false).when(
+ () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
+ eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
when(mResources.getStringArray(R.array.config_tether_dhcp_range))
- .thenReturn(new String[0]);
+ .thenReturn(new String[0]);
when(mResources.getStringArray(R.array.config_tether_usb_regexs))
- .thenReturn(new String[0]);
+ .thenReturn(new String[0]);
when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
- .thenReturn(new String[0]);
+ .thenReturn(new String[0]);
when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
- .thenReturn(new String[0]);
+ .thenReturn(new String[0]);
when(mResources.getIntArray(R.array.config_tether_upstream_types))
- .thenReturn(new int[0]);
+ .thenReturn(new int[0]);
+ when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
+ false);
+ when(mResources.getString(R.string.config_wifi_tether_enable)).thenReturn("");
when(mLog.forSubComponent(anyString())).thenReturn(mLog);
- mContentResolver = new MockContentResolver();
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
mMockContext = new MockContext(mContext);
mSM = new TestStateMachine();
mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE);
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 8574f54..7e62e5a 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -16,20 +16,26 @@
package com.android.server.connectivity.tethering;
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.STATS_PER_IFACE;
-import static android.net.NetworkStats.STATS_PER_UID;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
-import static android.net.TrafficStats.UID_TETHERING;
+import static android.net.NetworkStats.UID_TETHERING;
+import static android.net.RouteInfo.RTN_UNICAST;
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
+import static com.android.server.connectivity.tethering.OffloadController.StatsType.STATS_PER_IFACE;
+import static com.android.server.connectivity.tethering.OffloadController.StatsType.STATS_PER_UID;
import static com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
import static com.android.testutils.MiscAssertsKt.assertContainsAll;
import static com.android.testutils.MiscAssertsKt.assertThrows;
+import static com.android.testutils.NetworkStatsUtilsKt.orderInsensitiveEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
@@ -38,11 +44,14 @@
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.inOrder;
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.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
+import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.net.ITetheringStatsProvider;
@@ -50,10 +59,12 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkStats;
+import android.net.NetworkStats.Entry;
import android.net.RouteInfo;
+import android.net.netstats.provider.AbstractNetworkStatsProvider;
+import android.net.netstats.provider.NetworkStatsProviderCallback;
import android.net.util.SharedLog;
import android.os.Handler;
-import android.os.INetworkManagementService;
import android.os.Looper;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -96,11 +107,13 @@
@Mock private OffloadHardwareInterface mHardware;
@Mock private ApplicationInfo mApplicationInfo;
@Mock private Context mContext;
- @Mock private INetworkManagementService mNMService;
+ @Mock private NetworkStatsManager mStatsManager;
+ @Mock private NetworkStatsProviderCallback mTetherStatsProviderCb;
private final ArgumentCaptor<ArrayList> mStringArrayCaptor =
ArgumentCaptor.forClass(ArrayList.class);
- private final ArgumentCaptor<ITetheringStatsProvider.Stub> mTetherStatsProviderCaptor =
- ArgumentCaptor.forClass(ITetheringStatsProvider.Stub.class);
+ private final ArgumentCaptor<OffloadController.OffloadTetheringStatsProvider>
+ mTetherStatsProviderCaptor =
+ ArgumentCaptor.forClass(OffloadController.OffloadTetheringStatsProvider.class);
private final ArgumentCaptor<OffloadHardwareInterface.ControlCallback> mControlCallbackCaptor =
ArgumentCaptor.forClass(OffloadHardwareInterface.ControlCallback.class);
private MockContentResolver mContentResolver;
@@ -113,6 +126,8 @@
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
FakeSettingsProvider.clearSettingsProvider();
+ when(mStatsManager.registerNetworkStatsProvider(anyString(), any()))
+ .thenReturn(mTetherStatsProviderCb);
}
@After public void tearDown() throws Exception {
@@ -138,9 +153,9 @@
private OffloadController makeOffloadController() throws Exception {
OffloadController offload = new OffloadController(new Handler(Looper.getMainLooper()),
- mHardware, mContentResolver, mNMService, new SharedLog("test"));
- verify(mNMService).registerTetheringStatsProvider(
- mTetherStatsProviderCaptor.capture(), anyString());
+ mHardware, mContentResolver, mStatsManager, new SharedLog("test"));
+ verify(mStatsManager).registerNetworkStatsProvider(anyString(),
+ mTetherStatsProviderCaptor.capture());
return offload;
}
@@ -269,7 +284,7 @@
final String ipv4Addr = "192.0.2.5";
final String linkAddr = ipv4Addr + "/24";
lp.addLinkAddress(new LinkAddress(linkAddr));
- lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24")));
+ lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, null, RTN_UNICAST));
offload.setUpstreamLinkProperties(lp);
// IPv4 prefixes and addresses on the upstream are simply left as whole
// prefixes (already passed in from UpstreamNetworkMonitor code). If a
@@ -285,7 +300,7 @@
inOrder.verifyNoMoreInteractions();
final String ipv4Gateway = "192.0.2.1";
- lp.addRoute(new RouteInfo(InetAddress.getByName(ipv4Gateway)));
+ lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv4Gateway), null, RTN_UNICAST));
offload.setUpstreamLinkProperties(lp);
// No change in local addresses means no call to setLocalPrefixes().
inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
@@ -296,7 +311,7 @@
inOrder.verifyNoMoreInteractions();
final String ipv6Gw1 = "fe80::cafe";
- lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw1)));
+ lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv6Gw1), null, RTN_UNICAST));
offload.setUpstreamLinkProperties(lp);
// No change in local addresses means no call to setLocalPrefixes().
inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
@@ -310,7 +325,7 @@
inOrder.verifyNoMoreInteractions();
final String ipv6Gw2 = "fe80::d00d";
- lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw2)));
+ lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv6Gw2), null, RTN_UNICAST));
offload.setUpstreamLinkProperties(lp);
// No change in local addresses means no call to setLocalPrefixes().
inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
@@ -327,8 +342,10 @@
final LinkProperties stacked = new LinkProperties();
stacked.setInterfaceName("stacked");
stacked.addLinkAddress(new LinkAddress("192.0.2.129/25"));
- stacked.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
- stacked.addRoute(new RouteInfo(InetAddress.getByName("fe80::bad:f00")));
+ stacked.addRoute(new RouteInfo(null, InetAddress.getByName("192.0.2.254"), null,
+ RTN_UNICAST));
+ stacked.addRoute(new RouteInfo(null, InetAddress.getByName("fe80::bad:f00"), null,
+ RTN_UNICAST));
assertTrue(lp.addStackedLink(stacked));
offload.setUpstreamLinkProperties(lp);
// No change in local addresses means no call to setLocalPrefixes().
@@ -348,7 +365,7 @@
// removed from "local prefixes" and /128s added for the upstream IPv6
// addresses. This is not yet implemented, and for now we simply
// expect to see these /128s.
- lp.addRoute(new RouteInfo(new IpPrefix("2001:db8::/64")));
+ lp.addRoute(new RouteInfo(new IpPrefix("2001:db8::/64"), null, null, RTN_UNICAST));
// "2001:db8::/64" plus "assigned" ASCII in hex
lp.addLinkAddress(new LinkAddress("2001:db8::6173:7369:676e:6564/64"));
// "2001:db8::/64" plus "random" ASCII in hex
@@ -381,12 +398,11 @@
inOrder.verifyNoMoreInteractions();
}
- private void assertNetworkStats(String iface, ForwardedStats stats, NetworkStats.Entry entry) {
- assertEquals(iface, entry.iface);
- assertEquals(stats.rxBytes, entry.rxBytes);
- assertEquals(stats.txBytes, entry.txBytes);
- assertEquals(SET_DEFAULT, entry.set);
- assertEquals(TAG_NONE, entry.tag);
+ private static @NonNull Entry buildTestEntry(@NonNull OffloadController.StatsType how,
+ @NonNull String iface, long rxBytes, long txBytes) {
+ return new Entry(iface, how == STATS_PER_IFACE ? UID_ALL : UID_TETHERING, SET_DEFAULT,
+ TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, rxBytes, 0L,
+ txBytes, 0L, 0L);
}
@Test
@@ -397,19 +413,16 @@
final OffloadController offload = makeOffloadController();
offload.start();
+ final OffloadController.OffloadTetheringStatsProvider provider =
+ mTetherStatsProviderCaptor.getValue();
+
final String ethernetIface = "eth1";
final String mobileIface = "rmnet_data0";
- ForwardedStats ethernetStats = new ForwardedStats();
- ethernetStats.rxBytes = 12345;
- ethernetStats.txBytes = 54321;
-
- ForwardedStats mobileStats = new ForwardedStats();
- mobileStats.rxBytes = 999;
- mobileStats.txBytes = 99999;
-
- when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(ethernetStats);
- when(mHardware.getForwardedStats(eq(mobileIface))).thenReturn(mobileStats);
+ when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(
+ new ForwardedStats(12345, 54321));
+ when(mHardware.getForwardedStats(eq(mobileIface))).thenReturn(
+ new ForwardedStats(999, 99999));
InOrder inOrder = inOrder(mHardware);
@@ -429,10 +442,35 @@
// Expect that we fetch stats from the previous upstream.
inOrder.verify(mHardware, times(1)).getForwardedStats(eq(mobileIface));
- ethernetStats = new ForwardedStats();
- ethernetStats.rxBytes = 100000;
- ethernetStats.txBytes = 100000;
- when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(ethernetStats);
+ // Verify that the fetched stats are stored.
+ final NetworkStats ifaceStats = provider.getTetherStats(STATS_PER_IFACE);
+ final NetworkStats uidStats = provider.getTetherStats(STATS_PER_UID);
+ final NetworkStats expectedIfaceStats = new NetworkStats(0L, 2)
+ .addValues(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
+ .addValues(buildTestEntry(STATS_PER_IFACE, ethernetIface, 12345, 54321));
+
+ final NetworkStats expectedUidStats = new NetworkStats(0L, 2)
+ .addValues(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
+ .addValues(buildTestEntry(STATS_PER_UID, ethernetIface, 12345, 54321));
+
+ assertTrue(orderInsensitiveEquals(expectedIfaceStats, ifaceStats));
+ assertTrue(orderInsensitiveEquals(expectedUidStats, uidStats));
+
+ final ArgumentCaptor<NetworkStats> ifaceStatsCaptor = ArgumentCaptor.forClass(
+ NetworkStats.class);
+ final ArgumentCaptor<NetworkStats> uidStatsCaptor = ArgumentCaptor.forClass(
+ NetworkStats.class);
+
+ // Force pushing stats update to verify the stats reported.
+ provider.pushTetherStats();
+ verify(mTetherStatsProviderCb, times(1)).onStatsUpdated(anyInt(),
+ ifaceStatsCaptor.capture(), uidStatsCaptor.capture());
+ assertTrue(orderInsensitiveEquals(expectedIfaceStats, ifaceStatsCaptor.getValue()));
+ assertTrue(orderInsensitiveEquals(expectedUidStats, uidStatsCaptor.getValue()));
+
+
+ when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(
+ new ForwardedStats(100000, 100000));
offload.setUpstreamLinkProperties(null);
// Expect that we first clear the HAL's upstream parameters.
inOrder.verify(mHardware, times(1)).setUpstreamParameters(
@@ -440,37 +478,38 @@
// Expect that we fetch stats from the previous upstream.
inOrder.verify(mHardware, times(1)).getForwardedStats(eq(ethernetIface));
- ITetheringStatsProvider provider = mTetherStatsProviderCaptor.getValue();
- NetworkStats stats = provider.getTetherStats(STATS_PER_IFACE);
- NetworkStats perUidStats = provider.getTetherStats(STATS_PER_UID);
- waitForIdle();
// There is no current upstream, so no stats are fetched.
inOrder.verify(mHardware, never()).getForwardedStats(any());
inOrder.verifyNoMoreInteractions();
- assertEquals(2, stats.size());
- assertEquals(2, perUidStats.size());
+ // Verify that the stored stats is accumulated.
+ final NetworkStats ifaceStatsAccu = provider.getTetherStats(STATS_PER_IFACE);
+ final NetworkStats uidStatsAccu = provider.getTetherStats(STATS_PER_UID);
+ final NetworkStats expectedIfaceStatsAccu = new NetworkStats(0L, 2)
+ .addValues(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
+ .addValues(buildTestEntry(STATS_PER_IFACE, ethernetIface, 112345, 154321));
- NetworkStats.Entry entry = null;
- for (int i = 0; i < stats.size(); i++) {
- assertEquals(UID_ALL, stats.getValues(i, entry).uid);
- assertEquals(UID_TETHERING, perUidStats.getValues(i, entry).uid);
- }
+ final NetworkStats expectedUidStatsAccu = new NetworkStats(0L, 2)
+ .addValues(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
+ .addValues(buildTestEntry(STATS_PER_UID, ethernetIface, 112345, 154321));
- int ethernetPosition = ethernetIface.equals(stats.getValues(0, entry).iface) ? 0 : 1;
- int mobilePosition = 1 - ethernetPosition;
+ assertTrue(orderInsensitiveEquals(expectedIfaceStatsAccu, ifaceStatsAccu));
+ assertTrue(orderInsensitiveEquals(expectedUidStatsAccu, uidStatsAccu));
- entry = stats.getValues(mobilePosition, entry);
- assertNetworkStats(mobileIface, mobileStats, entry);
- entry = perUidStats.getValues(mobilePosition, entry);
- assertNetworkStats(mobileIface, mobileStats, entry);
+ // Verify that only diff of stats is reported.
+ reset(mTetherStatsProviderCb);
+ provider.pushTetherStats();
+ final NetworkStats expectedIfaceStatsDiff = new NetworkStats(0L, 2)
+ .addValues(buildTestEntry(STATS_PER_IFACE, mobileIface, 0, 0))
+ .addValues(buildTestEntry(STATS_PER_IFACE, ethernetIface, 100000, 100000));
- ethernetStats.rxBytes = 12345 + 100000;
- ethernetStats.txBytes = 54321 + 100000;
- entry = stats.getValues(ethernetPosition, entry);
- assertNetworkStats(ethernetIface, ethernetStats, entry);
- entry = perUidStats.getValues(ethernetPosition, entry);
- assertNetworkStats(ethernetIface, ethernetStats, entry);
+ final NetworkStats expectedUidStatsDiff = new NetworkStats(0L, 2)
+ .addValues(buildTestEntry(STATS_PER_UID, mobileIface, 0, 0))
+ .addValues(buildTestEntry(STATS_PER_UID, ethernetIface, 100000, 100000));
+ verify(mTetherStatsProviderCb, times(1)).onStatsUpdated(anyInt(),
+ ifaceStatsCaptor.capture(), uidStatsCaptor.capture());
+ assertTrue(orderInsensitiveEquals(expectedIfaceStatsDiff, ifaceStatsCaptor.getValue()));
+ assertTrue(orderInsensitiveEquals(expectedUidStatsDiff, uidStatsCaptor.getValue()));
}
@Test
@@ -490,19 +529,19 @@
lp.setInterfaceName(ethernetIface);
offload.setUpstreamLinkProperties(lp);
- ITetheringStatsProvider provider = mTetherStatsProviderCaptor.getValue();
+ AbstractNetworkStatsProvider provider = mTetherStatsProviderCaptor.getValue();
final InOrder inOrder = inOrder(mHardware);
when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true);
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true);
// Applying an interface quota to the current upstream immediately sends it to the hardware.
- provider.setInterfaceQuota(ethernetIface, ethernetLimit);
+ provider.setLimit(ethernetIface, ethernetLimit);
waitForIdle();
inOrder.verify(mHardware).setDataLimit(ethernetIface, ethernetLimit);
inOrder.verifyNoMoreInteractions();
// Applying an interface quota to another upstream does not take any immediate action.
- provider.setInterfaceQuota(mobileIface, mobileLimit);
+ provider.setLimit(mobileIface, mobileLimit);
waitForIdle();
inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
@@ -515,7 +554,7 @@
// Setting a limit of ITetheringStatsProvider.QUOTA_UNLIMITED causes the limit to be set
// to Long.MAX_VALUE.
- provider.setInterfaceQuota(mobileIface, ITetheringStatsProvider.QUOTA_UNLIMITED);
+ provider.setLimit(mobileIface, ITetheringStatsProvider.QUOTA_UNLIMITED);
waitForIdle();
inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE);
@@ -523,7 +562,7 @@
when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(false);
lp.setInterfaceName(ethernetIface);
offload.setUpstreamLinkProperties(lp);
- provider.setInterfaceQuota(mobileIface, mobileLimit);
+ provider.setLimit(mobileIface, mobileLimit);
waitForIdle();
inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
@@ -532,7 +571,7 @@
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(false);
lp.setInterfaceName(mobileIface);
offload.setUpstreamLinkProperties(lp);
- provider.setInterfaceQuota(mobileIface, mobileLimit);
+ provider.setLimit(mobileIface, mobileLimit);
waitForIdle();
inOrder.verify(mHardware).getForwardedStats(ethernetIface);
inOrder.verify(mHardware).stopOffloadControl();
@@ -548,7 +587,7 @@
OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
callback.onStoppedLimitReached();
- verify(mNMService, times(1)).tetherLimitReached(mTetherStatsProviderCaptor.getValue());
+ verify(mTetherStatsProviderCb, times(1)).onStatsUpdated(anyInt(), any(), any());
}
@Test
@@ -574,13 +613,15 @@
final LinkProperties usbLinkProperties = new LinkProperties();
usbLinkProperties.setInterfaceName(RNDIS0);
usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24"));
- usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX)));
+ usbLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, USB_PREFIX);
inOrder.verifyNoMoreInteractions();
// [2] Routes for IPv6 link-local prefixes should never be added.
- usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL)));
+ usbLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString());
inOrder.verifyNoMoreInteractions();
@@ -588,7 +629,8 @@
// [3] Add an IPv6 prefix for good measure. Only new offload-able
// prefixes should be passed to the HAL.
usbLinkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64"));
- usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX)));
+ usbLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX);
inOrder.verifyNoMoreInteractions();
@@ -601,8 +643,10 @@
// [5] Differences in local routes are converted into addDownstream()
// and removeDownstream() invocations accordingly.
- usbLinkProperties.removeRoute(new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, RNDIS0));
- usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_DISCARD_PREFIX)));
+ usbLinkProperties.removeRoute(
+ new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, RNDIS0, RTN_UNICAST));
+ usbLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(IPV6_DISCARD_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX);
inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX);
@@ -646,9 +690,10 @@
// Verify forwarded stats behaviour.
verify(mHardware, times(1)).getForwardedStats(eq(RMNET0));
verify(mHardware, times(1)).getForwardedStats(eq(WLAN0));
+ // TODO: verify the exact stats reported.
+ verify(mTetherStatsProviderCb, times(1)).onStatsUpdated(anyInt(), any(), any());
+ verifyNoMoreInteractions(mTetherStatsProviderCb);
verifyNoMoreInteractions(mHardware);
- verify(mNMService, times(1)).tetherLimitReached(mTetherStatsProviderCaptor.getValue());
- verifyNoMoreInteractions(mNMService);
}
@Test
@@ -680,19 +725,23 @@
final LinkProperties usbLinkProperties = new LinkProperties();
usbLinkProperties.setInterfaceName(RNDIS0);
usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24"));
- usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX)));
+ usbLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
final LinkProperties wifiLinkProperties = new LinkProperties();
wifiLinkProperties.setInterfaceName(WLAN0);
wifiLinkProperties.addLinkAddress(new LinkAddress("192.168.43.1/24"));
- wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(WIFI_PREFIX)));
- wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL)));
+ wifiLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(WIFI_PREFIX), null, null, RTN_UNICAST));
+ wifiLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST));
// Use a benchmark prefix (RFC 5180 + erratum), since the documentation
// prefix is included in the excluded prefix list.
wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::1/64"));
wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::2/64"));
- wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix("2001:2::/64")));
+ wifiLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix("2001:2::/64"), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(wifiLinkProperties);
offload.removeDownstreamInterface(RNDIS0);
@@ -707,8 +756,8 @@
// Verify forwarded stats behaviour.
verify(mHardware, times(1)).getForwardedStats(eq(RMNET0));
verify(mHardware, times(1)).getForwardedStats(eq(WLAN0));
- verify(mNMService, times(1)).tetherLimitReached(mTetherStatsProviderCaptor.getValue());
- verifyNoMoreInteractions(mNMService);
+ verify(mTetherStatsProviderCb, times(1)).onStatsUpdated(anyInt(), any(), any());
+ verifyNoMoreInteractions(mTetherStatsProviderCb);
// TODO: verify local prefixes and downstreams are also pushed to the HAL.
verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture());
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
index 30bff35..3635964 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -21,41 +21,38 @@
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-import static com.android.internal.R.array.config_mobile_hotspot_provision_app;
-import static com.android.internal.R.array.config_tether_bluetooth_regexs;
-import static com.android.internal.R.array.config_tether_dhcp_range;
-import static com.android.internal.R.array.config_tether_upstream_types;
-import static com.android.internal.R.array.config_tether_usb_regexs;
-import static com.android.internal.R.array.config_tether_wifi_regexs;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.net.util.SharedLog;
-import android.provider.Settings;
+import android.provider.DeviceConfig;
import android.telephony.TelephonyManager;
-import android.test.mock.MockContentResolver;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.test.BroadcastInterceptingContext;
-import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.networkstack.tethering.R;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
import java.util.Arrays;
import java.util.Iterator;
@@ -70,9 +67,10 @@
@Mock private TelephonyManager mTelephonyManager;
@Mock private Resources mResources;
@Mock private Resources mResourcesForSubId;
- private MockContentResolver mContentResolver;
private Context mMockContext;
private boolean mHasTelephonyManager;
+ private boolean mEnableLegacyDhcpServer;
+ private MockitoSession mMockingSession;
private class MockTetheringConfiguration extends TetheringConfiguration {
MockTetheringConfiguration(Context ctx, SharedLog log, int id) {
@@ -102,32 +100,44 @@
}
return super.getSystemService(name);
}
-
- @Override
- public ContentResolver getContentResolver() {
- return mContentResolver;
- }
}
@Before
public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- when(mResources.getStringArray(config_tether_dhcp_range)).thenReturn(new String[0]);
- when(mResources.getStringArray(config_tether_usb_regexs)).thenReturn(new String[0]);
- when(mResources.getStringArray(config_tether_wifi_regexs))
+ // TODO: use a dependencies class instead of mock statics.
+ mMockingSession = mockitoSession()
+ .initMocks(this)
+ .mockStatic(DeviceConfig.class)
+ .strictness(Strictness.WARN)
+ .startMocking();
+ doReturn(false).when(
+ () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
+ eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+
+ when(mResources.getStringArray(R.array.config_tether_dhcp_range)).thenReturn(
+ new String[0]);
+ when(mResources.getStringArray(R.array.config_tether_usb_regexs)).thenReturn(new String[0]);
+ when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
.thenReturn(new String[]{ "test_wlan\\d" });
- when(mResources.getStringArray(config_tether_bluetooth_regexs)).thenReturn(new String[0]);
- when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[0]);
- when(mResources.getStringArray(config_mobile_hotspot_provision_app))
+ when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs)).thenReturn(
+ new String[0]);
+ when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
+ when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
.thenReturn(new String[0]);
- mContentResolver = new MockContentResolver();
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
+ false);
mHasTelephonyManager = true;
mMockContext = new MockContext(mContext);
+ mEnableLegacyDhcpServer = false;
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mMockingSession.finishMocking();
}
private TetheringConfiguration getTetheringConfiguration(int... legacyTetherUpstreamTypes) {
- when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(
+ when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(
legacyTetherUpstreamTypes);
return new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
}
@@ -145,7 +155,7 @@
@Test
public void testDunFromTelephonyManagerMeansDun() {
- when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(true);
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(true);
final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI);
final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
@@ -169,7 +179,7 @@
@Test
public void testDunNotRequiredFromTelephonyManagerMeansNoDun() {
- when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false);
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI);
final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
@@ -211,8 +221,8 @@
@Test
public void testNoDefinedUpstreamTypesAddsEthernet() {
- when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[]{});
- when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false);
+ when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[]{});
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -233,9 +243,9 @@
@Test
public void testDefinedUpstreamTypesSansEthernetAddsEthernet() {
- when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(
+ when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(
new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI});
- when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false);
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -251,9 +261,9 @@
@Test
public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() {
- when(mResources.getIntArray(config_tether_upstream_types))
+ when(mResources.getIntArray(R.array.config_tether_upstream_types))
.thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI});
- when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false);
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -269,19 +279,38 @@
@Test
public void testNewDhcpServerDisabled() {
- Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
+ when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
+ true);
+ doReturn(false).when(
+ () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
+ eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
- final TetheringConfiguration cfg = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
- assertTrue(cfg.enableLegacyDhcpServer);
+ final TetheringConfiguration enableByRes =
+ new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ assertTrue(enableByRes.enableLegacyDhcpServer);
+
+ when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
+ false);
+ doReturn(true).when(
+ () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
+ eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+
+ final TetheringConfiguration enableByDevConfig =
+ new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ assertTrue(enableByDevConfig.enableLegacyDhcpServer);
}
@Test
public void testNewDhcpServerEnabled() {
- Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
+ when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
+ false);
+ doReturn(false).when(
+ () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
+ eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
- final TetheringConfiguration cfg = new TetheringConfiguration(
- mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ final TetheringConfiguration cfg =
+ new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+
assertFalse(cfg.enableLegacyDhcpServer);
}
@@ -300,16 +329,17 @@
private void setUpResourceForSubId() {
when(mResourcesForSubId.getStringArray(
- config_tether_dhcp_range)).thenReturn(new String[0]);
+ R.array.config_tether_dhcp_range)).thenReturn(new String[0]);
when(mResourcesForSubId.getStringArray(
- config_tether_usb_regexs)).thenReturn(new String[0]);
+ R.array.config_tether_usb_regexs)).thenReturn(new String[0]);
when(mResourcesForSubId.getStringArray(
- config_tether_wifi_regexs)).thenReturn(new String[]{ "test_wlan\\d" });
+ R.array.config_tether_wifi_regexs)).thenReturn(new String[]{ "test_wlan\\d" });
when(mResourcesForSubId.getStringArray(
- config_tether_bluetooth_regexs)).thenReturn(new String[0]);
- when(mResourcesForSubId.getIntArray(config_tether_upstream_types)).thenReturn(new int[0]);
+ R.array.config_tether_bluetooth_regexs)).thenReturn(new String[0]);
+ when(mResourcesForSubId.getIntArray(R.array.config_tether_upstream_types)).thenReturn(
+ new int[0]);
when(mResourcesForSubId.getStringArray(
- config_mobile_hotspot_provision_app)).thenReturn(PROVISIONING_APP_NAME);
+ R.array.config_mobile_hotspot_provision_app)).thenReturn(PROVISIONING_APP_NAME);
}
}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index 0bc8c79..affd691 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -19,15 +19,18 @@
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
-import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
-import static android.net.ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY;
-import static android.net.ConnectivityManager.EXTRA_ACTIVE_TETHER;
-import static android.net.ConnectivityManager.EXTRA_AVAILABLE_TETHER;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
-import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
+import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
+import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
+import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
+import static android.net.RouteInfo.RTN_UNICAST;
+import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
+import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
+import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER;
+import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
@@ -35,7 +38,6 @@
import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
-import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static org.junit.Assert.assertArrayEquals;
@@ -49,10 +51,10 @@
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
@@ -60,6 +62,8 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.app.usage.NetworkStatsManager;
+import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -68,20 +72,18 @@
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
+import android.net.ConnectivityManager;
import android.net.INetd;
-import android.net.INetworkPolicyManager;
-import android.net.INetworkStatsService;
import android.net.ITetheringEventCallback;
-import android.net.InterfaceConfiguration;
+import android.net.InetAddresses;
+import android.net.InterfaceConfigurationParcel;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
import android.net.NetworkRequest;
-import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.TetherStatesParcel;
import android.net.TetheringConfigurationParcel;
@@ -100,7 +102,6 @@
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.os.Handler;
-import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.RemoteException;
@@ -121,6 +122,7 @@
import com.android.internal.util.StateMachine;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.networkstack.tethering.R;
import org.junit.After;
import org.junit.Before;
@@ -134,6 +136,7 @@
import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Vector;
@RunWith(AndroidJUnit4.class)
@@ -146,14 +149,13 @@
private static final String TEST_USB_IFNAME = "test_rndis0";
private static final String TEST_WLAN_IFNAME = "test_wlan0";
private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
+ private static final String TETHERING_NAME = "Tethering";
private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
@Mock private ApplicationInfo mApplicationInfo;
@Mock private Context mContext;
- @Mock private INetworkManagementService mNMService;
- @Mock private INetworkStatsService mStatsService;
- @Mock private INetworkPolicyManager mPolicyManager;
+ @Mock private NetworkStatsManager mStatsManager;
@Mock private OffloadHardwareInterface mOffloadHardwareInterface;
@Mock private Resources mResources;
@Mock private TelephonyManager mTelephonyManager;
@@ -167,6 +169,7 @@
@Mock private INetd mNetd;
@Mock private UserManager mUserManager;
@Mock private NetworkRequest mNetworkRequest;
+ @Mock private ConnectivityManager mCm;
private final MockIpServerDependencies mIpServerDependencies =
spy(new MockIpServerDependencies());
@@ -184,6 +187,7 @@
private BroadcastReceiver mBroadcastReceiver;
private Tethering mTethering;
private PhoneStateListener mPhoneStateListener;
+ private InterfaceConfigurationParcel mInterfaceConfiguration;
private class TestContext extends BroadcastInterceptingContext {
TestContext(Context base) {
@@ -216,6 +220,8 @@
if (Context.USB_SERVICE.equals(name)) return mUsbManager;
if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
if (Context.USER_SERVICE.equals(name)) return mUserManager;
+ if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
+ if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
return super.getSystemService(name);
}
@@ -224,6 +230,11 @@
if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE;
return super.getSystemServiceName(serviceClass);
}
+
+ @Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return mContext;
+ }
}
public class MockIpServerDependencies extends IpServer.Dependencies {
@@ -247,11 +258,6 @@
}
@Override
- public INetd getNetdService() {
- return mNetd;
- }
-
- @Override
public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
DhcpServerCallbacks cb) {
new Thread(() -> {
@@ -270,6 +276,11 @@
}
@Override
+ protected boolean getDeviceConfigBoolean(final String name) {
+ return false;
+ }
+
+ @Override
protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) {
return mResources;
}
@@ -328,21 +339,6 @@
}
@Override
- public INetworkManagementService getINetworkManagementService() {
- return mNMService;
- }
-
- @Override
- public INetworkStatsService getINetworkStatsService() {
- return mStatsService;
- }
-
- @Override
- public INetworkPolicyManager getINetworkPolicyManager() {
- return mPolicyManager;
- }
-
- @Override
public INetd getINetd(Context context) {
return mNetd;
}
@@ -356,6 +352,12 @@
public Context getContext() {
return mServiceContext;
}
+
+ @Override
+ public BluetoothAdapter getBluetoothAdapter() {
+ // TODO: add test for bluetooth tethering.
+ return null;
+ }
}
private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
@@ -365,23 +367,26 @@
if (withIPv4) {
prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
- NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
+ InetAddresses.parseNumericAddress("10.0.0.1"),
+ TEST_MOBILE_IFNAME, RTN_UNICAST));
}
if (withIPv6) {
- prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
+ prop.addDnsServer(InetAddresses.parseNumericAddress("2001:db8::2"));
prop.addLinkAddress(
- new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
+ new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::"),
NetworkConstants.RFC7421_PREFIX_LENGTH));
prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
- NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
+ InetAddresses.parseNumericAddress("2001:db8::1"),
+ TEST_MOBILE_IFNAME, RTN_UNICAST));
}
if (with464xlat) {
final LinkProperties stackedLink = new LinkProperties();
stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
- NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
+ InetAddresses.parseNumericAddress("192.0.0.1"),
+ TEST_XLAT_MOBILE_IFNAME, RTN_UNICAST));
prop.addStackedLink(stackedLink);
}
@@ -411,32 +416,33 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
+ when(mResources.getStringArray(R.array.config_tether_dhcp_range))
.thenReturn(new String[0]);
- when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
+ when(mResources.getStringArray(R.array.config_tether_usb_regexs))
.thenReturn(new String[] { "test_rndis\\d" });
- when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
+ when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
.thenReturn(new String[]{ "test_wlan\\d" });
- when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_p2p_regexs))
+ when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs))
.thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
- when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
+ when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
.thenReturn(new String[0]);
- when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
- .thenReturn(new int[0]);
- when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
- .thenReturn(false);
- when(mNMService.listInterfaces())
+ when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
+ when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(false);
+ when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
+ false);
+ when(mNetd.interfaceGetList())
.thenReturn(new String[] {
TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME});
- when(mNMService.getInterfaceConfig(anyString()))
- .thenReturn(new InterfaceConfiguration());
+ when(mResources.getString(R.string.config_wifi_tether_enable)).thenReturn("");
+ mInterfaceConfiguration = new InterfaceConfigurationParcel();
+ mInterfaceConfiguration.flags = new String[0];
when(mRouterAdvertisementDaemon.start())
.thenReturn(true);
mServiceContext = new TestContext(mContext);
+ when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(null);
mContentResolver = new MockContentResolver(mServiceContext);
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
- Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
mIntents = new Vector<>();
mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -447,7 +453,7 @@
mServiceContext.registerReceiver(mBroadcastReceiver,
new IntentFilter(ACTION_TETHER_STATE_CHANGED));
mTethering = makeTethering();
- verify(mNMService).registerTetheringStatsProvider(any(), anyString());
+ verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
verify(mNetd).registerUnsolicitedEventListener(any());
final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor =
ArgumentCaptor.forClass(PhoneStateListener.class);
@@ -487,20 +493,21 @@
private void sendWifiP2pConnectionChanged(
boolean isGroupFormed, boolean isGroupOwner, String ifname) {
+ WifiP2pGroup group = null;
WifiP2pInfo p2pInfo = new WifiP2pInfo();
p2pInfo.groupFormed = isGroupFormed;
- p2pInfo.isGroupOwner = isGroupOwner;
+ if (isGroupFormed) {
+ p2pInfo.isGroupOwner = isGroupOwner;
+ group = mock(WifiP2pGroup.class);
+ when(group.isGroupOwner()).thenReturn(isGroupOwner);
+ when(group.getInterface()).thenReturn(ifname);
+ }
- NetworkInfo networkInfo = new NetworkInfo(TYPE_WIFI_P2P, 0, null, null);
+ final Intent intent = mock(Intent.class);
+ when(intent.getAction()).thenReturn(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
+ when(intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO)).thenReturn(p2pInfo);
+ when(intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP)).thenReturn(group);
- WifiP2pGroup group = new WifiP2pGroup();
- group.setIsGroupOwner(isGroupOwner);
- group.setInterface(ifname);
-
- final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, p2pInfo);
- intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, networkInfo);
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, group);
mServiceContext.sendBroadcastAsUserMultiplePermissions(intent, UserHandle.ALL,
P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
}
@@ -519,10 +526,11 @@
}
private void verifyInterfaceServingModeStarted(String ifname) throws Exception {
- verify(mNMService, times(1)).getInterfaceConfig(ifname);
- verify(mNMService, times(1))
- .setInterfaceConfig(eq(ifname), any(InterfaceConfiguration.class));
- verify(mNMService, times(1)).tetherInterface(ifname);
+ verify(mNetd, times(1)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, times(1)).tetherInterfaceAdd(ifname);
+ verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, ifname);
+ verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(ifname),
+ anyString(), anyString());
}
private void verifyTetheringBroadcast(String ifname, String whichExtra) {
@@ -554,7 +562,7 @@
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
}
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager);
}
@@ -577,14 +585,14 @@
prepareUsbTethering(upstreamState);
// This should produce no activity of any kind.
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Pretend we then receive USB configured broadcast.
sendUsbBroadcast(true, true, true);
mLooper.dispatchAll();
// Now we should see the start of tethering mechanics (in this case:
// tetherMatchingInterfaces() which starts by fetching all interfaces).
- verify(mNMService, times(1)).listInterfaces();
+ verify(mNetd, times(1)).interfaceGetList();
// UpstreamNetworkMonitor should receive selected upstream
verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
@@ -614,9 +622,9 @@
verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mNMService, times(1)).setIpForwardingEnabled(true);
- verify(mNMService, times(1)).startTethering(any(String[].class));
- verifyNoMoreInteractions(mNMService);
+ verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
+ verify(mNetd, times(1)).tetherStartWithConfiguration(any());
+ verifyNoMoreInteractions(mNetd);
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verify(mWifiManager).updateInterfaceIpState(
@@ -634,16 +642,16 @@
mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
- // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
- verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
- verify(mNMService, times(2))
- .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, times(1)).stopTethering();
- verify(mNMService, times(1)).setIpForwardingEnabled(false);
+ verify(mNetd, times(1)).tetherApplyDnsInterfaces();
+ verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
+ verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
+ // interfaceSetCfg() called once for enabling and twice disabling IPv4.
+ verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, times(1)).tetherStop();
+ verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
verify(mWifiManager, times(3)).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager);
// Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error.
@@ -680,8 +688,8 @@
UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
runUsbTethering(upstreamState);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
@@ -690,7 +698,8 @@
@Test
public void workingMobileUsbTethering_IPv4LegacyDhcp() {
- Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
+ when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
+ true);
sendConfigurationChanged();
final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
runUsbTethering(upstreamState);
@@ -704,8 +713,8 @@
UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
runUsbTethering(upstreamState);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
@@ -717,8 +726,8 @@
UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
runUsbTethering(upstreamState);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mRouterAdvertisementDaemon, times(1)).start();
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
@@ -732,12 +741,11 @@
UpstreamNetworkState upstreamState = buildMobile464xlatUpstreamState();
runUsbTethering(upstreamState);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
- TEST_XLAT_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
@@ -750,9 +758,9 @@
UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
runUsbTethering(upstreamState);
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
// Then 464xlat comes up
upstreamState = buildMobile464xlatUpstreamState();
@@ -768,20 +776,18 @@
mLooper.dispatchAll();
// Forwarding is added for 464xlat
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
- TEST_XLAT_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
// Forwarding was not re-added for v6 (still times(1))
- verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
- verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).tetherAddForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mNetd, times(1)).ipfwdAddInterfaceForward(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
// DHCP not restarted on downstream (still times(1))
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
}
@Test
public void configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes() throws Exception {
- when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
- .thenReturn(true);
+ when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true);
sendConfigurationChanged();
// Setup IPv6
@@ -816,7 +822,7 @@
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startSoftAp(null);
verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
@@ -829,7 +835,7 @@
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager);
}
@@ -843,7 +849,7 @@
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startSoftAp(null);
verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
@@ -854,9 +860,11 @@
verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mNMService, times(1)).setIpForwardingEnabled(true);
- verify(mNMService, times(1)).startTethering(any(String[].class));
- verifyNoMoreInteractions(mNMService);
+ verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
+ verify(mNetd, times(1)).tetherStartWithConfiguration(any());
+ verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME),
+ anyString(), anyString());
+ verifyNoMoreInteractions(mNetd);
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verify(mWifiManager).updateInterfaceIpState(
@@ -874,8 +882,8 @@
/////
// We do not currently emulate any upstream being found.
//
- // This is why there are no calls to verify mNMService.enableNat() or
- // mNMService.startInterfaceForwarding().
+ // This is why there are no calls to verify mNetd.tetherAddForward() or
+ // mNetd.ipfwdAddInterfaceForward().
/////
// Emulate pressing the WiFi tethering button.
@@ -883,7 +891,7 @@
mLooper.dispatchAll();
verify(mWifiManager, times(1)).stopSoftAp();
verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, when tethering mode
// is being torn down.
@@ -891,16 +899,16 @@
mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
- // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
- verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
- verify(mNMService, atLeastOnce())
- .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, times(1)).stopTethering();
- verify(mNMService, times(1)).setIpForwardingEnabled(false);
+ verify(mNetd, times(1)).tetherApplyDnsInterfaces();
+ verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
+ verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
+ // interfaceSetCfg() called once for enabling and twice for disabling IPv4.
+ verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, times(1)).tetherStop();
+ verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
verify(mWifiManager, times(3)).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
verifyNoMoreInteractions(mWifiManager);
// Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error.
@@ -911,14 +919,14 @@
@Test
public void failureEnablingIpForwarding() throws Exception {
when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
- doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
+ doThrow(new RemoteException()).when(mNetd).ipfwdEnableForwarding(TETHERING_NAME);
// Emulate pressing the WiFi tethering button.
mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startSoftAp(null);
verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
@@ -927,15 +935,15 @@
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll();
- // We verify get/set called thrice here: twice for setup (on NMService) and once during
- // teardown (on Netd) because all events happen over the course of the single
+ // We verify get/set called three times here: twice for setup and once during
+ // teardown because all events happen over the course of the single
// dispatchAll() above. Note that once the IpServer IPv4 address config
// code is refactored the two calls during shutdown will revert to one.
- verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
- verify(mNMService, times(2))
- .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
- verify(mNetd, times(1)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName)));
- verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
+ verify(mNetd, times(3)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName)));
+ verify(mNetd, times(1)).tetherInterfaceAdd(TEST_WLAN_IFNAME);
+ verify(mNetd, times(1)).networkAddInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
+ verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(TEST_WLAN_IFNAME),
+ anyString(), anyString());
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
verify(mWifiManager).updateInterfaceIpState(
@@ -945,18 +953,20 @@
assertEquals(3, mTetheringDependencies.mIsTetheringSupportedCalls);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
// This is called, but will throw.
- verify(mNMService, times(1)).setIpForwardingEnabled(true);
+ verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
// This never gets called because of the exception thrown above.
- verify(mNMService, times(0)).startTethering(any(String[].class));
+ verify(mNetd, times(0)).tetherStartWithConfiguration(any());
// When the master state machine transitions to an error state it tells
// downstream interfaces, which causes us to tell Wi-Fi about the error
// so it can take down AP mode.
- verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
+ verify(mNetd, times(1)).tetherApplyDnsInterfaces();
+ verify(mNetd, times(1)).tetherInterfaceRemove(TEST_WLAN_IFNAME);
+ verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_WLAN_IFNAME);
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
verifyNoMoreInteractions(mWifiManager);
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
}
private void runUserRestrictionsChange(
@@ -1210,12 +1220,12 @@
@Test
public void testMultiSimAware() throws Exception {
final TetheringConfiguration initailConfig = mTethering.getTetheringConfiguration();
- assertEquals(INVALID_SUBSCRIPTION_ID, initailConfig.subId);
+ assertEquals(INVALID_SUBSCRIPTION_ID, initailConfig.activeDataSubId);
final int fakeSubId = 1234;
mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId);
final TetheringConfiguration newConfig = mTethering.getTetheringConfiguration();
- assertEquals(fakeSubId, newConfig.subId);
+ assertEquals(fakeSubId, newConfig.activeDataSubId);
}
private void workingWifiP2pGroupOwner(
@@ -1228,9 +1238,9 @@
verifyInterfaceServingModeStarted(TEST_P2P_IFNAME);
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER);
- verify(mNMService, times(1)).setIpForwardingEnabled(true);
- verify(mNMService, times(1)).startTethering(any(String[].class));
- verifyNoMoreInteractions(mNMService);
+ verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
+ verify(mNetd, times(1)).tetherStartWithConfiguration(any());
+ verifyNoMoreInteractions(mNetd);
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
// This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
@@ -1245,16 +1255,16 @@
mTethering.interfaceRemoved(TEST_P2P_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, times(1)).untetherInterface(TEST_P2P_IFNAME);
- // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
- verify(mNMService, times(2)).getInterfaceConfig(TEST_P2P_IFNAME);
- verify(mNMService, times(2))
- .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, times(1)).stopTethering();
- verify(mNMService, times(1)).setIpForwardingEnabled(false);
+ verify(mNetd, times(1)).tetherApplyDnsInterfaces();
+ verify(mNetd, times(1)).tetherInterfaceRemove(TEST_P2P_IFNAME);
+ verify(mNetd, times(1)).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
+ // interfaceSetCfg() called once for enabling and twice for disabling IPv4.
+ verify(mNetd, times(3)).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, times(1)).tetherStop();
+ verify(mNetd, times(1)).ipfwdDisableForwarding(TETHERING_NAME);
verify(mUpstreamNetworkMonitor, never()).getCurrentPreferredUpstream();
verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
- verifyNoMoreInteractions(mNMService);
+ verifyNoMoreInteractions(mNetd);
// Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error.
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
@@ -1268,12 +1278,11 @@
sendWifiP2pConnectionChanged(true, false, TEST_P2P_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
- verify(mNMService, never())
- .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME);
- verify(mNMService, never()).setIpForwardingEnabled(true);
- verify(mNMService, never()).startTethering(any(String[].class));
+ verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME);
+ verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
+ verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
+ verify(mNetd, never()).tetherStartWithConfiguration(any());
// Emulate externally-visible WifiP2pManager effects, when wifi p2p group
// is being removed.
@@ -1281,13 +1290,13 @@
mTethering.interfaceRemoved(TEST_P2P_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, never()).untetherInterface(TEST_P2P_IFNAME);
- verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
- verify(mNMService, never())
- .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, never()).stopTethering();
- verify(mNMService, never()).setIpForwardingEnabled(false);
- verifyNoMoreInteractions(mNMService);
+ verify(mNetd, never()).tetherApplyDnsInterfaces();
+ verify(mNetd, never()).tetherInterfaceRemove(TEST_P2P_IFNAME);
+ verify(mNetd, never()).networkRemoveInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
+ verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, never()).tetherStop();
+ verify(mNetd, never()).ipfwdDisableForwarding(TETHERING_NAME);
+ verifyNoMoreInteractions(mNetd);
// Asking for the last error after the per-interface state machine
// has been reaped yields an unknown interface error.
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
@@ -1306,7 +1315,7 @@
private void workingWifiP2pGroupOwnerLegacyMode(
boolean emulateInterfaceStatusChanged) throws Exception {
// change to legacy mode and update tethering information by chaning SIM
- when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_p2p_regexs))
+ when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs))
.thenReturn(new String[]{});
final int fakeSubId = 1234;
mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId);
@@ -1317,12 +1326,11 @@
sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
mLooper.dispatchAll();
- verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
- verify(mNMService, never())
- .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
- verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME);
- verify(mNMService, never()).setIpForwardingEnabled(true);
- verify(mNMService, never()).startTethering(any(String[].class));
+ verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
+ verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME);
+ verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
+ verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
+ verify(mNetd, never()).tetherStartWithConfiguration(any());
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
}
@Test
@@ -1345,6 +1353,50 @@
workingWifiP2pGroupClient(false);
}
+ private void setDataSaverEnabled(boolean enabled) {
+ final Intent intent = new Intent(ACTION_RESTRICT_BACKGROUND_CHANGED);
+ mServiceContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+
+ final int status = enabled ? RESTRICT_BACKGROUND_STATUS_ENABLED
+ : RESTRICT_BACKGROUND_STATUS_DISABLED;
+ when(mCm.getRestrictBackgroundStatus()).thenReturn(status);
+ mLooper.dispatchAll();
+ }
+
+ @Test
+ public void testDataSaverChanged() {
+ // Start Tethering.
+ final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
+ runUsbTethering(upstreamState);
+ assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
+ // Data saver is ON.
+ setDataSaverEnabled(true);
+ // Verify that tethering should be disabled.
+ verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
+ mTethering.interfaceRemoved(TEST_USB_IFNAME);
+ mLooper.dispatchAll();
+ assertEquals(mTethering.getTetheredIfaces(), new String[0]);
+ reset(mUsbManager);
+
+ runUsbTethering(upstreamState);
+ // Verify that user can start tethering again without turning OFF data saver.
+ assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
+
+ // If data saver is keep ON with change event, tethering should not be OFF this time.
+ setDataSaverEnabled(true);
+ verify(mUsbManager, times(0)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
+ assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
+
+ // If data saver is turned OFF, it should not change tethering.
+ setDataSaverEnabled(false);
+ verify(mUsbManager, times(0)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
+ assertContains(Arrays.asList(mTethering.getTetheredIfaces()), TEST_USB_IFNAME);
+ }
+
+ private static <T> void assertContains(Collection<T> collection, T element) {
+ assertTrue(element + " not found in " + collection, collection.contains(element));
+ }
+
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index c90abbb..5ed75bf 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -18,13 +18,14 @@
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
-import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static com.android.server.connectivity.tethering.UpstreamNetworkMonitor.TYPE_NONE;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -538,13 +539,15 @@
mUNM.selectPreferredUpstreamType(preferredTypes));
verify(mEntitleMgr, times(1)).maybeRunProvisioning();
}
+
private void assertSatisfiesLegacyType(int legacyType, UpstreamNetworkState ns) {
if (legacyType == TYPE_NONE) {
assertTrue(ns == null);
return;
}
- final NetworkCapabilities nc = ConnectivityManager.networkCapabilitiesForType(legacyType);
+ final NetworkCapabilities nc =
+ UpstreamNetworkMonitor.networkCapabilitiesForType(legacyType);
assertTrue(nc.satisfiedByNetworkCapabilities(ns.networkCapabilities));
}
diff --git a/packages/WAPPushManager/Android.bp b/packages/WAPPushManager/Android.bp
index c391369..083dac9 100644
--- a/packages/WAPPushManager/Android.bp
+++ b/packages/WAPPushManager/Android.bp
@@ -10,5 +10,5 @@
proguard_flags_files: ["proguard.flags"],
},
- product_specific: true,
+ system_ext_specific: true,
}
diff --git a/packages/WAPPushManager/CleanSpec.mk b/packages/WAPPushManager/CleanSpec.mk
index 2dcbb10..f4e316c 100644
--- a/packages/WAPPushManager/CleanSpec.mk
+++ b/packages/WAPPushManager/CleanSpec.mk
@@ -49,3 +49,5 @@
# ************************************************
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/WAPPushManager)
+$(call add-clean-step, rm -rf $(TARGET_OUT_PRODUCT)/app/WAPPushManager)
+
diff --git a/packages/WallpaperCropper/Android.bp b/packages/WallpaperCropper/Android.bp
index 40c4235..ac38b27 100644
--- a/packages/WallpaperCropper/Android.bp
+++ b/packages/WallpaperCropper/Android.bp
@@ -3,7 +3,7 @@
srcs: ["src/**/*.java"],
platform_apis: true,
certificate: "platform",
- product_specific: true,
+ system_ext_specific: true,
privileged: true,
optimize: {
proguard_flags_files: ["proguard.flags"],
diff --git a/packages/WallpaperCropper/CleanSpec.mk b/packages/WallpaperCropper/CleanSpec.mk
index e6d8d5a..f08c343 100644
--- a/packages/WallpaperCropper/CleanSpec.mk
+++ b/packages/WallpaperCropper/CleanSpec.mk
@@ -44,6 +44,7 @@
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/WallpaperCropper)
+$(call add-clean-step, rm -rf $(TARGET_OUT_PRODUCT)/priv-app/WallpaperCropper)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java
index b7e05d9..7b5514b 100644
--- a/rs/java/android/renderscript/BaseObj.java
+++ b/rs/java/android/renderscript/BaseObj.java
@@ -16,8 +16,10 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import dalvik.system.CloseGuard;
+
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index b8eb3a1..0941907 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* <p>An Element represents one item within an {@link
diff --git a/rs/java/android/renderscript/FileA3D.java b/rs/java/android/renderscript/FileA3D.java
index 9a6b0bc..7cc2825 100644
--- a/rs/java/android/renderscript/FileA3D.java
+++ b/rs/java/android/renderscript/FileA3D.java
@@ -16,13 +16,13 @@
package android.renderscript;
-import java.io.File;
-import java.io.InputStream;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.content.res.Resources;
+import java.io.File;
+import java.io.InputStream;
+
/**
* @hide
* @deprecated in API 16
diff --git a/rs/java/android/renderscript/Font.java b/rs/java/android/renderscript/Font.java
index 583350e..df9d801 100644
--- a/rs/java/android/renderscript/Font.java
+++ b/rs/java/android/renderscript/Font.java
@@ -16,17 +16,16 @@
package android.renderscript;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.os.Environment;
+
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
-import android.os.Environment;
-
-import android.annotation.UnsupportedAppUsage;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-
/**
* @hide
* @deprecated in API 16
diff --git a/rs/java/android/renderscript/Matrix4f.java b/rs/java/android/renderscript/Matrix4f.java
index 026c9fb..a9469c9 100644
--- a/rs/java/android/renderscript/Matrix4f.java
+++ b/rs/java/android/renderscript/Matrix4f.java
@@ -16,8 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
-import java.lang.Math;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/Mesh.java b/rs/java/android/renderscript/Mesh.java
index 5321dcb..826225a 100644
--- a/rs/java/android/renderscript/Mesh.java
+++ b/rs/java/android/renderscript/Mesh.java
@@ -16,7 +16,8 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.util.Vector;
/**
diff --git a/rs/java/android/renderscript/Program.java b/rs/java/android/renderscript/Program.java
index e28d646..ff07218 100644
--- a/rs/java/android/renderscript/Program.java
+++ b/rs/java/android/renderscript/Program.java
@@ -17,14 +17,14 @@
package android.renderscript;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.res.Resources;
+import android.util.Log;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
-import android.annotation.UnsupportedAppUsage;
-import android.content.res.Resources;
-import android.util.Log;
-
/**
* @hide
diff --git a/rs/java/android/renderscript/ProgramFragment.java b/rs/java/android/renderscript/ProgramFragment.java
index 3dde9b6..8805312 100644
--- a/rs/java/android/renderscript/ProgramFragment.java
+++ b/rs/java/android/renderscript/ProgramFragment.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/ProgramFragmentFixedFunction.java b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
index d05d41d..c741ce6 100644
--- a/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/ProgramRaster.java b/rs/java/android/renderscript/ProgramRaster.java
index 33000ac..a21696c 100644
--- a/rs/java/android/renderscript/ProgramRaster.java
+++ b/rs/java/android/renderscript/ProgramRaster.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/ProgramStore.java b/rs/java/android/renderscript/ProgramStore.java
index 622fe21..7e61347 100644
--- a/rs/java/android/renderscript/ProgramStore.java
+++ b/rs/java/android/renderscript/ProgramStore.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/ProgramVertex.java b/rs/java/android/renderscript/ProgramVertex.java
index 83d9ea7..9257234 100644
--- a/rs/java/android/renderscript/ProgramVertex.java
+++ b/rs/java/android/renderscript/ProgramVertex.java
@@ -38,7 +38,7 @@
**/
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/ProgramVertexFixedFunction.java b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
index 579d3bb..03c2eaf 100644
--- a/rs/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/rs/java/android/renderscript/RSSurfaceView.java b/rs/java/android/renderscript/RSSurfaceView.java
index 561373c..6bdde38 100644
--- a/rs/java/android/renderscript/RSSurfaceView.java
+++ b/rs/java/android/renderscript/RSSurfaceView.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index f4c2777..46c49e5 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
diff --git a/rs/java/android/renderscript/RenderScriptCacheDir.java b/rs/java/android/renderscript/RenderScriptCacheDir.java
index 1797bef..862d032 100644
--- a/rs/java/android/renderscript/RenderScriptCacheDir.java
+++ b/rs/java/android/renderscript/RenderScriptCacheDir.java
@@ -16,7 +16,8 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.File;
/**
diff --git a/rs/java/android/renderscript/RenderScriptGL.java b/rs/java/android/renderscript/RenderScriptGL.java
index 6fac83e..dafaf36 100644
--- a/rs/java/android/renderscript/RenderScriptGL.java
+++ b/rs/java/android/renderscript/RenderScriptGL.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.view.Surface;
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index 9ad9aea..d1d3a76 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.SparseArray;
/**
diff --git a/services/Android.bp b/services/Android.bp
index 53d792d..943e491 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -111,7 +111,7 @@
srcs: [":services-sources"],
installable: false,
// TODO: remove the --hide options below
- args: " --show-single-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES,process=android.annotation.SystemApi.Process.SYSTEM_SERVER\\)" +
+ args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES,process=android.annotation.SystemApi.Process.SYSTEM_SERVER\\)" +
" --hide-annotation android.annotation.Hide" +
" --hide-package com.google.android.startop.iorap" +
" --hide ReferencesHidden" +
@@ -121,6 +121,12 @@
"framework-all",
],
visibility: ["//visibility:private"],
+ check_api: {
+ current: {
+ api_file: "api/current.txt",
+ removed_api_file: "api/removed.txt",
+ },
+ },
}
java_library {
diff --git a/services/api/current.txt b/services/api/current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/api/removed.txt b/services/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/core/Android.bp b/services/core/Android.bp
index cbd095b..4c569ef 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -27,8 +27,8 @@
"android.hardware.light-V2.0-java",
"android.hardware.power-V1.0-java",
"android.hardware.tv.cec-V1.0-java",
+ "android.hardware.vibrator-java",
"app-compat-annotations",
- "vintf-vibrator-java",
"framework-tethering",
],
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index d162441..bbb7c52 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -2167,8 +2167,9 @@
@Override
public long currentNetworkTimeMillis() {
final NtpTrustedTime time = NtpTrustedTime.getInstance(getContext());
- if (time.hasCache()) {
- return time.currentTimeMillis();
+ NtpTrustedTime.TimeResult ntpResult = time.getCachedTimeResult();
+ if (ntpResult != null) {
+ return ntpResult.currentTimeMillis();
} else {
throw new ParcelableException(new DateTimeException("Missing NTP fix"));
}
diff --git a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
new file mode 100644
index 0000000..31cd5d5
--- /dev/null
+++ b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
@@ -0,0 +1,258 @@
+/*
+ * 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.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothProfile.ServiceListener;
+import android.content.Context;
+import android.content.res.Resources;
+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 android.widget.Toast;
+
+import com.android.internal.R;
+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.
+ */
+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 AirplaneModeHelper 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(AirplaneModeHelper 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
+ void handleAirplaneModeChange() {
+ if (shouldSkipAirplaneModeChange()) {
+ Log.i(TAG, "Ignore airplane mode change");
+ // We have to store Bluetooth state here, so if user turns off Bluetooth
+ // after airplane mode is turned on, we don't forget to turn on Bluetooth
+ // when airplane mode turns off.
+ mAirplaneHelper.setSettingsInt(Settings.Global.BLUETOOTH_ON,
+ BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
+ if (shouldPopToast()) {
+ mAirplaneHelper.showToastMessage();
+ }
+ return;
+ }
+ mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager);
+ }
+
+ @VisibleForTesting
+ boolean shouldSkipAirplaneModeChange() {
+ if (mAirplaneHelper == null) {
+ return false;
+ }
+ if (!mAirplaneHelper.isBluetoothOn() || !mAirplaneHelper.isAirplaneModeOn()
+ || !mAirplaneHelper.isA2dpOrHearingAidConnected()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Helper class that handles callout and callback methods without
+ * complex logic.
+ */
+ @VisibleForTesting
+ public static class AirplaneModeHelper {
+ private volatile BluetoothA2dp mA2dp;
+ private volatile BluetoothHearingAid mHearingAid;
+ private final BluetoothAdapter mAdapter;
+ private final Context mContext;
+
+ AirplaneModeHelper(Context context) {
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mContext = context;
+
+ mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP);
+ mAdapter.getProfileProxy(mContext, mProfileServiceListener,
+ BluetoothProfile.HEARING_AID);
+ }
+
+ 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;
+ 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;
+ default:
+ break;
+ }
+ }
+ };
+
+ @VisibleForTesting
+ public boolean isA2dpOrHearingAidConnected() {
+ return isA2dpConnected() || isHearingAidConnected();
+ }
+
+ @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
+ 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;
+ }
+ };
+}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index cdfd310..fa8eda5 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -68,6 +68,7 @@
import android.util.StatsLog;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.server.pm.UserRestrictionsUtils;
@@ -138,7 +139,8 @@
// Bluetooth persisted setting is on
// but Airplane mode will affect Bluetooth state at start up
// and Airplane mode will have higher priority.
- private static final int BLUETOOTH_ON_AIRPLANE = 2;
+ @VisibleForTesting
+ static final int BLUETOOTH_ON_AIRPLANE = 2;
private static final int SERVICE_IBLUETOOTH = 1;
private static final int SERVICE_IBLUETOOTHGATT = 2;
@@ -159,6 +161,8 @@
private boolean mBinding;
private boolean mUnbinding;
+ private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
+
// used inside handler thread
private boolean mQuietEnable = false;
private boolean mEnable;
@@ -257,68 +261,65 @@
}
};
- private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
- @Override
- public void onChange(boolean unused) {
- 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());
-
+ public void onAirplaneModeChanged() {
+ synchronized (this) {
+ if (isBluetoothPersistedStateOn()) {
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();
- 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());
+ 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();
+ 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
@@ -430,9 +431,8 @@
Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
if (airplaneModeRadios == null || airplaneModeRadios.contains(
Settings.Global.RADIO_BLUETOOTH)) {
- mContentResolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
- mAirplaneModeObserver);
+ mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
+ this, IoThread.get().getLooper(), context);
}
int systemUiUid = -1;
@@ -478,6 +478,17 @@
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
*/
@@ -954,10 +965,12 @@
}
synchronized (mReceiver) {
- if (persist) {
- persistBluetoothSetting(BLUETOOTH_OFF);
+ if (!isBluetoothPersistedStateOnAirplane()) {
+ if (persist) {
+ persistBluetoothSetting(BLUETOOTH_OFF);
+ }
+ mEnableExternal = false;
}
- mEnableExternal = false;
sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
packageName);
}
@@ -1185,6 +1198,10 @@
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
mHandler.sendMessage(getMsg);
}
+ if (mBluetoothAirplaneModeListener != null) {
+ mBluetoothAirplaneModeListener.start(
+ new BluetoothAirplaneModeListener.AirplaneModeHelper(mContext));
+ }
}
/**
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index bb78ace..76c119d 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -39,6 +39,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.uidRulesToString;
@@ -86,14 +87,14 @@
import android.net.NattSocketKeepalive;
import android.net.Network;
import android.net.NetworkAgent;
+import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
-import android.net.NetworkFactory;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
-import android.net.NetworkMisc;
import android.net.NetworkMonitorManager;
import android.net.NetworkPolicyManager;
+import android.net.NetworkProvider;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkScore;
@@ -221,6 +222,7 @@
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* @hide
@@ -364,10 +366,10 @@
private static final int EVENT_PROXY_HAS_CHANGED = 16;
/**
- * used internally when registering NetworkFactories
- * obj = NetworkFactoryInfo
+ * used internally when registering NetworkProviders
+ * obj = NetworkProviderInfo
*/
- private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
+ private static final int EVENT_REGISTER_NETWORK_PROVIDER = 17;
/**
* used internally when registering NetworkAgents
@@ -403,10 +405,10 @@
private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
/**
- * used internally when registering NetworkFactories
+ * used internally when registering NetworkProviders
* obj = Messenger
*/
- private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
+ private static final int EVENT_UNREGISTER_NETWORK_PROVIDER = 23;
/**
* used internally to expire a wakelock when transitioning
@@ -597,6 +599,10 @@
// sequence number of NetworkRequests
private int mNextNetworkRequestId = 1;
+ // Sequence number for NetworkProvider IDs.
+ private final AtomicInteger mNextNetworkProviderId = new AtomicInteger(
+ NetworkProvider.FIRST_PROVIDER_ID);
+
// NetworkRequest activity String log entries.
private static final int MAX_NETWORK_REQUEST_LOGS = 20;
private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
@@ -1567,48 +1573,49 @@
enforceAccessPermission();
final int uid = Binder.getCallingUid();
NetworkState state = getUnfilteredActiveNetworkState(uid);
- return state.linkProperties;
+ if (state.linkProperties == null) return null;
+ return linkPropertiesRestrictedForCallerPermissions(state.linkProperties,
+ Binder.getCallingPid(), uid);
}
@Override
public LinkProperties getLinkPropertiesForType(int networkType) {
enforceAccessPermission();
NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
- if (nai != null) {
- synchronized (nai) {
- return new LinkProperties(nai.linkProperties);
- }
- }
- return null;
+ final LinkProperties lp = getLinkProperties(nai);
+ if (lp == null) return null;
+ return linkPropertiesRestrictedForCallerPermissions(
+ lp, Binder.getCallingPid(), Binder.getCallingUid());
}
// TODO - this should be ALL networks
@Override
public LinkProperties getLinkProperties(Network network) {
enforceAccessPermission();
- return getLinkProperties(getNetworkAgentInfoForNetwork(network));
+ final LinkProperties lp = getLinkProperties(getNetworkAgentInfoForNetwork(network));
+ if (lp == null) return null;
+ return linkPropertiesRestrictedForCallerPermissions(
+ lp, Binder.getCallingPid(), Binder.getCallingUid());
}
- private LinkProperties getLinkProperties(NetworkAgentInfo nai) {
+ @Nullable
+ private LinkProperties getLinkProperties(@Nullable NetworkAgentInfo nai) {
if (nai == null) {
return null;
}
synchronized (nai) {
- return new LinkProperties(nai.linkProperties);
+ return nai.linkProperties;
}
}
private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
- if (nai != null) {
- synchronized (nai) {
- if (nai.networkCapabilities != null) {
- return networkCapabilitiesRestrictedForCallerPermissions(
- nai.networkCapabilities,
- Binder.getCallingPid(), Binder.getCallingUid());
- }
- }
+ if (nai == null) return null;
+ synchronized (nai) {
+ if (nai.networkCapabilities == null) return null;
+ return networkCapabilitiesRestrictedForCallerPermissions(
+ nai.networkCapabilities,
+ Binder.getCallingPid(), Binder.getCallingUid());
}
- return null;
}
@Override
@@ -1630,6 +1637,29 @@
return newNc;
}
+ private LinkProperties linkPropertiesRestrictedForCallerPermissions(
+ LinkProperties lp, int callerPid, int callerUid) {
+ if (lp == null) return new LinkProperties();
+
+ // Only do a permission check if sanitization is needed, to avoid unnecessary binder calls.
+ final boolean needsSanitization =
+ (lp.getCaptivePortalApiUrl() != null || lp.getCaptivePortalData() != null);
+ if (!needsSanitization) {
+ return new LinkProperties(lp);
+ }
+
+ if (checkSettingsPermission(callerPid, callerUid)) {
+ return lp.makeSensitiveFieldsParcelingCopy();
+ }
+
+ final LinkProperties newLp = new LinkProperties(lp);
+ // Sensitive fields would not be parceled anyway, but sanitize for consistency before the
+ // object gets parceled.
+ newLp.setCaptivePortalApiUrl(null);
+ newLp.setCaptivePortalData(null);
+ return newLp;
+ }
+
private void restrictRequestUidsForCaller(NetworkCapabilities nc) {
if (!checkSettingsPermission()) {
nc.setSingleUid(Binder.getCallingUid());
@@ -2381,9 +2411,9 @@
return;
}
- pw.print("NetworkFactories for:");
- for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- pw.print(" " + nfi.name);
+ pw.print("NetworkProviders for:");
+ for (NetworkProviderInfo npi : mNetworkProviderInfos.values()) {
+ pw.print(" " + npi.name);
}
pw.println();
pw.println();
@@ -2618,8 +2648,8 @@
if (nai.everConnected) {
loge("ERROR: cannot call explicitlySelected on already-connected network");
}
- nai.networkMisc.explicitlySelected = toBool(msg.arg1);
- nai.networkMisc.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2);
+ nai.networkAgentConfig.explicitlySelected = toBool(msg.arg1);
+ nai.networkAgentConfig.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2);
// Mark the network as temporarily accepting partial connectivity so that it
// will be validated (and possibly become default) even if it only provides
// partial internet access. Note that if user connects to partial connectivity
@@ -2627,7 +2657,7 @@
// out of wifi coverage) and if the same wifi is available again, the device
// will auto connect to this wifi even though the wifi has "no internet".
// TODO: Evaluate using a separate setting in IpMemoryStore.
- nai.networkMisc.acceptPartialConnectivity = toBool(msg.arg2);
+ nai.networkAgentConfig.acceptPartialConnectivity = toBool(msg.arg2);
break;
}
case NetworkAgent.EVENT_SOCKET_KEEPALIVE: {
@@ -2659,10 +2689,10 @@
}
// Only show the notification when the private DNS is broken and the
// PRIVATE_DNS_BROKEN notification hasn't shown since last valid.
- if (privateDnsBroken && !nai.networkMisc.hasShownBroken) {
+ if (privateDnsBroken && !nai.networkAgentConfig.hasShownBroken) {
showNetworkNotification(nai, NotificationType.PRIVATE_DNS_BROKEN);
}
- nai.networkMisc.hasShownBroken = privateDnsBroken;
+ nai.networkAgentConfig.hasShownBroken = privateDnsBroken;
} else if (nai.networkCapabilities.isPrivateDnsBroken()) {
// If probePrivateDnsCompleted is false but nai.networkCapabilities says
// private DNS is broken, it means this network is being reevaluated.
@@ -2672,7 +2702,7 @@
nai.networkCapabilities.setPrivateDnsBroken(false);
final int oldScore = nai.getCurrentScore();
updateCapabilities(oldScore, nai, nai.networkCapabilities);
- nai.networkMisc.hasShownBroken = false;
+ nai.networkAgentConfig.hasShownBroken = false;
}
break;
}
@@ -2714,7 +2744,7 @@
nai.lastValidated = valid;
nai.everValidated |= valid;
updateCapabilities(oldScore, nai, nai.networkCapabilities);
- // If score has changed, rebroadcast to NetworkFactories. b/17726566
+ // If score has changed, rebroadcast to NetworkProviders. b/17726566
if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
if (valid) {
handleFreshlyValidatedNetwork(nai);
@@ -2731,7 +2761,7 @@
// If network becomes valid, the hasShownBroken should be reset for
// that network so that the notification will be fired when the private
// DNS is broken again.
- nai.networkMisc.hasShownBroken = false;
+ nai.networkAgentConfig.hasShownBroken = false;
}
} else if (partialConnectivityChanged) {
updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
@@ -2790,9 +2820,10 @@
loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
break;
}
- if (!nai.networkMisc.provisioningNotificationDisabled) {
+ if (!nai.networkAgentConfig.provisioningNotificationDisabled) {
mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null,
- (PendingIntent) msg.obj, nai.networkMisc.explicitlySelected);
+ (PendingIntent) msg.obj,
+ nai.networkAgentConfig.explicitlySelected);
}
}
break;
@@ -2829,25 +2860,11 @@
return true;
}
- private boolean maybeHandleNetworkFactoryMessage(Message msg) {
- switch (msg.what) {
- default:
- return false;
- case NetworkFactory.EVENT_UNFULFILLABLE_REQUEST: {
- handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.sendingUid,
- /* callOnUnavailable */ true);
- break;
- }
- }
- return true;
- }
-
@Override
public void handleMessage(Message msg) {
if (!maybeHandleAsyncChannelMessage(msg)
&& !maybeHandleNetworkMonitorMessage(msg)
- && !maybeHandleNetworkAgentInfoMessage(msg)
- && !maybeHandleNetworkFactoryMessage(msg)) {
+ && !maybeHandleNetworkAgentInfoMessage(msg)) {
maybeHandleNetworkAgentMessage(msg);
}
}
@@ -3018,32 +3035,16 @@
private void handleAsyncChannelHalfConnect(Message msg) {
ensureRunningOnConnectivityServiceThread();
final AsyncChannel ac = (AsyncChannel) msg.obj;
- if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
+ if (mNetworkProviderInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (VDBG) log("NetworkFactory connected");
// Finish setting up the full connection
- mNetworkFactoryInfos.get(msg.replyTo).asyncChannel.sendMessage(
- AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
- // A network factory has connected. Send it all current NetworkRequests.
- for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (nri.request.isListen()) continue;
- ensureRunningOnConnectivityServiceThread();
- NetworkAgentInfo nai = nri.mSatisfier;
- final int score;
- final int serial;
- if (nai != null) {
- score = nai.getCurrentScore();
- serial = nai.factorySerialNumber;
- } else {
- score = 0;
- serial = NetworkFactory.SerialNumber.NONE;
- }
- ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, serial,
- nri.request);
- }
+ NetworkProviderInfo npi = mNetworkProviderInfos.get(msg.replyTo);
+ npi.completeConnection();
+ sendAllRequestsToProvider(npi);
} else {
loge("Error connecting NetworkFactory");
- mNetworkFactoryInfos.remove(msg.obj);
+ mNetworkProviderInfos.remove(msg.obj);
}
} else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
@@ -3075,8 +3076,8 @@
if (nai != null) {
disconnectAndDestroyNetwork(nai);
} else {
- NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
- if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name);
+ NetworkProviderInfo npi = mNetworkProviderInfos.remove(msg.replyTo);
+ if (DBG && npi != null) log("unregisterNetworkFactory for " + npi.name);
}
}
@@ -3159,7 +3160,7 @@
// ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
// after we've rematched networks with requests which should make a potential
// fallback network the default or requested a new network from the
- // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
+ // NetworkProviders, so network traffic isn't interrupted for an unnecessarily
// long time.
destroyNativeNetwork(nai);
mDnsManager.removeNetwork(nai.network);
@@ -3172,8 +3173,8 @@
// This should never fail. Specifying an already in use NetID will cause failure.
if (networkAgent.isVPN()) {
mNetd.networkCreateVpn(networkAgent.network.netId,
- (networkAgent.networkMisc == null
- || !networkAgent.networkMisc.allowBypass));
+ (networkAgent.networkAgentConfig == null
+ || !networkAgent.networkAgentConfig.allowBypass));
} else {
mNetd.networkCreatePhysical(networkAgent.network.netId,
getNetworkPermission(networkAgent.networkCapabilities));
@@ -3422,9 +3423,8 @@
}
}
- for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
- nri.request);
+ for (NetworkProviderInfo npi : mNetworkProviderInfos.values()) {
+ npi.cancelRequest(nri.request);
}
} else {
// listens don't have a singular affectedNetwork. Check all networks to see
@@ -3474,16 +3474,16 @@
return;
}
- if (!nai.networkMisc.explicitlySelected) {
+ if (!nai.networkAgentConfig.explicitlySelected) {
Slog.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network");
}
- if (accept != nai.networkMisc.acceptUnvalidated) {
- nai.networkMisc.acceptUnvalidated = accept;
+ if (accept != nai.networkAgentConfig.acceptUnvalidated) {
+ nai.networkAgentConfig.acceptUnvalidated = accept;
// If network becomes partial connectivity and user already accepted to use this
// network, we should respect the user's option and don't need to popup the
// PARTIAL_CONNECTIVITY notification to user again.
- nai.networkMisc.acceptPartialConnectivity = accept;
+ nai.networkAgentConfig.acceptPartialConnectivity = accept;
rematchAllNetworksAndRequests();
sendUpdatedScoreToFactories(nai);
}
@@ -3520,8 +3520,8 @@
return;
}
- if (accept != nai.networkMisc.acceptPartialConnectivity) {
- nai.networkMisc.acceptPartialConnectivity = accept;
+ if (accept != nai.networkAgentConfig.acceptPartialConnectivity) {
+ nai.networkAgentConfig.acceptPartialConnectivity = accept;
}
// TODO: Use the current design or save the user choice into IpMemoryStore.
@@ -3619,17 +3619,32 @@
enforceSettingsPermission();
}
- // getNetworkAgentInfoForNetwork is thread-safe
- final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(mNetwork);
- if (nai == null) return;
-
- // nai.networkMonitor() is thread-safe
- final NetworkMonitorManager nm = nai.networkMonitor();
+ final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork);
if (nm == null) return;
nm.notifyCaptivePortalAppFinished(response);
}
@Override
+ public void appRequest(final int request) {
+ final NetworkMonitorManager nm = getNetworkMonitorManager(mNetwork);
+ if (nm == null) return;
+
+ if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) {
+ nm.forceReevaluation(Binder.getCallingUid());
+ }
+ }
+
+ @Nullable
+ private NetworkMonitorManager getNetworkMonitorManager(final Network network) {
+ // getNetworkAgentInfoForNetwork is thread-safe
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
+ if (nai == null) return null;
+
+ // nai.networkMonitor() is thread-safe
+ return nai.networkMonitor();
+ }
+
+ @Override
public void logEvent(int eventId, String packageName) {
enforceSettingsPermission();
@@ -3731,7 +3746,7 @@
action = ConnectivityManager.ACTION_PROMPT_PARTIAL_CONNECTIVITY;
// Don't bother the user with a high-priority notification if the network was not
// explicitly selected by the user.
- highPriority = nai.networkMisc.explicitlySelected;
+ highPriority = nai.networkAgentConfig.explicitlySelected;
break;
default:
Slog.wtf(TAG, "Unknown notification type " + type);
@@ -3764,14 +3779,15 @@
// automatically connects to a network that has partial Internet access, the user will
// always be able to use it, either because they've already chosen "don't ask again" or
// because we have prompt them.
- if (nai.partialConnectivity && !nai.networkMisc.acceptPartialConnectivity) {
+ if (nai.partialConnectivity && !nai.networkAgentConfig.acceptPartialConnectivity) {
return true;
}
// If a network has no Internet access, only prompt if the network was explicitly selected
// and if the user has not already told us to use the network regardless of whether it
// validated or not.
- if (nai.networkMisc.explicitlySelected && !nai.networkMisc.acceptUnvalidated) {
+ if (nai.networkAgentConfig.explicitlySelected
+ && !nai.networkAgentConfig.acceptUnvalidated) {
return true;
}
@@ -3859,12 +3875,12 @@
handleApplyDefaultProxy((ProxyInfo)msg.obj);
break;
}
- case EVENT_REGISTER_NETWORK_FACTORY: {
- handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
+ case EVENT_REGISTER_NETWORK_PROVIDER: {
+ handleRegisterNetworkProvider((NetworkProviderInfo) msg.obj);
break;
}
- case EVENT_UNREGISTER_NETWORK_FACTORY: {
- handleUnregisterNetworkFactory((Messenger)msg.obj);
+ case EVENT_UNREGISTER_NETWORK_PROVIDER: {
+ handleUnregisterNetworkProvider((Messenger) msg.obj);
break;
}
case EVENT_REGISTER_NETWORK_AGENT: {
@@ -4909,7 +4925,7 @@
}
};
- private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos = new HashMap<>();
+ private final HashMap<Messenger, NetworkProviderInfo> mNetworkProviderInfos = new HashMap<>();
private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests = new HashMap<>();
private static final int MAX_NETWORK_REQUESTS_PER_UID = 100;
@@ -4917,18 +4933,73 @@
@GuardedBy("mUidToNetworkRequestCount")
private final SparseIntArray mUidToNetworkRequestCount = new SparseIntArray();
- private static class NetworkFactoryInfo {
+ private static class NetworkProviderInfo {
public final String name;
public final Messenger messenger;
- public final AsyncChannel asyncChannel;
- public final int factorySerialNumber;
+ private final AsyncChannel mAsyncChannel;
+ private final IBinder.DeathRecipient mDeathRecipient;
+ public final int providerId;
- NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
- int factorySerialNumber) {
+ NetworkProviderInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
+ int providerId, IBinder.DeathRecipient deathRecipient) {
this.name = name;
this.messenger = messenger;
- this.asyncChannel = asyncChannel;
- this.factorySerialNumber = factorySerialNumber;
+ this.providerId = providerId;
+ mAsyncChannel = asyncChannel;
+ mDeathRecipient = deathRecipient;
+
+ if ((mAsyncChannel == null) == (mDeathRecipient == null)) {
+ throw new AssertionError("Must pass exactly one of asyncChannel or deathRecipient");
+ }
+ }
+
+ boolean isLegacyNetworkFactory() {
+ return mAsyncChannel != null;
+ }
+
+ void sendMessageToNetworkProvider(int what, int arg1, int arg2, Object obj) {
+ try {
+ messenger.send(Message.obtain(null /* handler */, what, arg1, arg2, obj));
+ } catch (RemoteException e) {
+ // Remote process died. Ignore; the death recipient will remove this
+ // NetworkProviderInfo from mNetworkProviderInfos.
+ }
+ }
+
+ void requestNetwork(NetworkRequest request, int score, int servingProviderId) {
+ if (isLegacyNetworkFactory()) {
+ mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
+ servingProviderId, request);
+ } else {
+ sendMessageToNetworkProvider(NetworkProvider.CMD_REQUEST_NETWORK, score,
+ servingProviderId, request);
+ }
+ }
+
+ void cancelRequest(NetworkRequest request) {
+ if (isLegacyNetworkFactory()) {
+ mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST, request);
+ } else {
+ sendMessageToNetworkProvider(NetworkProvider.CMD_CANCEL_REQUEST, 0, 0, request);
+ }
+ }
+
+ void connect(Context context, Handler handler) {
+ if (isLegacyNetworkFactory()) {
+ mAsyncChannel.connect(context, handler, messenger);
+ } else {
+ try {
+ messenger.getBinder().linkToDeath(mDeathRecipient, 0);
+ } catch (RemoteException e) {
+ mDeathRecipient.binderDied();
+ }
+ }
+ }
+
+ void completeConnection() {
+ if (isLegacyNetworkFactory()) {
+ mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+ }
}
}
@@ -5299,6 +5370,11 @@
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
}
+ /** Returns the next Network provider ID. */
+ public final int nextNetworkProviderId() {
+ return mNextNetworkProviderId.getAndIncrement();
+ }
+
@Override
public void releaseNetworkRequest(NetworkRequest networkRequest) {
ensureNetworkRequestHasType(networkRequest);
@@ -5309,31 +5385,65 @@
@Override
public int registerNetworkFactory(Messenger messenger, String name) {
enforceNetworkFactoryPermission();
- NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(),
- NetworkFactory.SerialNumber.nextSerialNumber());
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
- return nfi.factorySerialNumber;
+ NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger, new AsyncChannel(),
+ nextNetworkProviderId(), null /* deathRecipient */);
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_PROVIDER, npi));
+ return npi.providerId;
}
- private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
- if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
- mNetworkFactoryInfos.put(nfi.messenger, nfi);
- nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
+ private void handleRegisterNetworkProvider(NetworkProviderInfo npi) {
+ if (mNetworkProviderInfos.containsKey(npi.messenger)) {
+ // Avoid creating duplicates. even if an app makes a direct AIDL call.
+ // This will never happen if an app calls ConnectivityManager#registerNetworkProvider,
+ // as that will throw if a duplicate provider is registered.
+ Slog.e(TAG, "Attempt to register existing NetworkProviderInfo "
+ + mNetworkProviderInfos.get(npi.messenger).name);
+ return;
+ }
+
+ if (DBG) log("Got NetworkProvider Messenger for " + npi.name);
+ mNetworkProviderInfos.put(npi.messenger, npi);
+ npi.connect(mContext, mTrackerHandler);
+ if (!npi.isLegacyNetworkFactory()) {
+ // Legacy NetworkFactories get their requests when their AsyncChannel connects.
+ sendAllRequestsToProvider(npi);
+ }
+ }
+
+ @Override
+ public int registerNetworkProvider(Messenger messenger, String name) {
+ enforceNetworkFactoryPermission();
+ NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger,
+ null /* asyncChannel */, nextNetworkProviderId(),
+ () -> unregisterNetworkProvider(messenger));
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_PROVIDER, npi));
+ return npi.providerId;
+ }
+
+ @Override
+ public void unregisterNetworkProvider(Messenger messenger) {
+ enforceNetworkFactoryPermission();
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger));
}
@Override
public void unregisterNetworkFactory(Messenger messenger) {
- enforceNetworkFactoryPermission();
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
+ unregisterNetworkProvider(messenger);
}
- private void handleUnregisterNetworkFactory(Messenger messenger) {
- NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
- if (nfi == null) {
- loge("Failed to find Messenger in unregisterNetworkFactory");
+ private void handleUnregisterNetworkProvider(Messenger messenger) {
+ NetworkProviderInfo npi = mNetworkProviderInfos.remove(messenger);
+ if (npi == null) {
+ loge("Failed to find Messenger in unregisterNetworkProvider");
return;
}
- if (DBG) log("unregisterNetworkFactory for " + nfi.name);
+ if (DBG) log("unregisterNetworkProvider for " + npi.name);
+ }
+
+ @Override
+ public void declareNetworkRequestUnfulfillable(NetworkRequest request) {
+ enforceNetworkFactoryPermission();
+ mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true));
}
// NOTE: Accessed on multiple threads, must be synchronized on itself.
@@ -5397,11 +5507,14 @@
// changes that would conflict throughout the automerger graph. Having this method temporarily
// helps with the process of going through with all these dependent changes across the entire
// tree.
- public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
+ /**
+ * Register a new agent. {@see #registerNetworkAgent} below.
+ */
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
- int currentScore, NetworkMisc networkMisc) {
+ int currentScore, NetworkAgentConfig networkAgentConfig) {
return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities,
- currentScore, networkMisc, NetworkFactory.SerialNumber.NONE);
+ currentScore, networkAgentConfig, NetworkProvider.ID_NONE);
}
/**
@@ -5416,12 +5529,13 @@
* later : see {@link #updateCapabilities}.
* @param currentScore the initial score of the network. See
* {@link NetworkAgentInfo#getCurrentScore}.
- * @param networkMisc metadata about the network. This is never updated.
- * @param factorySerialNumber the serial number of the factory owning this NetworkAgent.
+ * @param networkAgentConfig metadata about the network. This is never updated.
+ * @param providerId the ID of the provider owning this NetworkAgent.
+ * @return the network created for this agent.
*/
- public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
- int currentScore, NetworkMisc networkMisc, int factorySerialNumber) {
+ int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {
enforceNetworkFactoryPermission();
LinkProperties lp = new LinkProperties(linkProperties);
@@ -5433,8 +5547,8 @@
ns.putIntExtension(NetworkScore.LEGACY_SCORE, currentScore);
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
- ns, mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd,
- mDnsResolver, mNMS, factorySerialNumber);
+ ns, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), this,
+ mNetd, mDnsResolver, mNMS, providerId);
// Make sure the network capabilities reflect what the agent info says.
nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc));
final String extraInfo = networkInfo.getExtraInfo();
@@ -5452,7 +5566,7 @@
// If the network disconnects or sends any other event before that, messages are deferred by
// NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the
// registration.
- return nai.network.netId;
+ return nai.network;
}
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
@@ -5704,6 +5818,19 @@
return INetd.PERMISSION_NONE;
}
+ private void updateNetworkPermissions(@NonNull final NetworkAgentInfo nai,
+ @NonNull final NetworkCapabilities newNc) {
+ final int oldPermission = getNetworkPermission(nai.networkCapabilities);
+ final int newPermission = getNetworkPermission(newNc);
+ if (oldPermission != newPermission && nai.created && !nai.isVPN()) {
+ try {
+ mNMS.setNetworkPermission(nai.network.netId, newPermission);
+ } catch (RemoteException e) {
+ loge("Exception in setNetworkPermission: " + e);
+ }
+ }
+ }
+
/**
* Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are
* maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal,
@@ -5713,7 +5840,7 @@
// Once a NetworkAgent is connected, complain if some immutable capabilities are removed.
// Don't complain for VPNs since they're not driven by requests and there is no risk of
// causing a connect/teardown loop.
- // TODO: remove this altogether and make it the responsibility of the NetworkFactories to
+ // TODO: remove this altogether and make it the responsibility of the NetworkProviders to
// avoid connect/teardown loops.
if (nai.everConnected &&
!nai.isVPN() &&
@@ -5744,11 +5871,6 @@
} else {
newNc.addCapability(NET_CAPABILITY_FOREGROUND);
}
- if (nai.isSuspended()) {
- newNc.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
- } else {
- newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
- }
if (nai.partialConnectivity) {
newNc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
} else {
@@ -5756,6 +5878,12 @@
}
newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken());
+ // TODO : remove this once all factories are updated to send NOT_SUSPENDED and NOT_ROAMING
+ if (!newNc.hasTransport(TRANSPORT_CELLULAR)) {
+ newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ newNc.addCapability(NET_CAPABILITY_NOT_ROAMING);
+ }
+
return newNc;
}
@@ -5775,21 +5903,11 @@
* @param nai the network having its capabilities updated.
* @param nc the new network capabilities.
*/
- private void updateCapabilities(int oldScore, NetworkAgentInfo nai, NetworkCapabilities nc) {
+ private void updateCapabilities(final int oldScore, @NonNull final NetworkAgentInfo nai,
+ @NonNull final NetworkCapabilities nc) {
NetworkCapabilities newNc = mixInCapabilities(nai, nc);
-
if (Objects.equals(nai.networkCapabilities, newNc)) return;
-
- final int oldPermission = getNetworkPermission(nai.networkCapabilities);
- final int newPermission = getNetworkPermission(newNc);
- if (oldPermission != newPermission && nai.created && !nai.isVPN()) {
- try {
- mNMS.setNetworkPermission(nai.network.netId, newPermission);
- } catch (RemoteException e) {
- loge("Exception in setNetworkPermission: " + e);
- }
- }
-
+ updateNetworkPermissions(nai, newNc);
final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc);
updateUids(nai, prevNc, newNc);
@@ -5800,6 +5918,19 @@
// on this network. We might have been called by rematchNetworkAndRequests when a
// network changed foreground state.
processListenRequests(nai);
+ final boolean prevSuspended = !prevNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ final boolean suspended = !newNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ final boolean prevRoaming = !prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+ final boolean roaming = !newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+ if (prevSuspended != suspended || prevRoaming != roaming) {
+ // TODO (b/73132094) : remove this call once the few users of onSuspended and
+ // onResumed have been removed.
+ notifyNetworkCallbacks(nai, suspended ? ConnectivityManager.CALLBACK_SUSPENDED
+ : ConnectivityManager.CALLBACK_RESUMED);
+ // updateNetworkInfo will mix in the suspended info from the capabilities and
+ // take appropriate action for the network having possibly changed state.
+ updateNetworkInfo(nai, nai.networkInfo);
+ }
} else {
// If the requestable capabilities have changed or the score changed, we can't have been
// called by rematchNetworkAndRequests, so it's safe to start a rematch.
@@ -5807,6 +5938,9 @@
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
+ // TODO : static analysis indicates that prevNc can't be null here (getAndSetNetworkCaps
+ // never returns null), so mark the relevant members and functions in nai as @NonNull and
+ // remove this test
if (prevNc != null) {
final boolean oldMetered = prevNc.isMetered();
final boolean newMetered = newNc.isMetered();
@@ -5855,7 +5989,7 @@
LinkProperties lp) {
if (nc == null || lp == null) return false;
return nai.isVPN()
- && !nai.networkMisc.allowBypass
+ && !nai.networkAgentConfig.allowBypass
&& nc.getEstablishingVpnAppUid() != Process.SYSTEM_UID
&& lp.getInterfaceName() != null
&& (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute());
@@ -5953,9 +6087,27 @@
if (VDBG || DDBG){
log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
}
- for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
- serial, networkRequest);
+ for (NetworkProviderInfo npi : mNetworkProviderInfos.values()) {
+ npi.requestNetwork(networkRequest, score, serial);
+ }
+ }
+
+ /** Sends all current NetworkRequests to the specified factory. */
+ private void sendAllRequestsToProvider(NetworkProviderInfo npi) {
+ ensureRunningOnConnectivityServiceThread();
+ for (NetworkRequestInfo nri : mNetworkRequests.values()) {
+ if (nri.request.isListen()) continue;
+ NetworkAgentInfo nai = nri.mSatisfier;
+ final int score;
+ final int serial;
+ if (nai != null) {
+ score = nai.getCurrentScore();
+ serial = nai.factorySerialNumber;
+ } else {
+ score = 0;
+ serial = NetworkProvider.ID_NONE;
+ }
+ npi.requestNetwork(nri.request, score, serial);
}
}
@@ -6010,7 +6162,8 @@
case ConnectivityManager.CALLBACK_AVAILABLE: {
putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions(
networkAgent.networkCapabilities, nri.mPid, nri.mUid));
- putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
+ putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
+ networkAgent.linkProperties, nri.mPid, nri.mUid));
// For this notification, arg1 contains the blocked status.
msg.arg1 = arg1;
break;
@@ -6027,7 +6180,8 @@
break;
}
case ConnectivityManager.CALLBACK_IP_CHANGED: {
- putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
+ putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
+ networkAgent.linkProperties, nri.mPid, nri.mUid));
break;
}
case ConnectivityManager.CALLBACK_BLK_CHANGED: {
@@ -6136,6 +6290,30 @@
}
}
+ // An accumulator class to gather the list of changes that result from a rematch.
+ // TODO : enrich to represent an entire set of changes to apply.
+ private static class NetworkReassignment {
+ static class NetworkBgStatePair {
+ @NonNull final NetworkAgentInfo mNetwork;
+ final boolean mOldBackground;
+ NetworkBgStatePair(@NonNull final NetworkAgentInfo network,
+ final boolean oldBackground) {
+ mNetwork = network;
+ mOldBackground = oldBackground;
+ }
+ }
+
+ @NonNull private final Set<NetworkBgStatePair> mRematchedNetworks = new ArraySet<>();
+
+ @NonNull Iterable<NetworkBgStatePair> getRematchedNetworks() {
+ return mRematchedNetworks;
+ }
+
+ void addRematchedNetwork(@NonNull final NetworkBgStatePair network) {
+ mRematchedNetworks.add(network);
+ }
+ }
+
private ArrayMap<NetworkRequestInfo, NetworkAgentInfo> computeRequestReassignmentForNetwork(
@NonNull final NetworkAgentInfo newNetwork) {
final int score = newNetwork.getCurrentScore();
@@ -6181,8 +6359,8 @@
// needed. A network is needed if it is the best network for
// one or more NetworkRequests, or if it is a VPN.
//
- // - Tears down newNetwork if it just became validated
- // but turns out to be unneeded.
+ // - Writes into the passed reassignment object all changes that should be done for
+ // rematching this network with all requests, to be applied later.
//
// NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
// it does not remove NetworkRequests that other Networks could better satisfy.
@@ -6190,15 +6368,22 @@
// This function should be used when possible instead of {@code rematchAllNetworksAndRequests}
// as it performs better by a factor of the number of Networks.
//
+ // TODO : stop writing to the passed reassignment. This is temporarily more useful, but
+ // it's unidiomatic Java and it's hard to read.
+ //
+ // @param changes a currently-building list of changes to write to
// @param newNetwork is the network to be matched against NetworkRequests.
// @param now the time the rematch starts, as returned by SystemClock.elapsedRealtime();
- private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, long now) {
+ private void rematchNetworkAndRequests(@NonNull final NetworkReassignment changes,
+ @NonNull final NetworkAgentInfo newNetwork, final long now) {
ensureRunningOnConnectivityServiceThread();
if (!newNetwork.everConnected) return;
boolean isNewDefault = false;
NetworkAgentInfo oldDefaultNetwork = null;
- final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork();
+ changes.addRematchedNetwork(new NetworkReassignment.NetworkBgStatePair(newNetwork,
+ newNetwork.isBackgroundNetwork()));
+
final int score = newNetwork.getCurrentScore();
if (VDBG || DDBG) log("rematching " + newNetwork.name());
@@ -6236,11 +6421,11 @@
Slog.wtf(TAG, "BUG: " + newSatisfier.name() + " already has " + nri.request);
}
addedRequests.add(nri);
- // Tell NetworkFactories about the new score, so they can stop
+ // Tell NetworkProviders about the new score, so they can stop
// trying to connect if they know they cannot match it.
// TODO - this could get expensive if we have a lot of requests for this
// network. Think about if there is a way to reduce this. Push
- // netid->request mapping to each factory?
+ // netid->request mapping to each provider?
sendUpdatedScoreToFactories(nri.request, newSatisfier);
if (isDefaultRequest(nri)) {
isNewDefault = true;
@@ -6269,7 +6454,7 @@
} else {
Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " +
newNetwork.name() +
- " without updating mSatisfier or factories!");
+ " without updating mSatisfier or providers!");
}
// TODO: Technically, sending CALLBACK_LOST here is
// incorrect if there is a replacement network currently
@@ -6301,39 +6486,12 @@
if (newNetwork.getCurrentScore() != score) {
Slog.wtf(TAG, String.format(
"BUG: %s changed score during rematch: %d -> %d",
- newNetwork.name(), score, newNetwork.getCurrentScore()));
+ newNetwork.name(), score, newNetwork.getCurrentScore()));
}
// Notify requested networks are available after the default net is switched, but
// before LegacyTypeTracker sends legacy broadcasts
for (NetworkRequestInfo nri : addedRequests) notifyNetworkAvailable(newNetwork, nri);
-
- // Finally, process listen requests and update capabilities if the background state has
- // changed for this network. For consistency with previous behavior, send onLost callbacks
- // before onAvailable.
- processNewlyLostListenRequests(newNetwork);
-
- // Maybe the network changed background states. Update its capabilities.
- final boolean backgroundChanged = wasBackgroundNetwork != newNetwork.isBackgroundNetwork();
- if (backgroundChanged) {
- final NetworkCapabilities newNc = mixInCapabilities(newNetwork,
- newNetwork.networkCapabilities);
-
- final int oldPermission = getNetworkPermission(newNetwork.networkCapabilities);
- final int newPermission = getNetworkPermission(newNc);
- if (oldPermission != newPermission) {
- try {
- mNMS.setNetworkPermission(newNetwork.network.netId, newPermission);
- } catch (RemoteException e) {
- loge("Exception in setNetworkPermission: " + e);
- }
- }
-
- newNetwork.getAndSetNetworkCapabilities(newNc);
- notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_CAP_CHANGED);
- }
-
- processNewlySatisfiedListenRequests(newNetwork);
}
/**
@@ -6355,12 +6513,24 @@
// scoring network and then a higher scoring network, which could produce multiple
// callbacks.
Arrays.sort(nais);
+ final NetworkReassignment changes = new NetworkReassignment();
for (final NetworkAgentInfo nai : nais) {
- rematchNetworkAndRequests(nai, now);
+ rematchNetworkAndRequests(changes, nai, now);
}
final NetworkAgentInfo newDefaultNetwork = getDefaultNetwork();
+ for (final NetworkReassignment.NetworkBgStatePair event : changes.getRematchedNetworks()) {
+ // Process listen requests and update capabilities if the background state has
+ // changed for this network. For consistency with previous behavior, send onLost
+ // callbacks before onAvailable.
+ processNewlyLostListenRequests(event.mNetwork);
+ if (event.mOldBackground != event.mNetwork.isBackgroundNetwork()) {
+ applyBackgroundChangeForRematch(event.mNetwork);
+ }
+ processNewlySatisfiedListenRequests(event.mNetwork);
+ }
+
for (final NetworkAgentInfo nai : nais) {
// Rematching may have altered the linger state of some networks, so update all linger
// timers. updateLingerState reads the state from the network agent and does nothing
@@ -6392,6 +6562,24 @@
}
}
+ /**
+ * Apply a change in background state resulting from rematching networks with requests.
+ *
+ * During rematch, a network may change background states by starting to satisfy or stopping
+ * to satisfy a foreground request. Listens don't count for this. When a network changes
+ * background states, its capabilities need to be updated and callbacks fired for the
+ * capability change.
+ *
+ * @param nai The network that changed background states
+ */
+ private void applyBackgroundChangeForRematch(@NonNull final NetworkAgentInfo nai) {
+ final NetworkCapabilities newNc = mixInCapabilities(nai, nai.networkCapabilities);
+ if (Objects.equals(nai.networkCapabilities, newNc)) return;
+ updateNetworkPermissions(nai, newNc);
+ nai.getAndSetNetworkCapabilities(newNc);
+ notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
+ }
+
private void updateLegacyTypeTrackerAndVpnLockdownForRematch(
@Nullable final NetworkAgentInfo oldDefaultNetwork,
@Nullable final NetworkAgentInfo newDefaultNetwork,
@@ -6483,10 +6671,31 @@
}
}
- private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
+ @NonNull
+ private NetworkInfo mixInInfo(@NonNull final NetworkAgentInfo nai, @NonNull NetworkInfo info) {
+ final NetworkInfo newInfo = new NetworkInfo(info);
+ // The suspended and roaming bits are managed in NetworkCapabilities.
+ final boolean suspended =
+ !nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
+ if (suspended && info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) {
+ // Only override the state with SUSPENDED if the network is currently in CONNECTED
+ // state. This is because the network could have been suspended before connecting,
+ // or it could be disconnecting while being suspended, and in both these cases
+ // the state should not be overridden. Note that the only detailed state that
+ // maps to State.CONNECTED is DetailedState.CONNECTED, so there is also no need to
+ // worry about multiple different substates of CONNECTED.
+ newInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, info.getReason(),
+ info.getExtraInfo());
+ }
+ newInfo.setRoaming(!nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+ return newInfo;
+ }
+
+ private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo info) {
+ final NetworkInfo newInfo = mixInInfo(networkAgent, info);
+
final NetworkInfo.State state = newInfo.getState();
NetworkInfo oldInfo = null;
- final int oldScore = networkAgent.getCurrentScore();
synchronized (networkAgent) {
oldInfo = networkAgent.networkInfo;
networkAgent.networkInfo = newInfo;
@@ -6528,7 +6737,7 @@
// command must be sent after updating LinkProperties to maximize chances of
// NetworkMonitor seeing the correct LinkProperties when starting.
// TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call.
- if (networkAgent.networkMisc.acceptPartialConnectivity) {
+ if (networkAgent.networkAgentConfig.acceptPartialConnectivity) {
networkAgent.networkMonitor().setAcceptPartialConnectivity();
}
networkAgent.networkMonitor().notifyNetworkConnected(
@@ -6568,17 +6777,6 @@
}
} else if (networkAgent.created && (oldInfo.getState() == NetworkInfo.State.SUSPENDED ||
state == NetworkInfo.State.SUSPENDED)) {
- // going into or coming out of SUSPEND: re-score and notify
- if (networkAgent.getCurrentScore() != oldScore) {
- rematchAllNetworksAndRequests();
- }
- updateCapabilities(networkAgent.getCurrentScore(), networkAgent,
- networkAgent.networkCapabilities);
- // TODO (b/73132094) : remove this call once the few users of onSuspended and
- // onResumed have been removed.
- notifyNetworkCallbacks(networkAgent, (state == NetworkInfo.State.SUSPENDED ?
- ConnectivityManager.CALLBACK_SUSPENDED :
- ConnectivityManager.CALLBACK_RESUMED));
mLegacyTypeTracker.update(networkAgent);
}
}
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 9dead16..aeb3e7f 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -41,7 +41,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -582,11 +582,9 @@
}
int numFound = 0, numArgs = searchArgs.size();
- Time time = new Time();
out.append("\n");
for (EntryFile entry : mAllFiles.contents) {
- time.set(entry.timestampMillis);
- String date = time.format("%Y-%m-%d %H:%M:%S");
+ String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis);
boolean match = true;
for (int i = 0; i < numArgs && match; i++) {
String arg = searchArgs.get(i);
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 7909e30..c60460f 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -44,9 +44,9 @@
private static final String TAG = "DynamicSystemService";
private static final String NO_SERVICE_ERROR = "no gsiservice";
private static final int GSID_ROUGH_TIMEOUT_MS = 8192;
- private static final String PATH_DEFAULT = "/data/gsi";
+ private static final String PATH_DEFAULT = "/data/gsi/";
private Context mContext;
- private String mInstallPath;
+ private String mInstallPath, mDsuSlot;
private volatile IGsiService mGsiService;
DynamicSystemService(Context context) {
@@ -115,7 +115,7 @@
}
@Override
- public boolean startInstallation() throws RemoteException {
+ public boolean startInstallation(String dsuSlot) throws RemoteException {
IGsiService service = getGsiService();
// priority from high to low: sysprop -> sdcard -> /data
String path = SystemProperties.get("os.aot.path");
@@ -129,16 +129,17 @@
if (!Environment.MEDIA_MOUNTED.equals(volume.getState())) continue;
File sdCard = volume.getPathFile();
if (sdCard.isDirectory()) {
- path = sdCard.getPath();
+ path = new File(sdCard, dsuSlot).getPath();
break;
}
}
if (path.isEmpty()) {
- path = PATH_DEFAULT;
+ path = PATH_DEFAULT + dsuSlot;
}
Slog.i(TAG, "startInstallation -> " + path);
}
mInstallPath = path;
+ mDsuSlot = dsuSlot;
if (service.openInstall(path) != 0) {
Slog.i(TAG, "Failed to open " + path);
return false;
@@ -203,7 +204,7 @@
public boolean setEnable(boolean enable, boolean oneShot) throws RemoteException {
IGsiService gsiService = getGsiService();
if (enable) {
- return gsiService.enableGsi(oneShot) == 0;
+ return gsiService.enableGsi(oneShot, mDsuSlot) == 0;
} else {
return gsiService.disableGsi();
}
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index c0f10a3..9b1326b 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+
import android.Manifest;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -37,6 +39,7 @@
import android.os.UserHandle;
import android.service.carrier.CarrierMessagingService;
import android.telephony.SmsManager;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Slog;
@@ -137,11 +140,6 @@
}
@Override
- public Bundle getCarrierConfigValues(int subId) throws RemoteException {
- return null;
- }
-
- @Override
public Uri importTextMessage(String callingPkg, String address, int type, String text,
long timestampMillis, boolean seen, boolean read) throws RemoteException {
return null;
@@ -370,12 +368,6 @@
}
@Override
- public Bundle getCarrierConfigValues(int subId) throws RemoteException {
- Slog.d(TAG, "getCarrierConfigValues() by " + getCallingPackageName());
- return getServiceGuarded().getCarrierConfigValues(subId);
- }
-
- @Override
public Uri importTextMessage(String callingPkg, String address, int type, String text,
long timestampMillis, boolean seen, boolean read) throws RemoteException {
if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
@@ -523,11 +515,11 @@
// Grant permission for the carrier app.
Intent intent = new Intent(action);
- TelephonyManager telephonyManager =
- (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- List<String> carrierPackages =
- telephonyManager.getCarrierPackageNamesForIntentAndPhone(
- intent, SubscriptionManager.getPhoneId(subId));
+ TelephonyManager telephonyManager = (TelephonyManager)
+ mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ List<String> carrierPackages = telephonyManager
+ .getCarrierPackageNamesForIntentAndPhone(
+ intent, getPhoneIdFromSubId(subId));
if (carrierPackages != null && carrierPackages.size() == 1) {
LocalServices.getService(UriGrantsManagerInternal.class)
.grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
@@ -539,4 +531,13 @@
return contentUri;
}
}
+
+ private int getPhoneIdFromSubId(int subId) {
+ SubscriptionManager subManager = (SubscriptionManager)
+ mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ if (subManager == null) return INVALID_SIM_SLOT_INDEX;
+ SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
+ if (info == null) return INVALID_SIM_SLOT_INDEX;
+ return info.getSimSlotIndex();
+ }
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 0d496b6..1daed1b 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -58,10 +58,12 @@
import android.net.NetworkStats;
import android.net.NetworkUtils;
import android.net.RouteInfo;
-import android.net.TetherConfigParcel;
import android.net.TetherStatsParcel;
import android.net.UidRange;
import android.net.UidRangeParcel;
+import android.net.shared.NetdUtils;
+import android.net.shared.RouteUtils;
+import android.net.shared.RouteUtils.ModifyOperation;
import android.net.util.NetdService;
import android.os.BatteryStats;
import android.os.Binder;
@@ -897,48 +899,14 @@
@Override
public void addRoute(int netId, RouteInfo route) {
- modifyRoute(MODIFY_OPERATION_ADD, netId, route);
+ NetworkStack.checkNetworkStackPermission(mContext);
+ RouteUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route);
}
@Override
public void removeRoute(int netId, RouteInfo route) {
- modifyRoute(MODIFY_OPERATION_REMOVE, netId, route);
- }
-
- private void modifyRoute(boolean add, int netId, RouteInfo route) {
NetworkStack.checkNetworkStackPermission(mContext);
-
- final String ifName = route.getInterface();
- final String dst = route.getDestination().toString();
- final String nextHop;
-
- switch (route.getType()) {
- case RouteInfo.RTN_UNICAST:
- if (route.hasGateway()) {
- nextHop = route.getGateway().getHostAddress();
- } else {
- nextHop = INetd.NEXTHOP_NONE;
- }
- break;
- case RouteInfo.RTN_UNREACHABLE:
- nextHop = INetd.NEXTHOP_UNREACHABLE;
- break;
- case RouteInfo.RTN_THROW:
- nextHop = INetd.NEXTHOP_THROW;
- break;
- default:
- nextHop = INetd.NEXTHOP_NONE;
- break;
- }
- try {
- if (add) {
- mNetdService.networkAddRoute(netId, ifName, dst, nextHop);
- } else {
- mNetdService.networkRemoveRoute(netId, ifName, dst, nextHop);
- }
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
+ RouteUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route);
}
private ArrayList<String> readRouteList(String filename) {
@@ -1022,12 +990,8 @@
@Override
public void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange) {
NetworkStack.checkNetworkStackPermission(mContext);
- // an odd number of addrs will fail
try {
- final TetherConfigParcel config = new TetherConfigParcel();
- config.usingLegacyDnsProxy = usingLegacyDnsProxy;
- config.dhcpRanges = dhcpRange;
- mNetdService.tetherStartWithConfiguration(config);
+ NetdUtils.tetherStart(mNetdService, usingLegacyDnsProxy, dhcpRange);
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
}
@@ -1059,26 +1023,21 @@
public void tetherInterface(String iface) {
NetworkStack.checkNetworkStackPermission(mContext);
try {
- mNetdService.tetherInterfaceAdd(iface);
+ final LinkAddress addr = getInterfaceConfig(iface).getLinkAddress();
+ final IpPrefix dest = new IpPrefix(addr.getAddress(), addr.getPrefixLength());
+ NetdUtils.tetherInterface(mNetdService, iface, dest);
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
}
- List<RouteInfo> routes = new ArrayList<>();
- // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
- // suitable to use as a route destination.
- routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
- addInterfaceToLocalNetwork(iface, routes);
}
@Override
public void untetherInterface(String iface) {
NetworkStack.checkNetworkStackPermission(mContext);
try {
- mNetdService.tetherInterfaceRemove(iface);
+ NetdUtils.untetherInterface(mNetdService, iface);
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
- } finally {
- removeInterfaceFromLocalNetwork(iface);
}
}
@@ -2121,16 +2080,8 @@
@Override
public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
-
- for (RouteInfo route : routes) {
- if (!route.isDefaultRoute()) {
- modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route);
- }
- }
-
- // IPv6 link local should be activated always.
- modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID,
- new RouteInfo(new IpPrefix("fe80::/64"), null, iface));
+ // modifyInterfaceInNetwork already check calling permission.
+ RouteUtils.addRoutesToLocalNetwork(mNetdService, iface, routes);
}
@Override
@@ -2140,17 +2091,8 @@
@Override
public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
- int failures = 0;
-
- for (RouteInfo route : routes) {
- try {
- modifyRoute(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, route);
- } catch (IllegalStateException e) {
- failures++;
- }
- }
-
- return failures;
+ NetworkStack.checkNetworkStackPermission(mContext);
+ return RouteUtils.removeRoutesFromLocalNetwork(mNetdService, routes);
}
@Override
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 9a7a4e7..2fb1f77 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -54,7 +54,6 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.IntArray;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -527,7 +526,7 @@
@Override
public void accept(INetworkScoreCache networkScoreCache, Object cookie) {
- int filterType = NetworkScoreManager.CACHE_FILTER_NONE;
+ int filterType = NetworkScoreManager.SCORE_FILTER_NONE;
if (cookie instanceof Integer) {
filterType = (Integer) cookie;
}
@@ -551,17 +550,17 @@
private List<ScoredNetwork> filterScores(List<ScoredNetwork> scoredNetworkList,
int filterType) {
switch (filterType) {
- case NetworkScoreManager.CACHE_FILTER_NONE:
+ case NetworkScoreManager.SCORE_FILTER_NONE:
return scoredNetworkList;
- case NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK:
+ case NetworkScoreManager.SCORE_FILTER_CURRENT_NETWORK:
if (mCurrentNetworkFilter == null) {
mCurrentNetworkFilter =
new CurrentNetworkScoreCacheFilter(new WifiInfoSupplier(mContext));
}
return mCurrentNetworkFilter.apply(scoredNetworkList);
- case NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS:
+ case NetworkScoreManager.SCORE_FILTER_SCAN_RESULTS:
if (mScanResultsFilter == null) {
mScanResultsFilter = new ScanResultsScoreCacheFilter(
new ScanResultsSupplier(mContext));
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 1ff455ea..c34dd98 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -16,15 +16,273 @@
package com.android.server;
-import android.os.IBinder;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.timedetector.NetworkTimeSuggestion;
+import android.app.timedetector.TimeDetector;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.os.TimestampedValue;
+import android.provider.Settings;
+import android.util.Log;
+import android.util.NtpTrustedTime;
+import android.util.TimeUtils;
+
+import com.android.internal.util.DumpUtils;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
/**
- * An interface for NetworkTimeUpdateService implementations. Eventually part or all of this service
- * will be subsumed into {@link com.android.server.timedetector.TimeDetectorService}. In the
- * meantime this interface allows Android to use either the old or new implementation.
+ * Monitors the network time. If looking up the network time fails for some reason, it tries a few
+ * times with a short interval and then resets to checking on longer intervals.
+ *
+ * <p>When available, the time is always suggested to the {@link
+ * com.android.server.timedetector.TimeDetectorService} where it may be used to set the device
+ * system clock, depending on user settings and what other signals are available.
*/
-public interface NetworkTimeUpdateService extends IBinder {
+public class NetworkTimeUpdateService extends Binder {
+
+ private static final String TAG = "NetworkTimeUpdateService";
+ private static final boolean DBG = false;
+
+ private static final int EVENT_AUTO_TIME_ENABLED = 1;
+ private static final int EVENT_POLL_NETWORK_TIME = 2;
+ private static final int EVENT_NETWORK_CHANGED = 3;
+
+ private static final String ACTION_POLL =
+ "com.android.server.NetworkTimeUpdateService.action.POLL";
+
+ private static final int POLL_REQUEST = 0;
+
+ private Network mDefaultNetwork = null;
+
+ private final Context mContext;
+ private final NtpTrustedTime mTime;
+ private final AlarmManager mAlarmManager;
+ private final TimeDetector mTimeDetector;
+ private final ConnectivityManager mCM;
+ private final PendingIntent mPendingPollIntent;
+ private final PowerManager.WakeLock mWakeLock;
+
+ // NTP lookup is done on this thread and handler
+ private Handler mHandler;
+ private AutoTimeSettingObserver mAutoTimeSettingObserver;
+ private NetworkTimeUpdateCallback mNetworkTimeUpdateCallback;
+
+ // Normal polling frequency
+ private final long mPollingIntervalMs;
+ // Try-again polling interval, in case the network request failed
+ private final long mPollingIntervalShorterMs;
+ // Number of times to try again
+ private final int mTryAgainTimesMax;
+ // Keeps track of how many quick attempts were made to fetch NTP time.
+ // During bootup, the network may not have been up yet, or it's taking time for the
+ // connection to happen.
+ private int mTryAgainCounter;
+
+ public NetworkTimeUpdateService(Context context) {
+ mContext = context;
+ mTime = NtpTrustedTime.getInstance(context);
+ mAlarmManager = mContext.getSystemService(AlarmManager.class);
+ mTimeDetector = mContext.getSystemService(TimeDetector.class);
+ mCM = mContext.getSystemService(ConnectivityManager.class);
+
+ Intent pollIntent = new Intent(ACTION_POLL, null);
+ mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
+
+ mPollingIntervalMs = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_ntpPollingInterval);
+ mPollingIntervalShorterMs = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_ntpPollingIntervalShorter);
+ mTryAgainTimesMax = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_ntpRetry);
+
+ mWakeLock = context.getSystemService(PowerManager.class).newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, TAG);
+ }
/** Initialize the receivers and initiate the first NTP request */
- void systemRunning();
+ public void systemRunning() {
+ registerForAlarms();
+
+ HandlerThread thread = new HandlerThread(TAG);
+ thread.start();
+ mHandler = new MyHandler(thread.getLooper());
+ mNetworkTimeUpdateCallback = new NetworkTimeUpdateCallback();
+ mCM.registerDefaultNetworkCallback(mNetworkTimeUpdateCallback, mHandler);
+
+ mAutoTimeSettingObserver = new AutoTimeSettingObserver(mContext, mHandler,
+ EVENT_AUTO_TIME_ENABLED);
+ mAutoTimeSettingObserver.observe();
+ }
+
+ private void registerForAlarms() {
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();
+ }
+ }, new IntentFilter(ACTION_POLL));
+ }
+
+ private void onPollNetworkTime(int event) {
+ // If we don't have any default network, don't bother.
+ if (mDefaultNetwork == null) return;
+ mWakeLock.acquire();
+ try {
+ onPollNetworkTimeUnderWakeLock(event);
+ } finally {
+ mWakeLock.release();
+ }
+ }
+
+ private void onPollNetworkTimeUnderWakeLock(int event) {
+ // Force an NTP fix when outdated
+ NtpTrustedTime.TimeResult cachedNtpResult = mTime.getCachedTimeResult();
+ if (cachedNtpResult == null || cachedNtpResult.getAgeMillis() >= mPollingIntervalMs) {
+ if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh");
+ mTime.forceRefresh();
+ cachedNtpResult = mTime.getCachedTimeResult();
+ }
+
+ if (cachedNtpResult != null && cachedNtpResult.getAgeMillis() < mPollingIntervalMs) {
+ // Obtained fresh fix; schedule next normal update
+ resetAlarm(mPollingIntervalMs);
+
+ // Suggest the time to the time detector. It may choose use it to set the system clock.
+ TimestampedValue<Long> timeSignal = new TimestampedValue<>(
+ cachedNtpResult.getElapsedRealtimeMillis(), cachedNtpResult.getTimeMillis());
+ NetworkTimeSuggestion timeSuggestion = new NetworkTimeSuggestion(timeSignal);
+ timeSuggestion.addDebugInfo("Origin: NetworkTimeUpdateService. event=" + event);
+ mTimeDetector.suggestNetworkTime(timeSuggestion);
+ } else {
+ // No fresh fix; schedule retry
+ mTryAgainCounter++;
+ if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
+ resetAlarm(mPollingIntervalShorterMs);
+ } else {
+ // Try much later
+ mTryAgainCounter = 0;
+ resetAlarm(mPollingIntervalMs);
+ }
+ }
+ }
+
+ /**
+ * Cancel old alarm and starts a new one for the specified interval.
+ *
+ * @param interval when to trigger the alarm, starting from now.
+ */
+ private void resetAlarm(long interval) {
+ mAlarmManager.cancel(mPendingPollIntent);
+ long now = SystemClock.elapsedRealtime();
+ long next = now + interval;
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
+ }
+
+ /** Handler to do the network accesses on */
+ private class MyHandler extends Handler {
+
+ MyHandler(Looper l) {
+ super(l);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_AUTO_TIME_ENABLED:
+ case EVENT_POLL_NETWORK_TIME:
+ case EVENT_NETWORK_CHANGED:
+ onPollNetworkTime(msg.what);
+ break;
+ }
+ }
+ }
+
+ private class NetworkTimeUpdateCallback extends NetworkCallback {
+ @Override
+ public void onAvailable(Network network) {
+ Log.d(TAG, String.format("New default network %s; checking time.", network));
+ mDefaultNetwork = network;
+ // Running on mHandler so invoke directly.
+ onPollNetworkTime(EVENT_NETWORK_CHANGED);
+ }
+
+ @Override
+ public void onLost(Network network) {
+ if (network.equals(mDefaultNetwork)) mDefaultNetwork = null;
+ }
+ }
+
+ /**
+ * Observer to watch for changes to the AUTO_TIME setting. It only triggers when the setting
+ * is enabled.
+ */
+ private static class AutoTimeSettingObserver extends ContentObserver {
+
+ private final Context mContext;
+ private final int mMsg;
+ private final Handler mHandler;
+
+ AutoTimeSettingObserver(Context context, Handler handler, int msg) {
+ super(handler);
+ mContext = context;
+ mHandler = handler;
+ mMsg = msg;
+ }
+
+ void observe() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME),
+ false, this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ if (isAutomaticTimeEnabled()) {
+ mHandler.obtainMessage(mMsg).sendToTarget();
+ }
+ }
+
+ /**
+ * Checks if the user prefers to automatically set the time.
+ */
+ private boolean isAutomaticTimeEnabled() {
+ ContentResolver resolver = mContext.getContentResolver();
+ return Settings.Global.getInt(resolver, Settings.Global.AUTO_TIME, 0) != 0;
+ }
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+ pw.print("PollingIntervalMs: ");
+ TimeUtils.formatDuration(mPollingIntervalMs, pw);
+ pw.print("\nPollingIntervalShorterMs: ");
+ TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
+ pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
+ pw.println("\nTryAgainCounter: " + mTryAgainCounter);
+ NtpTrustedTime.TimeResult ntpResult = mTime.getCachedTimeResult();
+ pw.println("NTP cache result: " + ntpResult);
+ if (ntpResult != null) {
+ pw.println("NTP result age: " + ntpResult.getAgeMillis());
+ }
+ pw.println();
+ }
}
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
deleted file mode 100644
index 39be311..0000000
--- a/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
+++ /dev/null
@@ -1,329 +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 com.android.server;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.ContentObserver;
-import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
-import android.net.Network;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.util.NtpTrustedTime;
-import android.util.TimeUtils;
-
-import com.android.internal.util.DumpUtils;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Monitors the network time and updates the system time if it is out of sync
- * and there hasn't been any NITZ update from the carrier recently.
- * If looking up the network time fails for some reason, it tries a few times with a short
- * interval and then resets to checking on longer intervals.
- * <p>
- * If the user enables AUTO_TIME, it will check immediately for the network time, if NITZ wasn't
- * available.
- * </p>
- */
-public class NetworkTimeUpdateServiceImpl extends Binder implements NetworkTimeUpdateService {
-
- private static final String TAG = "NetworkTimeUpdateService";
- private static final boolean DBG = false;
-
- private static final int EVENT_AUTO_TIME_CHANGED = 1;
- private static final int EVENT_POLL_NETWORK_TIME = 2;
- private static final int EVENT_NETWORK_CHANGED = 3;
-
- private static final String ACTION_POLL =
- "com.android.server.NetworkTimeUpdateService.action.POLL";
-
- private static final int POLL_REQUEST = 0;
-
- private static final long NOT_SET = -1;
- private long mNitzTimeSetTime = NOT_SET;
- private Network mDefaultNetwork = null;
-
- private final Context mContext;
- private final NtpTrustedTime mTime;
- private final AlarmManager mAlarmManager;
- private final ConnectivityManager mCM;
- private final PendingIntent mPendingPollIntent;
- private final PowerManager.WakeLock mWakeLock;
-
- // NTP lookup is done on this thread and handler
- private Handler mHandler;
- private SettingsObserver mSettingsObserver;
- private NetworkTimeUpdateCallback mNetworkTimeUpdateCallback;
-
- // Normal polling frequency
- private final long mPollingIntervalMs;
- // Try-again polling interval, in case the network request failed
- private final long mPollingIntervalShorterMs;
- // Number of times to try again
- private final int mTryAgainTimesMax;
- // If the time difference is greater than this threshold, then update the time.
- private final int mTimeErrorThresholdMs;
- // Keeps track of how many quick attempts were made to fetch NTP time.
- // During bootup, the network may not have been up yet, or it's taking time for the
- // connection to happen.
- private int mTryAgainCounter;
-
- public NetworkTimeUpdateServiceImpl(Context context) {
- mContext = context;
- mTime = NtpTrustedTime.getInstance(context);
- mAlarmManager = mContext.getSystemService(AlarmManager.class);
- mCM = mContext.getSystemService(ConnectivityManager.class);
-
- Intent pollIntent = new Intent(ACTION_POLL, null);
- mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
-
- mPollingIntervalMs = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_ntpPollingInterval);
- mPollingIntervalShorterMs = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_ntpPollingIntervalShorter);
- mTryAgainTimesMax = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_ntpRetry);
- mTimeErrorThresholdMs = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_ntpThreshold);
-
- mWakeLock = context.getSystemService(PowerManager.class).newWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, TAG);
- }
-
- @Override
- public void systemRunning() {
- registerForTelephonyIntents();
- registerForAlarms();
-
- HandlerThread thread = new HandlerThread(TAG);
- thread.start();
- mHandler = new MyHandler(thread.getLooper());
- mNetworkTimeUpdateCallback = new NetworkTimeUpdateCallback();
- mCM.registerDefaultNetworkCallback(mNetworkTimeUpdateCallback, mHandler);
-
- mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED);
- mSettingsObserver.observe(mContext);
- }
-
- private void registerForTelephonyIntents() {
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(TelephonyManager.ACTION_NETWORK_SET_TIME);
- mContext.registerReceiver(mNitzReceiver, intentFilter);
- }
-
- private void registerForAlarms() {
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();
- }
- }, new IntentFilter(ACTION_POLL));
- }
-
- private void onPollNetworkTime(int event) {
- // If Automatic time is not set, don't bother. Similarly, if we don't
- // have any default network, don't bother.
- if (mDefaultNetwork == null) return;
- mWakeLock.acquire();
- try {
- onPollNetworkTimeUnderWakeLock(event);
- } finally {
- mWakeLock.release();
- }
- }
-
- private void onPollNetworkTimeUnderWakeLock(int event) {
- // Force an NTP fix when outdated
- if (mTime.getCacheAge() >= mPollingIntervalMs) {
- if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh");
- mTime.forceRefresh();
- }
-
- if (mTime.getCacheAge() < mPollingIntervalMs) {
- // Obtained fresh fix; schedule next normal update
- resetAlarm(mPollingIntervalMs);
- if (isAutomaticTimeRequested()) {
- updateSystemClock(event);
- }
-
- } else {
- // No fresh fix; schedule retry
- mTryAgainCounter++;
- if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
- resetAlarm(mPollingIntervalShorterMs);
- } else {
- // Try much later
- mTryAgainCounter = 0;
- resetAlarm(mPollingIntervalMs);
- }
- }
- }
-
- private long getNitzAge() {
- if (mNitzTimeSetTime == NOT_SET) {
- return Long.MAX_VALUE;
- } else {
- return SystemClock.elapsedRealtime() - mNitzTimeSetTime;
- }
- }
-
- /**
- * Consider updating system clock based on current NTP fix, if requested by
- * user, significant enough delta, and we don't have a recent NITZ.
- */
- private void updateSystemClock(int event) {
- final boolean forceUpdate = (event == EVENT_AUTO_TIME_CHANGED);
- if (!forceUpdate) {
- if (getNitzAge() < mPollingIntervalMs) {
- if (DBG) Log.d(TAG, "Ignoring NTP update due to recent NITZ");
- return;
- }
-
- final long skew = Math.abs(mTime.currentTimeMillis() - System.currentTimeMillis());
- if (skew < mTimeErrorThresholdMs) {
- if (DBG) Log.d(TAG, "Ignoring NTP update due to low skew");
- return;
- }
- }
-
- SystemClock.setCurrentTimeMillis(mTime.currentTimeMillis());
- }
-
- /**
- * Cancel old alarm and starts a new one for the specified interval.
- *
- * @param interval when to trigger the alarm, starting from now.
- */
- private void resetAlarm(long interval) {
- mAlarmManager.cancel(mPendingPollIntent);
- long now = SystemClock.elapsedRealtime();
- long next = now + interval;
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
- }
-
- /**
- * Checks if the user prefers to automatically set the time.
- */
- private boolean isAutomaticTimeRequested() {
- return Settings.Global.getInt(
- mContext.getContentResolver(), Settings.Global.AUTO_TIME, 0) != 0;
- }
-
- /** Receiver for Nitz time events */
- private BroadcastReceiver mNitzReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (DBG) Log.d(TAG, "Received " + action);
- if (TelephonyManager.ACTION_NETWORK_SET_TIME.equals(action)) {
- mNitzTimeSetTime = SystemClock.elapsedRealtime();
- }
- }
- };
-
- /** Handler to do the network accesses on */
- private class MyHandler extends Handler {
-
- public MyHandler(Looper l) {
- super(l);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case EVENT_AUTO_TIME_CHANGED:
- case EVENT_POLL_NETWORK_TIME:
- case EVENT_NETWORK_CHANGED:
- onPollNetworkTime(msg.what);
- break;
- }
- }
- }
-
- private class NetworkTimeUpdateCallback extends NetworkCallback {
- @Override
- public void onAvailable(Network network) {
- Log.d(TAG, String.format("New default network %s; checking time.", network));
- mDefaultNetwork = network;
- // Running on mHandler so invoke directly.
- onPollNetworkTime(EVENT_NETWORK_CHANGED);
- }
-
- @Override
- public void onLost(Network network) {
- if (network.equals(mDefaultNetwork)) mDefaultNetwork = null;
- }
- }
-
- /** Observer to watch for changes to the AUTO_TIME setting */
- private static class SettingsObserver extends ContentObserver {
-
- private int mMsg;
- private Handler mHandler;
-
- SettingsObserver(Handler handler, int msg) {
- super(handler);
- mHandler = handler;
- mMsg = msg;
- }
-
- void observe(Context context) {
- ContentResolver resolver = context.getContentResolver();
- resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME),
- false, this);
- }
-
- @Override
- public void onChange(boolean selfChange) {
- mHandler.obtainMessage(mMsg).sendToTarget();
- }
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
- pw.print("PollingIntervalMs: ");
- TimeUtils.formatDuration(mPollingIntervalMs, pw);
- pw.print("\nPollingIntervalShorterMs: ");
- TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
- pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
- pw.print("TimeErrorThresholdMs: ");
- TimeUtils.formatDuration(mTimeErrorThresholdMs, pw);
- pw.println("\nTryAgainCounter: " + mTryAgainCounter);
- pw.println("NTP cache age: " + mTime.getCacheAge());
- pw.println("NTP cache certainty: " + mTime.getCacheCertainty());
- pw.println();
- }
-}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d1bc6af..90b0c11 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2648,9 +2648,11 @@
*/
@Override
public boolean supportsCheckpoint() throws RemoteException {
- // Only the system process is permitted to start checkpoints
- if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
- throw new SecurityException("no permission to check filesystem checkpoint support");
+ // Only the root, system_server and shell processes are permitted to start checkpoints
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID
+ && callingUid != Process.SHELL_UID) {
+ throw new SecurityException("no permission to start filesystem checkpoint");
}
return mVold.supportsCheckpoint();
@@ -2665,8 +2667,10 @@
*/
@Override
public void startCheckpoint(int numTries) throws RemoteException {
- // Only the system process is permitted to start checkpoints
- if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
+ // Only the root, system_server and shell processes are permitted to start checkpoints
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID
+ && callingUid != Process.SHELL_UID) {
throw new SecurityException("no permission to start filesystem checkpoint");
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index b5ecd19..62743aa 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -16,12 +16,15 @@
package com.android.server;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
import static android.telephony.TelephonyRegistryManager.SIM_ACTIVATION_TYPE_DATA;
import static android.telephony.TelephonyRegistryManager.SIM_ACTIVATION_TYPE_VOICE;
import static java.util.Arrays.copyOf;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
@@ -44,8 +47,16 @@
import android.telephony.Annotation.SrvccState;
import android.telephony.CallAttributes;
import android.telephony.CallQuality;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.CellLocation;
+import android.telephony.CellSignalStrength;
+import android.telephony.CellSignalStrengthCdma;
+import android.telephony.CellSignalStrengthGsm;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.CellSignalStrengthNr;
+import android.telephony.CellSignalStrengthTdscdma;
+import android.telephony.CellSignalStrengthWcdma;
import android.telephony.DataFailCause;
import android.telephony.DisconnectCause;
import android.telephony.LocationAccessPolicy;
@@ -57,6 +68,7 @@
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
@@ -95,7 +107,7 @@
* and 15973975 by saving the phoneId of the registrant and then using the
* phoneId when deciding to to make a callback. This is necessary because
* a subId changes from to a dummy value when a SIM is removed and thus won't
- * compare properly. Because SubscriptionManager.getPhoneId(int subId) handles
+ * compare properly. Because getPhoneIdFromSubId(int subId) handles
* the dummy value conversion we properly do the callbacks.
*
* Eventually we may want to remove the notion of dummy value but for now this
@@ -112,6 +124,7 @@
Context context;
String callingPackage;
+ String callingFeatureId;
IBinder binder;
@@ -128,7 +141,7 @@
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+ int phoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
boolean matchPhoneStateListenerEvent(int events) {
return (callback != null) && ((events & this.events) != 0);
@@ -145,7 +158,7 @@
boolean canReadCallLog() {
try {
return TelephonyPermissions.checkReadCallLog(
- context, subId, callerPid, callerUid, callingPackage);
+ context, subId, callerPid, callerUid, callingPackage, callingFeatureId);
} catch (SecurityException e) {
return false;
}
@@ -203,7 +216,7 @@
// Connection state of default APN type data (i.e. internet) of phones
private int[] mDataConnectionState;
- private Bundle[] mCellLocation;
+ private CellIdentity[] mCellIdentity;
private int[] mDataConnectionNetworkType;
@@ -226,7 +239,7 @@
private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- private int mDefaultPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+ private int mDefaultPhoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
private int[] mRingingCallState;
@@ -269,11 +282,15 @@
static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
| PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
- | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST;
+ | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST
+ | PhoneStateListener.LISTEN_REGISTRATION_FAILURE;
static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
- PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
- PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
+ PhoneStateListener.LISTEN_PRECISE_CALL_STATE
+ | PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE
+ | PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES
+ | PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED
+ | PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES;
static final int READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK =
PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL
@@ -291,7 +308,7 @@
int numPhones = getTelephonyManager().getPhoneCount();
for (int sub = 0; sub < numPhones; sub++) {
TelephonyRegistry.this.notifyCellLocationForSubscriber(sub,
- mCellLocation[sub]);
+ mCellIdentity[sub]);
}
break;
}
@@ -355,7 +372,7 @@
SubscriptionManager.getDefaultSubscriptionId());
int newDefaultPhoneId = intent.getIntExtra(
SubscriptionManager.EXTRA_SLOT_INDEX,
- SubscriptionManager.getPhoneId(newDefaultSubId));
+ getPhoneIdFromSubId(newDefaultSubId));
if (DBG) {
log("onReceive:current mDefaultSubId=" + mDefaultSubId
+ " current mDefaultPhoneId=" + mDefaultPhoneId
@@ -397,10 +414,14 @@
mVoiceActivationState = copyOf(mVoiceActivationState, mNumPhones);
mDataActivationState = copyOf(mDataActivationState, mNumPhones);
mUserMobileDataState = copyOf(mUserMobileDataState, mNumPhones);
- mSignalStrength = copyOf(mSignalStrength, mNumPhones);
+ if (mSignalStrength != null) {
+ mSignalStrength = copyOf(mSignalStrength, mNumPhones);
+ } else {
+ mSignalStrength = new SignalStrength[mNumPhones];
+ }
mMessageWaiting = copyOf(mMessageWaiting, mNumPhones);
mCallForwarding = copyOf(mCallForwarding, mNumPhones);
- mCellLocation = copyOf(mCellLocation, mNumPhones);
+ mCellIdentity = copyOf(mCellIdentity, mNumPhones);
mSrvccState = copyOf(mSrvccState, mNumPhones);
mPreciseCallState = copyOf(mPreciseCallState, mNumPhones);
mForegroundCallState = copyOf(mForegroundCallState, mNumPhones);
@@ -431,11 +452,11 @@
mDataActivationState[i] = TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
mCallIncomingNumber[i] = "";
mServiceState[i] = new ServiceState();
- mSignalStrength[i] = new SignalStrength();
+ mSignalStrength[i] = null;
mUserMobileDataState[i] = false;
mMessageWaiting[i] = false;
mCallForwarding[i] = false;
- mCellLocation[i] = new Bundle();
+ mCellIdentity[i] = null;
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
@@ -451,15 +472,6 @@
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
}
-
- // Note that location can be null for non-phone builds like
- // like the generic one.
- CellLocation location = CellLocation.getEmpty();
- if (location != null) {
- for (int i = oldNumPhones; i < mNumPhones; i++) {
- location.fillInNotifierBundle(mCellLocation[i]);
- }
- }
}
private void cutListToSize(List list, int size) {
@@ -499,7 +511,7 @@
mSignalStrength = new SignalStrength[numPhones];
mMessageWaiting = new boolean[numPhones];
mCallForwarding = new boolean[numPhones];
- mCellLocation = new Bundle[numPhones];
+ mCellIdentity = new CellIdentity[numPhones];
mSrvccState = new int[numPhones];
mPreciseCallState = new PreciseCallState[numPhones];
mForegroundCallState = new int[numPhones];
@@ -524,11 +536,11 @@
mDataActivationState[i] = TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
mCallIncomingNumber[i] = "";
mServiceState[i] = new ServiceState();
- mSignalStrength[i] = new SignalStrength();
+ mSignalStrength[i] = null;
mUserMobileDataState[i] = false;
mMessageWaiting[i] = false;
mCallForwarding[i] = false;
- mCellLocation[i] = new Bundle();
+ mCellIdentity[i] = null;
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
@@ -545,14 +557,6 @@
mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
}
- // Note that location can be null for non-phone builds like
- // like the generic one.
- if (location != null) {
- for (int i = 0; i < numPhones; i++) {
- location.fillInNotifierBundle(mCellLocation[i]);
- }
- }
-
mAppOps = mContext.getSystemService(AppOpsManager.class);
}
@@ -568,7 +572,7 @@
}
@Override
- public void addOnSubscriptionsChangedListener(String callingPackage,
+ public void addOnSubscriptionsChangedListener(String callingPackage, String callingFeatureId,
IOnSubscriptionsChangedListener callback) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
@@ -590,6 +594,7 @@
r.context = mContext;
r.onSubscriptionsChangedListenerCallback = callback;
r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
r.events = 0;
@@ -622,7 +627,7 @@
@Override
public void addOnOpportunisticSubscriptionsChangedListener(String callingPackage,
- IOnSubscriptionsChangedListener callback) {
+ String callingFeatureId, IOnSubscriptionsChangedListener callback) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
if (VDBG) {
@@ -643,6 +648,7 @@
r.context = mContext;
r.onOpportunisticSubscriptionsChangedListenerCallback = callback;
r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
r.events = 0;
@@ -718,21 +724,28 @@
}
}
+ @Deprecated
@Override
- public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
+ public void listen(String callingPackage, IPhoneStateListener callback, int events,
boolean notifyNow) {
- listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, pkgForDebug, callback,
- events, notifyNow);
+ listenWithFeature(callingPackage, null, callback, events, notifyNow);
}
@Override
- public void listenForSubscriber(int subId, String pkgForDebug, IPhoneStateListener callback,
- int events, boolean notifyNow) {
- listen(pkgForDebug, callback, events, notifyNow, subId);
+ public void listenWithFeature(String callingPackage, String callingFeatureId,
+ IPhoneStateListener callback, int events, boolean notifyNow) {
+ listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, callingPackage,
+ callingFeatureId, callback, events, notifyNow);
}
- private void listen(String callingPackage, IPhoneStateListener callback, int events,
- boolean notifyNow, int subId) {
+ @Override
+ public void listenForSubscriber(int subId, String callingPackage, String callingFeatureId,
+ IPhoneStateListener callback, int events, boolean notifyNow) {
+ listen(callingPackage, callingFeatureId, callback, events, notifyNow, subId);
+ }
+
+ private void listen(String callingPackage, @Nullable String callingFeatureId,
+ IPhoneStateListener callback, int events, boolean notifyNow, int subId) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
String str = "listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events)
@@ -747,11 +760,12 @@
// Checks permission and throws SecurityException for disallowed operations. For pre-M
// apps whose runtime permission has been revoked, we return immediately to skip sending
// events to the app without crashing it.
- if (!checkListenerPermission(events, subId, callingPackage, "listen")) {
+ if (!checkListenerPermission(events, subId, callingPackage, callingFeatureId,
+ "listen")) {
return;
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
@@ -764,6 +778,7 @@
r.context = mContext;
r.callback = callback;
r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
// Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
@@ -786,9 +801,11 @@
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
r.callback.onServiceStateChanged(rawSs);
} else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(false));
+ r.callback.onServiceStateChanged(
+ rawSs.createLocationInfoSanitizedCopy(false));
} else {
- r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(true));
+ r.callback.onServiceStateChanged(
+ rawSs.createLocationInfoSanitizedCopy(true));
}
} catch (RemoteException ex) {
remove(r.binder);
@@ -796,10 +813,12 @@
}
if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
- int gsmSignalStrength = mSignalStrength[phoneId]
- .getGsmSignalStrength();
- r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
- : gsmSignalStrength));
+ if (mSignalStrength[phoneId] != null) {
+ int gsmSignalStrength = mSignalStrength[phoneId]
+ .getGsmSignalStrength();
+ r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+ : gsmSignalStrength));
+ }
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -822,11 +841,10 @@
}
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
- if (DBG_LOC) log("listen: mCellLocation = "
- + mCellLocation[phoneId]);
+ if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onCellLocationChanged(
- new Bundle(mCellLocation[phoneId]));
+ // null will be translated to empty CellLocation object in client.
+ r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
}
} catch (RemoteException ex) {
remove(r.binder);
@@ -857,7 +875,9 @@
}
if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
try {
- r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
+ if (mSignalStrength[phoneId] != null) {
+ r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
+ }
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -1077,7 +1097,7 @@
// Called only by Telecomm to communicate call state across different phone accounts. So
// there is no need to add a valid subId or slotId.
broadcastCallStateChanged(state, phoneNumber,
- SubscriptionManager.INVALID_PHONE_INDEX,
+ SubscriptionManager.INVALID_SIM_SLOT_INDEX,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
}
@@ -1144,9 +1164,9 @@
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
stateToSend = new ServiceState(state);
} else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- stateToSend = state.sanitizeLocationInfo(false);
+ stateToSend = state.createLocationInfoSanitizedCopy(false);
} else {
- stateToSend = state.sanitizeLocationInfo(true);
+ stateToSend = state.createLocationInfoSanitizedCopy(true);
}
if (DBG) {
log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
@@ -1291,7 +1311,8 @@
// only CarrierService with carrier privilege rule should have the permission
int[] subIds = Arrays.stream(SubscriptionManager.from(mContext)
.getActiveSubscriptionIdList(false))
- .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(i)).toArray();
+ .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(mContext,
+ i)).toArray();
if (ArrayUtils.isEmpty(subIds)) {
loge("notifyCarrierNetworkChange without carrier privilege");
// the active subId does not have carrier privilege.
@@ -1301,7 +1322,7 @@
synchronized (mRecords) {
mCarrierNetworkChangeState = active;
for (int subId : subIds) {
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
if (VDBG) {
log("notifyCarrierNetworkChange: active=" + active + "subId: " + subId);
@@ -1334,7 +1355,7 @@
log("notifyCellInfoForSubscriber: subId=" + subId
+ " cellInfo=" + cellInfo);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mCellInfo.set(phoneId, cellInfo);
@@ -1425,7 +1446,7 @@
log("notifyCallForwardingChangedForSubscriber: subId=" + subId
+ " cfi=" + cfi);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mCallForwarding[phoneId] = cfi;
@@ -1453,7 +1474,7 @@
if (!checkNotifyPermission("notifyDataActivity()" )) {
return;
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mDataActivity[phoneId] = state;
@@ -1593,7 +1614,7 @@
TelephonyManager.DATA_UNKNOWN,
TelephonyManager.NETWORK_TYPE_UNKNOWN,
ApnSetting.getApnTypesBitmaskFromString(apnType), null, null,
- DataFailCause.NONE));
+ DataFailCause.NONE, null));
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
@@ -1610,14 +1631,15 @@
handleRemoveListLocked();
}
- broadcastDataConnectionFailed(apnType, subId);
}
- public void notifyCellLocation(Bundle cellLocation) {
- notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
+ @Override
+ public void notifyCellLocation(CellIdentity cellLocation) {
+ notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
}
- public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) {
+ @Override
+ public void notifyCellLocationForSubscriber(int subId, CellIdentity cellLocation) {
log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
if (!checkNotifyPermission("notifyCellLocation()")) {
@@ -1627,10 +1649,10 @@
log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
- mCellLocation[phoneId] = cellLocation;
+ mCellIdentity[phoneId] = cellLocation;
for (Record r : mRecords) {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
idMatch(r.subId, subId, phoneId) &&
@@ -1640,7 +1662,7 @@
log("notifyCellLocation: cellLocation=" + cellLocation
+ " r=" + r);
}
- r.callback.onCellLocationChanged(new Bundle(cellLocation));
+ r.callback.onCellLocationChanged(cellLocation);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -1736,7 +1758,7 @@
if (!checkNotifyPermission("notifyImsCallDisconnectCause()")) {
return;
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mImsReasonInfo.set(phoneId, imsReasonInfo);
@@ -1777,7 +1799,7 @@
TelephonyManager.DATA_UNKNOWN,
TelephonyManager.NETWORK_TYPE_UNKNOWN,
ApnSetting.getApnTypesBitmaskFromString(apnType), null, null,
- failCause));
+ failCause, null));
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
@@ -1803,7 +1825,7 @@
if (VDBG) {
log("notifySrvccStateChanged: subId=" + subId + " srvccState=" + state);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mSrvccState[phoneId] = state;
@@ -2049,6 +2071,40 @@
}
@Override
+ public void notifyRegistrationFailed(int phoneId, int subId, @NonNull CellIdentity cellIdentity,
+ @NonNull String chosenPlmn, int domain, int causeCode, int additionalCauseCode) {
+ if (!checkNotifyPermission("notifyRegistrationFailed()")) {
+ return;
+ }
+
+ // In case callers don't have fine location access, pre-construct a location-free version
+ // of the CellIdentity. This will still have the PLMN ID, which should be sufficient for
+ // most purposes.
+ final CellIdentity noLocationCi = cellIdentity.sanitizeLocationInfo();
+
+ synchronized (mRecords) {
+ if (validatePhoneId(phoneId)) {
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_REGISTRATION_FAILURE)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onRegistrationFailed(
+ checkFineLocationAccess(r, Build.VERSION_CODES.R)
+ ? cellIdentity : noLocationCi,
+ chosenPlmn, domain, causeCode,
+ additionalCauseCode);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2077,7 +2133,7 @@
pw.println("mCallForwarding=" + mCallForwarding[i]);
pw.println("mDataActivity=" + mDataActivity[i]);
pw.println("mDataConnectionState=" + mDataConnectionState[i]);
- pw.println("mCellLocation=" + mCellLocation[i]);
+ pw.println("mCellIdentity=" + mCellIdentity[i]);
pw.println("mCellInfo=" + mCellInfo.get(i));
pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i));
pw.println("mSrvccState=" + mSrvccState[i]);
@@ -2166,13 +2222,32 @@
Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
Bundle data = new Bundle();
- signalStrength.fillInNotifierBundle(data);
+ fillInSignalStrengthNotifierBundle(signalStrength, data);
intent.putExtras(data);
intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
+ private void fillInSignalStrengthNotifierBundle(SignalStrength signalStrength, Bundle bundle) {
+ List<CellSignalStrength> cellSignalStrengths = signalStrength.getCellSignalStrengths();
+ for (CellSignalStrength cellSignalStrength : cellSignalStrengths) {
+ if (cellSignalStrength instanceof CellSignalStrengthLte) {
+ bundle.putParcelable("Lte", (CellSignalStrengthLte) cellSignalStrength);
+ } else if (cellSignalStrength instanceof CellSignalStrengthCdma) {
+ bundle.putParcelable("Cdma", (CellSignalStrengthCdma) cellSignalStrength);
+ } else if (cellSignalStrength instanceof CellSignalStrengthGsm) {
+ bundle.putParcelable("Gsm", (CellSignalStrengthGsm) cellSignalStrength);
+ } else if (cellSignalStrength instanceof CellSignalStrengthWcdma) {
+ bundle.putParcelable("Wcdma", (CellSignalStrengthWcdma) cellSignalStrength);
+ } else if (cellSignalStrength instanceof CellSignalStrengthTdscdma) {
+ bundle.putParcelable("Tdscdma", (CellSignalStrengthTdscdma) cellSignalStrength);
+ } else if (cellSignalStrength instanceof CellSignalStrengthNr) {
+ bundle.putParcelable("Nr", (CellSignalStrengthNr) cellSignalStrength);
+ }
+ }
+ }
+
/**
* Broadcasts an intent notifying apps of a phone state change. {@code subId} can be
* a valid subId, in which case this function fires a subId-specific intent, or it
@@ -2209,7 +2284,7 @@
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
}
// If the phoneId is invalid, the broadcast is for overall call state.
- if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
+ if (phoneId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
}
@@ -2259,19 +2334,12 @@
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
- private void broadcastDataConnectionFailed(String apnType, int subId) {
- Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
- intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
- intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
private void enforceNotifyPermissionOrCarrierPrivilege(String method) {
if (checkNotifyPermission()) {
return;
}
- TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
+ TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext,
SubscriptionManager.getDefaultSubscriptionId(), method);
}
@@ -2290,8 +2358,8 @@
== PackageManager.PERMISSION_GRANTED;
}
- private boolean checkListenerPermission(
- int events, int subId, String callingPackage, String message) {
+ private boolean checkListenerPermission(int events, int subId, String callingPackage,
+ @Nullable String callingFeatureId, String message) {
LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder =
new LocationAccessPolicy.LocationPermissionQuery.Builder()
.setCallingPackage(callingPackage)
@@ -2326,14 +2394,20 @@
if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mContext, subId, callingPackage, message)) {
+ mContext, subId, callingPackage, callingFeatureId, message)) {
return false;
}
}
if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
+ // check if calling app has either permission READ_PRECISE_PHONE_STATE
+ // or with carrier privileges
+ try {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
+ } catch (SecurityException se) {
+ TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, subId, message);
+ }
}
if ((events & READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK) != 0) {
@@ -2351,16 +2425,6 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
}
- if ((events & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
- }
-
- if ((events & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
- }
-
if ((events & PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
@@ -2371,11 +2435,6 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
}
- if ((events & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
- }
-
return true;
}
@@ -2488,11 +2547,14 @@
if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
try {
- SignalStrength signalStrength = mSignalStrength[phoneId];
- if (DBG) {
- log("checkPossibleMissNotify: onSignalStrengthsChanged SS=" + signalStrength);
+ if (mSignalStrength[phoneId] != null) {
+ SignalStrength signalStrength = mSignalStrength[phoneId];
+ if (DBG) {
+ log("checkPossibleMissNotify: onSignalStrengthsChanged SS="
+ + signalStrength);
+ }
+ r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
}
- r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -2500,14 +2562,16 @@
if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
- int gsmSignalStrength = mSignalStrength[phoneId]
- .getGsmSignalStrength();
- if (DBG) {
- log("checkPossibleMissNotify: onSignalStrengthChanged SS=" +
- gsmSignalStrength);
+ if (mSignalStrength[phoneId] != null) {
+ int gsmSignalStrength = mSignalStrength[phoneId]
+ .getGsmSignalStrength();
+ if (DBG) {
+ log("checkPossibleMissNotify: onSignalStrengthChanged SS="
+ + gsmSignalStrength);
+ }
+ r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+ : gsmSignalStrength));
}
- r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
- : gsmSignalStrength));
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -2567,10 +2631,13 @@
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
- if (DBG_LOC) log("checkPossibleMissNotify: onCellLocationChanged mCellLocation = "
- + mCellLocation[phoneId]);
+ if (DBG_LOC) {
+ log("checkPossibleMissNotify: onCellLocationChanged mCellIdentity = "
+ + mCellIdentity[phoneId]);
+ }
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onCellLocationChanged(new Bundle(mCellLocation[phoneId]));
+ // null will be translated to empty CellLocation object in client.
+ r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
}
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
@@ -2653,8 +2720,14 @@
return "TD_SCDMA";
case TelephonyManager.NETWORK_TYPE_IWLAN:
return "IWLAN";
- case TelephonyManager.NETWORK_TYPE_LTE_CA:
- return "LTE_CA";
+
+ //TODO: This network type is marked as hidden because it is not a
+ // true network type and we are looking to remove it completely from the available list
+ // of network types. Since this method is only used for logging, in the event that this
+ // network type is selected, the log will read as "Unknown."
+ //case TelephonyManager.NETWORK_TYPE_LTE_CA:
+ // return "LTE_CA";
+
case TelephonyManager.NETWORK_TYPE_NR:
return "NR";
default:
@@ -2675,4 +2748,18 @@
private static CallQuality createCallQuality() {
return new CallQuality(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
+
+ private int getPhoneIdFromSubId(int subId) {
+ SubscriptionManager subManager = (SubscriptionManager)
+ mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ if (subManager == null) return INVALID_SIM_SLOT_INDEX;
+
+ if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ subId = SubscriptionManager.getDefaultSubscriptionId();
+ }
+
+ SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
+ if (info == null) return INVALID_SIM_SLOT_INDEX;
+ return info.getSimSlotIndex();
+ }
}
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index d19d2dd..a7e36b2 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -219,7 +219,7 @@
// Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up
// resources, even for binder death or unwanted calls.
synchronized (mTestNetworkTracker) {
- mTestNetworkTracker.remove(netId);
+ mTestNetworkTracker.remove(network.netId);
}
}
}
@@ -338,7 +338,7 @@
callingUid,
binder);
- mTestNetworkTracker.put(agent.netId, agent);
+ mTestNetworkTracker.put(agent.network.netId, agent);
}
} catch (SocketException e) {
throw new UncheckedIOException(e);
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index a1480e3..e7179e0 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -60,7 +60,6 @@
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.DebugUtils;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.StatsLog;
@@ -162,8 +161,7 @@
private int mHapticFeedbackIntensity;
private int mNotificationIntensity;
private int mRingIntensity;
- private SparseArray<Pair<VibrationEffect, AudioAttributes>> mAlwaysOnEffects =
- new SparseArray<>();
+ private SparseArray<Vibration> mAlwaysOnEffects = new SparseArray<>();
static native boolean vibratorExists();
static native void vibratorInit();
@@ -477,6 +475,10 @@
Settings.System.getUriFor(Settings.System.RING_VIBRATION_INTENSITY),
true, mSettingObserver, UserHandle.USER_ALL);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ZEN_MODE),
+ true, mSettingObserver, UserHandle.USER_ALL);
+
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -524,7 +526,8 @@
}
@Override // Binder call
- public boolean setAlwaysOnEffect(int id, VibrationEffect effect, AudioAttributes attrs) {
+ public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect,
+ AudioAttributes attrs) {
if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) {
throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission");
}
@@ -534,8 +537,8 @@
}
if (effect == null) {
synchronized (mLock) {
- mAlwaysOnEffects.delete(id);
- vibratorAlwaysOnDisable(id);
+ mAlwaysOnEffects.delete(alwaysOnId);
+ vibratorAlwaysOnDisable(alwaysOnId);
}
} else {
if (!verifyVibrationEffect(effect)) {
@@ -545,14 +548,11 @@
Slog.e(TAG, "Only prebaked effects supported for always-on.");
return false;
}
- if (attrs == null) {
- attrs = new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_UNKNOWN)
- .build();
- }
+ attrs = fixupVibrationAttributes(attrs);
synchronized (mLock) {
- mAlwaysOnEffects.put(id, Pair.create(effect, attrs));
- updateAlwaysOnLocked(id, effect, attrs);
+ Vibration vib = new Vibration(null, effect, attrs, uid, opPkg, null);
+ mAlwaysOnEffects.put(alwaysOnId, vib);
+ updateAlwaysOnLocked(alwaysOnId, vib);
}
}
return true;
@@ -592,6 +592,25 @@
return true;
}
+ private AudioAttributes fixupVibrationAttributes(AudioAttributes attrs) {
+ if (attrs == null) {
+ attrs = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_UNKNOWN)
+ .build();
+ }
+ if (shouldBypassDnd(attrs)) {
+ if (!(hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ || hasPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ || hasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
+ final int flags = attrs.getAllFlags()
+ & ~AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
+ attrs = new AudioAttributes.Builder(attrs).replaceFlags(flags).build();
+ }
+ }
+
+ return attrs;
+ }
+
private static long[] getLongIntArray(Resources r, int resid) {
int[] ar = r.getIntArray(resid);
if (ar == null) {
@@ -621,21 +640,7 @@
return;
}
- if (attrs == null) {
- attrs = new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_UNKNOWN)
- .build();
- }
-
- if (shouldBypassDnd(attrs)) {
- if (!(hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
- || hasPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- || hasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
- final int flags = attrs.getAllFlags()
- & ~AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
- attrs = new AudioAttributes.Builder(attrs).replaceFlags(flags).build();
- }
- }
+ attrs = fixupVibrationAttributes(attrs);
// If our current vibration is longer than the new vibration and is the same amplitude,
// then just let the current one finish.
@@ -796,29 +801,8 @@
private void startVibrationLocked(final Vibration vib) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationLocked");
try {
- if (!isAllowedToVibrateLocked(vib)) {
- return;
- }
-
final int intensity = getCurrentIntensityLocked(vib);
- if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
- return;
- }
-
- if (vib.isRingtone() && !shouldVibrateForRingtone()) {
- if (DEBUG) {
- Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
- }
- return;
- }
-
- final int mode = getAppOpMode(vib);
- if (mode != AppOpsManager.MODE_ALLOWED) {
- if (mode == AppOpsManager.MODE_ERRORED) {
- // We might be getting calls from within system_server, so we don't actually
- // want to throw a SecurityException here.
- Slog.w(TAG, "Would be an error: vibrate from uid " + vib.uid);
- }
+ if (!shouldVibrate(vib, intensity)) {
return;
}
applyVibrationIntensityScalingLocked(vib, intensity);
@@ -985,6 +969,35 @@
return mode;
}
+ private boolean shouldVibrate(Vibration vib, int intensity) {
+ if (!isAllowedToVibrateLocked(vib)) {
+ return false;
+ }
+
+ if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ return false;
+ }
+
+ if (vib.isRingtone() && !shouldVibrateForRingtone()) {
+ if (DEBUG) {
+ Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
+ }
+ return false;
+ }
+
+ final int mode = getAppOpMode(vib);
+ if (mode != AppOpsManager.MODE_ALLOWED) {
+ if (mode == AppOpsManager.MODE_ERRORED) {
+ // We might be getting calls from within system_server, so we don't actually
+ // want to throw a SecurityException here.
+ Slog.w(TAG, "Would be an error: vibrate from uid " + vib.uid);
+ }
+ return false;
+ }
+
+ return true;
+ }
+
@GuardedBy("mLock")
private void reportFinishVibrationLocked() {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "reportFinishVibrationLocked");
@@ -1096,14 +1109,12 @@
mVibrator.getDefaultRingVibrationIntensity(), UserHandle.USER_CURRENT);
}
- private void updateAlwaysOnLocked(int id, VibrationEffect effect, AudioAttributes attrs) {
- // TODO: Check DND and LowPower settings
- final Vibration vib = new Vibration(null, effect, attrs, 0, null, null);
+ private void updateAlwaysOnLocked(int id, Vibration vib) {
final int intensity = getCurrentIntensityLocked(vib);
- if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ if (!shouldVibrate(vib, intensity)) {
vibratorAlwaysOnDisable(id);
} else {
- final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) effect;
+ final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.effect;
final int strength = intensityToEffectStrength(intensity);
vibratorAlwaysOnEnable(id, prebaked.getId(), strength);
}
@@ -1112,8 +1123,8 @@
private void updateAlwaysOnLocked() {
for (int i = 0; i < mAlwaysOnEffects.size(); i++) {
int id = mAlwaysOnEffects.keyAt(i);
- Pair<VibrationEffect, AudioAttributes> pair = mAlwaysOnEffects.valueAt(i);
- updateAlwaysOnLocked(id, pair.first, pair.second);
+ Vibration vib = mAlwaysOnEffects.valueAt(i);
+ updateAlwaysOnLocked(id, vib);
}
}
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 7fd98e0..c125b1b 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -17,6 +17,7 @@
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.debug.AdbManagerInternal;
import android.debug.IAdbManager;
@@ -260,6 +261,30 @@
}
}
+ /**
+ * @return true if the device supports secure ADB over Wi-Fi.
+ * @hide
+ */
+ @Override
+ public boolean isAdbWifiSupported() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.MANAGE_DEBUGGING, "AdbService");
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
+ }
+
+ /**
+ * @return true if the device supports secure ADB over Wi-Fi and device pairing by
+ * QR code.
+ * @hide
+ */
+ @Override
+ public boolean isAdbWifiQrSupported() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.MANAGE_DEBUGGING, "AdbService");
+ return isAdbWifiSupported() && mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_CAMERA_ANY);
+ }
+
private void setAdbEnabled(boolean enable) {
if (DEBUG) Slog.d(TAG, "setAdbEnabled(" + enable + "), mAdbEnabled=" + mAdbEnabled);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1c4f1e3..2af04ae 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5280,7 +5280,7 @@
storageManager.commitChanges();
} catch (Exception e) {
PowerManager pm = (PowerManager)
- mInjector.getContext().getSystemService(Context.POWER_SERVICE);
+ mContext.getSystemService(Context.POWER_SERVICE);
pm.reboot("Checkpoint commit failed");
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index b406ce6..972b106 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2899,33 +2899,37 @@
}
ArraySet<Long> enabled = new ArraySet<>();
ArraySet<Long> disabled = new ArraySet<>();
- switch (toggleValue) {
- case "enable":
- enabled.add(changeId);
- pw.println("Enabled change " + changeId + " for " + packageName + ".");
- CompatibilityChangeConfig overrides =
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled));
- platformCompat.setOverrides(overrides, packageName);
- return 0;
- case "disable":
- disabled.add(changeId);
- pw.println("Disabled change " + changeId + " for " + packageName + ".");
- overrides =
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled));
- platformCompat.setOverrides(overrides, packageName);
- return 0;
- case "reset":
- if (platformCompat.clearOverride(changeId, packageName)) {
- pw.println("Reset change " + changeId + " for " + packageName
- + " to default value.");
- } else {
- pw.println("No override exists for changeId " + changeId + ".");
- }
- return 0;
- default:
- pw.println("Invalid toggle value: '" + toggleValue + "'.");
+ try {
+ switch (toggleValue) {
+ case "enable":
+ enabled.add(changeId);
+ CompatibilityChangeConfig overrides =
+ new CompatibilityChangeConfig(
+ new Compatibility.ChangeConfig(enabled, disabled));
+ platformCompat.setOverrides(overrides, packageName);
+ pw.println("Enabled change " + changeId + " for " + packageName + ".");
+ return 0;
+ case "disable":
+ disabled.add(changeId);
+ overrides =
+ new CompatibilityChangeConfig(
+ new Compatibility.ChangeConfig(enabled, disabled));
+ platformCompat.setOverrides(overrides, packageName);
+ pw.println("Disabled change " + changeId + " for " + packageName + ".");
+ return 0;
+ case "reset":
+ if (platformCompat.clearOverride(changeId, packageName)) {
+ pw.println("Reset change " + changeId + " for " + packageName
+ + " to default value.");
+ } else {
+ pw.println("No override exists for changeId " + changeId + ".");
+ }
+ return 0;
+ default:
+ pw.println("Invalid toggle value: '" + toggleValue + "'.");
+ }
+ } catch (SecurityException e) {
+ pw.println(e.getMessage());
}
return -1;
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index f557976..c2652c0 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -20,6 +20,7 @@
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static android.os.Process.getFreeMemory;
@@ -57,6 +58,8 @@
import android.content.pm.IPackageManager;
import android.content.res.Resources;
import android.graphics.Point;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
import android.os.AppZygote;
import android.os.Binder;
import android.os.Build;
@@ -74,6 +77,7 @@
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
+import android.system.Os;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.EventLog;
@@ -102,6 +106,7 @@
import dalvik.system.VMRuntime;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
@@ -245,6 +250,10 @@
private static final String PROPERTY_USE_APP_IMAGE_STARTUP_CACHE =
"persist.device_config.runtime_native.use_app_image_startup_cache";
+ // The socket path for zygote to send unsolicited msg.
+ // Must keep sync with com_android_internal_os_Zygote.cpp.
+ private static final String UNSOL_ZYGOTE_MSG_SOCKET_PATH = "/data/system/unsolzygotesocket";
+
// Low Memory Killer Daemon command codes.
// These must be kept in sync with lmk_cmd definitions in lmkd.h
//
@@ -388,6 +397,28 @@
private PlatformCompat mPlatformCompat = null;
+ /**
+ * The server socket in system_server, zygote will connect to it
+ * in order to send unsolicited messages to system_server.
+ */
+ private LocalSocket mSystemServerSocketForZygote;
+
+ /**
+ * Maximum number of bytes that an incoming unsolicited zygote message could be.
+ * To be updated if new message type needs to be supported.
+ */
+ private static final int MAX_ZYGOTE_UNSOLICITED_MESSAGE_SIZE = 16;
+
+ /**
+ * The buffer to be used to receive the incoming unsolicited zygote message.
+ */
+ private final byte[] mZygoteUnsolicitedMessage = new byte[MAX_ZYGOTE_UNSOLICITED_MESSAGE_SIZE];
+
+ /**
+ * The buffer to be used to receive the SIGCHLD data, it includes pid/uid/status.
+ */
+ private final int[] mZygoteSigChldMessage = new int[3];
+
interface LmkdKillListener {
/**
* Called when there is a process kill by lmkd.
@@ -645,6 +676,13 @@
}
}
);
+ // Start listening on incoming connections from zygotes.
+ mSystemServerSocketForZygote = createSystemServerSocketForZygote();
+ if (mSystemServerSocketForZygote != null) {
+ sKillHandler.getLooper().getQueue().addOnFileDescriptorEventListener(
+ mSystemServerSocketForZygote.getFileDescriptor(),
+ EVENT_INPUT, this::handleZygoteMessages);
+ }
}
}
@@ -1363,7 +1401,7 @@
final int procCount = procs.size();
for (int i = 0; i < procCount; i++) {
final int procUid = procs.keyAt(i);
- if (UserHandle.isApp(procUid) || !UserHandle.isSameUser(procUid, uid)) {
+ if (!UserHandle.isCore(procUid) || !UserHandle.isSameUser(procUid, uid)) {
// Don't use an app process or different user process for system component.
continue;
}
@@ -3267,4 +3305,66 @@
}
}
}
+
+ private void handleZygoteSigChld(int pid, int uid, int status) {
+ // Just log it now.
+ if (DEBUG_PROCESSES) {
+ Slog.i(TAG, "Got SIGCHLD from zygote: pid=" + pid + ", uid=" + uid
+ + ", status=" + Integer.toHexString(status));
+ }
+ }
+
+ /**
+ * Create a server socket in system_server, zygote will connect to it
+ * in order to send unsolicited messages to system_server.
+ */
+ private LocalSocket createSystemServerSocketForZygote() {
+ // The file system entity for this socket is created with 0666 perms, owned
+ // by system:system. selinux restricts things so that only zygotes can
+ // access it.
+ final File socketFile = new File(UNSOL_ZYGOTE_MSG_SOCKET_PATH);
+ if (socketFile.exists()) {
+ socketFile.delete();
+ }
+
+ LocalSocket serverSocket = null;
+ try {
+ serverSocket = new LocalSocket(LocalSocket.SOCKET_DGRAM);
+ serverSocket.bind(new LocalSocketAddress(
+ UNSOL_ZYGOTE_MSG_SOCKET_PATH, LocalSocketAddress.Namespace.FILESYSTEM));
+ Os.chmod(UNSOL_ZYGOTE_MSG_SOCKET_PATH, 0666);
+ } catch (Exception e) {
+ if (serverSocket != null) {
+ try {
+ serverSocket.close();
+ } catch (IOException ex) {
+ }
+ serverSocket = null;
+ }
+ }
+ return serverSocket;
+ }
+
+ /**
+ * Handle the unsolicited message from zygote.
+ */
+ private int handleZygoteMessages(FileDescriptor fd, int events) {
+ final int eventFd = fd.getInt$();
+ if ((events & EVENT_INPUT) != 0) {
+ // An incoming message from zygote
+ try {
+ final int len = Os.read(fd, mZygoteUnsolicitedMessage, 0,
+ mZygoteUnsolicitedMessage.length);
+ if (len > 0 && mZygoteSigChldMessage.length == Zygote.nativeParseSigChld(
+ mZygoteUnsolicitedMessage, len, mZygoteSigChldMessage)) {
+ handleZygoteSigChld(mZygoteSigChldMessage[0] /* pid */,
+ mZygoteSigChldMessage[1] /* uid */,
+ mZygoteSigChldMessage[2] /* status */);
+ }
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception in reading unsolicited zygote message: " + e);
+ }
+ }
+ return EVENT_INPUT;
+ }
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 314e04c..d45bc72a 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1110,8 +1110,8 @@
return Collections.emptyList();
}
synchronized (this) {
- Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false /* edit */,
- false /* uidMismatchExpected */);
+ Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false /* isPrivileged */,
+ false /* edit */);
if (pkgOps == null) {
return null;
}
@@ -1208,8 +1208,7 @@
private void pruneOp(Op op, int uid, String packageName) {
if (!op.hasAnyTime()) {
- Ops ops = getOpsRawLocked(uid, packageName, false /* edit */,
- false /* uidMismatchExpected */);
+ Ops ops = getOpsRawLocked(uid, packageName, false /* isPrivileged */, false /* edit */);
if (ops != null) {
ops.remove(op.op);
if (ops.size() <= 0) {
@@ -1409,11 +1408,6 @@
}
}
- @Override
- public void setMode(int code, int uid, String packageName, int mode) {
- setMode(code, uid, packageName, mode, true, false);
- }
-
/**
* Sets the mode for a certain op and uid.
*
@@ -1421,19 +1415,25 @@
* @param uid The UID for which to set
* @param packageName The package for which to set
* @param mode The new mode to set
- * @param verifyUid Iff {@code true}, check that the package name belongs to the uid
- * @param isPrivileged Whether the package is privileged. (Only used if {@code verifyUid ==
- * false})
*/
- private void setMode(int code, int uid, @NonNull String packageName, int mode,
- boolean verifyUid, boolean isPrivileged) {
+ @Override
+ public void setMode(int code, int uid, @NonNull String packageName, int mode) {
enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
verifyIncomingOp(code);
ArraySet<ModeCallback> repCbs = null;
code = AppOpsManager.opToSwitch(code);
+
+ boolean isPrivileged;
+ try {
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ } catch (SecurityException e) {
+ Slog.e(TAG, "Cannot setMode", e);
+ return;
+ }
+
synchronized (this) {
UidState uidState = getUidStateLocked(uid, false);
- Op op = getOpLocked(code, uid, packageName, true, verifyUid, isPrivileged);
+ Op op = getOpLocked(code, uid, packageName, isPrivileged, true);
if (op != null) {
if (op.mode != mode) {
op.mode = mode;
@@ -1799,34 +1799,32 @@
}
/**
- * @see #checkOperationUnchecked(int, int, String, boolean, boolean)
- */
- private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
- boolean raw) {
- return checkOperationUnchecked(code, uid, packageName, raw, true);
- }
-
- /**
* Get the mode of an app-op.
*
* @param code The code of the op
* @param uid The uid of the package the op belongs to
* @param packageName The package the op belongs to
* @param raw If the raw state of eval-ed state should be checked.
- * @param verify If the code should check the package belongs to the uid
*
* @return The mode of the op
*/
private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
- boolean raw, boolean verify) {
+ boolean raw) {
if (isOpRestrictedDueToSuspend(code, packageName, uid)) {
return AppOpsManager.MODE_IGNORED;
}
+
+ boolean isPrivileged;
+
+ try {
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ } catch (SecurityException e) {
+ Slog.e(TAG, "checkOperation", e);
+ return AppOpsManager.opToDefaultMode(code);
+ }
+
synchronized (this) {
- if (verify) {
- checkPackage(uid, packageName);
- }
- if (isOpRestrictedLocked(uid, code, packageName)) {
+ if (isOpRestrictedLocked(uid, code, packageName, isPrivileged)) {
return AppOpsManager.MODE_IGNORED;
}
code = AppOpsManager.opToSwitch(code);
@@ -1836,7 +1834,7 @@
final int rawMode = uidState.opModes.get(code);
return raw ? rawMode : uidState.evalMode(code, rawMode);
}
- Op op = getOpLocked(code, uid, packageName, false, verify, false);
+ Op op = getOpLocked(code, uid, packageName, false, false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
@@ -1941,14 +1939,12 @@
@Override
public int checkPackage(int uid, String packageName) {
Preconditions.checkNotNull(packageName);
- synchronized (this) {
- Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
- true /* uidMismatchExpected */);
- if (ops != null) {
- return AppOpsManager.MODE_ALLOWED;
- } else {
- return AppOpsManager.MODE_ERRORED;
- }
+ try {
+ verifyAndGetIsPrivileged(uid, packageName);
+
+ return AppOpsManager.MODE_ALLOWED;
+ } catch (SecurityException ignored) {
+ return AppOpsManager.MODE_ERRORED;
}
}
@@ -2011,9 +2007,16 @@
private int noteOperationUnchecked(int code, int uid, String packageName,
int proxyUid, String proxyPackageName, @OpFlags int flags) {
+ boolean isPrivileged;
+ try {
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ } catch (SecurityException e) {
+ Slog.e(TAG, "noteOperation", e);
+ return AppOpsManager.MODE_ERRORED;
+ }
+
synchronized (this) {
- final Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
- false /* uidMismatchExpected */);
+ final Ops ops = getOpsRawLocked(uid, packageName, isPrivileged, true /* edit */);
if (ops == null) {
scheduleOpNotedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_IGNORED);
@@ -2022,7 +2025,7 @@
return AppOpsManager.MODE_ERRORED;
}
final Op op = getOpLocked(ops, code, true);
- if (isOpRestrictedLocked(uid, code, packageName)) {
+ if (isOpRestrictedLocked(uid, code, packageName, isPrivileged)) {
scheduleOpNotedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_IGNORED);
return AppOpsManager.MODE_IGNORED;
@@ -2181,16 +2184,25 @@
return AppOpsManager.MODE_IGNORED;
}
ClientState client = (ClientState)token;
+
+ boolean isPrivileged;
+ try {
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ } catch (SecurityException e) {
+ Slog.e(TAG, "startOperation", e);
+ return AppOpsManager.MODE_ERRORED;
+ }
+
synchronized (this) {
- final Ops ops = getOpsRawLocked(uid, resolvedPackageName, true /* edit */,
- false /* uidMismatchExpected */);
+ final Ops ops = getOpsRawLocked(uid, resolvedPackageName, isPrivileged,
+ true /* edit */);
if (ops == null) {
if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
+ " package " + resolvedPackageName);
return AppOpsManager.MODE_ERRORED;
}
final Op op = getOpLocked(ops, code, true);
- if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
+ if (isOpRestrictedLocked(uid, code, resolvedPackageName, isPrivileged)) {
return AppOpsManager.MODE_IGNORED;
}
final int switchCode = AppOpsManager.opToSwitch(code);
@@ -2262,8 +2274,17 @@
return;
}
ClientState client = (ClientState) token;
+
+ boolean isPrivileged;
+ try {
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ } catch (SecurityException e) {
+ Slog.e(TAG, "Cannot finishOperation", e);
+ return;
+ }
+
synchronized (this) {
- Op op = getOpLocked(code, uid, resolvedPackageName, true, true, false);
+ Op op = getOpLocked(code, uid, resolvedPackageName, isPrivileged, true);
if (op == null) {
return;
}
@@ -2513,8 +2534,76 @@
uidState.pendingStateCommitTime = 0;
}
- private Ops getOpsRawLocked(int uid, String packageName, boolean edit,
- boolean uidMismatchExpected) {
+ /**
+ * Verify that package belongs to uid and return whether the package is privileged.
+ *
+ * @param uid The uid the package belongs to
+ * @param packageName The package the might belong to the uid
+ *
+ * @return {@code true} iff the package is privileged
+ */
+ private boolean verifyAndGetIsPrivileged(int uid, String packageName) {
+ if (uid == Process.ROOT_UID) {
+ // For backwards compatibility, don't check package name for root UID.
+ return false;
+ }
+
+ // Do not check if uid/packageName is already known
+ synchronized (this) {
+ UidState uidState = mUidStates.get(uid);
+ if (uidState != null && uidState.pkgOps != null) {
+ Ops ops = uidState.pkgOps.get(packageName);
+
+ if (ops != null) {
+ return ops.isPrivileged;
+ }
+ }
+ }
+
+ boolean isPrivileged = false;
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ int pkgUid;
+
+ ApplicationInfo appInfo = LocalServices.getService(PackageManagerInternal.class)
+ .getApplicationInfo(packageName, PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
+ | PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_INSTANT,
+ Process.SYSTEM_UID, UserHandle.getUserId(uid));
+ if (appInfo != null) {
+ pkgUid = appInfo.uid;
+ isPrivileged = (appInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
+ } else {
+ pkgUid = resolveUid(packageName);
+ if (pkgUid >= 0) {
+ isPrivileged = false;
+ }
+ }
+ if (pkgUid != uid) {
+ throw new SecurityException("Specified package " + packageName + " under uid " + uid
+ + " but it is really " + pkgUid);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
+ return isPrivileged;
+ }
+
+ /**
+ * Get (and potentially create) ops.
+ *
+ * @param uid The uid the package belongs to
+ * @param packageName The name of the package
+ * @param isPrivileged If the package is privilidged (ignored if {@code edit} is false)
+ * @param edit If an ops does not exist, create the ops?
+
+ * @return
+ */
+ private Ops getOpsRawLocked(int uid, String packageName, boolean isPrivileged, boolean edit) {
UidState uidState = getUidStateLocked(uid, edit);
if (uidState == null) {
return null;
@@ -2532,47 +2621,6 @@
if (!edit) {
return null;
}
- boolean isPrivileged = false;
- // This is the first time we have seen this package name under this uid,
- // so let's make sure it is valid.
- if (uid != 0) {
- final long ident = Binder.clearCallingIdentity();
- try {
- int pkgUid = -1;
- try {
- ApplicationInfo appInfo = ActivityThread.getPackageManager()
- .getApplicationInfo(packageName,
- PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- UserHandle.getUserId(uid));
- if (appInfo != null) {
- pkgUid = appInfo.uid;
- isPrivileged = (appInfo.privateFlags
- & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
- } else {
- pkgUid = resolveUid(packageName);
- if (pkgUid >= 0) {
- isPrivileged = false;
- }
- }
- } catch (RemoteException e) {
- Slog.w(TAG, "Could not contact PackageManager", e);
- }
- if (pkgUid != uid) {
- // Oops! The package name is not valid for the uid they are calling
- // under. Abort.
- if (!uidMismatchExpected) {
- RuntimeException ex = new RuntimeException("here");
- ex.fillInStackTrace();
- Slog.w(TAG, "Bad call: specified package " + packageName
- + " under uid " + uid + " but it is really " + pkgUid, ex);
- }
- return null;
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
ops = new Ops(packageName, uidState, isPrivileged);
uidState.pkgOps.put(packageName, ops);
}
@@ -2580,7 +2628,7 @@
}
/**
- * Get the state of all ops for a package, <b>don't verify that package belongs to uid</b>.
+ * Get the state of all ops for a package.
*
* <p>Usually callers should use {@link #getOpLocked} and not call this directly.
*
@@ -2638,23 +2686,15 @@
* @param code The code of the op
* @param uid The uid the of the package
* @param packageName The package name for which to get the state for
+ * @param isPrivileged Whether the package is privileged or not (only used if {@code edit
+ * == true})
* @param edit Iff {@code true} create the {@link Op} object if not yet created
- * @param verifyUid Iff {@code true} check that the package belongs to the uid
- * @param isPrivileged Whether the package is privileged or not (only used if {@code verifyUid
- * == false})
*
* @return The {@link Op state} of the op
*/
- private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName, boolean edit,
- boolean verifyUid, boolean isPrivileged) {
- Ops ops;
-
- if (verifyUid) {
- ops = getOpsRawLocked(uid, packageName, edit, false /* uidMismatchExpected */);
- } else {
- ops = getOpsRawNoVerifyLocked(uid, packageName, edit, isPrivileged);
- }
-
+ private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName,
+ boolean isPrivileged, boolean edit) {
+ Ops ops = getOpsRawNoVerifyLocked(uid, packageName, edit, isPrivileged);
if (ops == null) {
return null;
}
@@ -2684,7 +2724,8 @@
return pmi.isPackageSuspended(packageName, UserHandle.getUserId(uid));
}
- private boolean isOpRestrictedLocked(int uid, int code, String packageName) {
+ private boolean isOpRestrictedLocked(int uid, int code, String packageName,
+ boolean isPrivileged) {
int userHandle = UserHandle.getUserId(uid);
final int restrictionSetCount = mOpUserRestrictions.size();
@@ -2696,8 +2737,8 @@
if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
// If we are the system, bypass user restrictions for certain codes
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
- false /* uidMismatchExpected */);
+ Ops ops = getOpsRawLocked(uid, packageName, isPrivileged,
+ true /* edit */);
if ((ops != null) && ops.isPrivileged) {
return false;
}
@@ -3068,7 +3109,7 @@
out.attribute(null, "n", Integer.toString(pkg.getUid()));
synchronized (this) {
Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(),
- false /* edit */, false /* uidMismatchExpected */);
+ false /* isPrivileged */, false /* edit */);
// Should always be present as the list of PackageOps is generated
// from Ops.
if (ops != null) {
@@ -4647,18 +4688,8 @@
}
@Override
- public void setUidMode(int code, int uid, int mode) {
- AppOpsService.this.setUidMode(code, uid, mode);
- }
-
- @Override
public void setAllPkgModesToDefault(int code, int uid) {
AppOpsService.this.setAllPkgModesToDefault(code, uid);
}
-
- @Override
- public @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName) {
- return AppOpsService.this.checkOperationUnchecked(code, uid, packageName, true, false);
- }
}
}
diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING
index a53797d..1a5dac5 100644
--- a/services/core/java/com/android/server/appop/TEST_MAPPING
+++ b/services/core/java/com/android/server/appop/TEST_MAPPING
@@ -10,6 +10,14 @@
"include-filter": "com.android.server.appop"
}
]
+ },
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.appop"
+ }
+ ]
}
]
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 25fdf64..88a63f1 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6292,7 +6292,7 @@
return false;
}
boolean suppress = false;
- if (resolvedStream == DEFAULT_VOL_STREAM_NO_PLAYBACK && mController != null) {
+ if (resolvedStream != AudioSystem.STREAM_MUSIC && mController != null) {
final long now = SystemClock.uptimeMillis();
if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
// ui will become visible
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index cf83dd6..f15d999 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -17,8 +17,10 @@
package com.android.server.compat;
import android.compat.Compatibility.ChangeConfig;
+import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Environment;
+import android.os.RemoteException;
import android.text.TextUtils;
import android.util.LongArray;
import android.util.LongSparseArray;
@@ -26,8 +28,11 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.AndroidBuildClassifier;
import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.compat.CompatibilityChangeInfo;
+import com.android.internal.compat.IOverrideValidator;
+import com.android.internal.compat.OverrideAllowedState;
import com.android.server.compat.config.Change;
import com.android.server.compat.config.XmlParser;
@@ -54,22 +59,14 @@
private static final String TAG = "CompatConfig";
- private static final CompatConfig sInstance = new CompatConfig().initConfigFromLib(
- Environment.buildPath(
- Environment.getRootDirectory(), "etc", "compatconfig"));
-
@GuardedBy("mChanges")
private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
- @VisibleForTesting
- CompatConfig() {
- }
+ private IOverrideValidator mOverrideValidator;
- /**
- * @return The static instance of this class to be used within the system server.
- */
- static CompatConfig get() {
- return sInstance;
+ @VisibleForTesting
+ CompatConfig(AndroidBuildClassifier androidBuildClassifier, Context context) {
+ mOverrideValidator = new OverrideValidatorImpl(androidBuildClassifier, context, this);
}
/**
@@ -159,8 +156,12 @@
* @param enabled If the change should be enabled or disabled.
* @return {@code true} if the change existed before adding the override.
*/
- boolean addOverride(long changeId, String packageName, boolean enabled) {
+ boolean addOverride(long changeId, String packageName, boolean enabled)
+ throws RemoteException, SecurityException {
boolean alreadyKnown = true;
+ OverrideAllowedState allowedState =
+ mOverrideValidator.getOverrideAllowedState(changeId, packageName);
+ allowedState.enforce(changeId, packageName);
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
if (c == null) {
@@ -186,6 +187,20 @@
}
/**
+ * Returns the minimum sdk version for which this change should be enabled (or 0 if it is not
+ * target sdk gated).
+ */
+ int minTargetSdkForChangeId(long changeId) {
+ synchronized (mChanges) {
+ CompatChange c = mChanges.get(changeId);
+ if (c == null) {
+ return 0;
+ }
+ return c.getEnableAfterTargetSdk();
+ }
+ }
+
+ /**
* Removes an override previously added via {@link #addOverride(long, String, boolean)}. This
* restores the default behaviour for the given change and app, once any app processes have been
* restarted.
@@ -194,34 +209,44 @@
* @param packageName The app package name that was overridden.
* @return {@code true} if an override existed;
*/
- boolean removeOverride(long changeId, String packageName) {
+ boolean removeOverride(long changeId, String packageName)
+ throws RemoteException, SecurityException {
boolean overrideExists = false;
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
- if (c != null) {
- overrideExists = true;
- c.removePackageOverride(packageName);
+ try {
+ if (c != null) {
+ OverrideAllowedState allowedState =
+ mOverrideValidator.getOverrideAllowedState(changeId, packageName);
+ allowedState.enforce(changeId, packageName);
+ overrideExists = true;
+ c.removePackageOverride(packageName);
+ }
+ } catch (RemoteException e) {
+ // Should never occur, since validator is in the same process.
+ throw new RuntimeException("Unable to call override validator!", e);
}
}
return overrideExists;
}
/**
- * Overrides the enabled state for a given change and app. This method is intended to be used
- * *only* for debugging purposes.
+ * Overrides the enabled state for a given change and app.
*
* <p>Note, package overrides are not persistent and will be lost on system or runtime restart.
*
* @param overrides list of overrides to default changes config.
* @param packageName app for which the overrides will be applied.
*/
- void addOverrides(CompatibilityChangeConfig overrides, String packageName) {
+ void addOverrides(CompatibilityChangeConfig overrides, String packageName)
+ throws RemoteException, SecurityException {
synchronized (mChanges) {
for (Long changeId : overrides.enabledChanges()) {
addOverride(changeId, packageName, true);
}
for (Long changeId : overrides.disabledChanges()) {
addOverride(changeId, packageName, false);
+
}
}
}
@@ -235,10 +260,22 @@
*
* @param packageName The package for which the overrides should be purged.
*/
- void removePackageOverrides(String packageName) {
+ void removePackageOverrides(String packageName) throws RemoteException, SecurityException {
synchronized (mChanges) {
for (int i = 0; i < mChanges.size(); ++i) {
- mChanges.valueAt(i).removePackageOverride(packageName);
+ try {
+ CompatChange change = mChanges.valueAt(i);
+ OverrideAllowedState allowedState =
+ mOverrideValidator.getOverrideAllowedState(change.getId(),
+ packageName);
+ allowedState.enforce(change.getId(), packageName);
+ if (change != null) {
+ mChanges.valueAt(i).removePackageOverride(packageName);
+ }
+ } catch (RemoteException e) {
+ // Should never occur, since validator is in the same process.
+ throw new RuntimeException("Unable to call override validator!", e);
+ }
}
}
}
@@ -326,17 +363,23 @@
}
}
- CompatConfig initConfigFromLib(File libraryDir) {
+ static CompatConfig create(AndroidBuildClassifier androidBuildClassifier, Context context) {
+ CompatConfig config = new CompatConfig(androidBuildClassifier, context);
+ config.initConfigFromLib(Environment.buildPath(
+ Environment.getRootDirectory(), "etc", "compatconfig"));
+ return config;
+ }
+
+ void initConfigFromLib(File libraryDir) {
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Slog.e(TAG, "No directory " + libraryDir + ", skipping");
- return this;
+ return;
}
for (File f : libraryDir.listFiles()) {
Slog.d(TAG, "Found a config file: " + f.getPath());
//TODO(b/138222363): Handle duplicate ids across config files.
readConfig(f);
}
- return this;
}
private void readConfig(File configFile) {
@@ -350,4 +393,7 @@
}
}
+ IOverrideValidator getOverrideValidator() {
+ return mOverrideValidator;
+ }
}
diff --git a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java
new file mode 100644
index 0000000..4bf606e
--- /dev/null
+++ b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.compat;
+
+import static com.android.internal.compat.OverrideAllowedState.ALLOWED;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_NON_TARGET_SDK;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_NOT_DEBUGGABLE;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_SDK_TOO_HIGH;
+import static com.android.internal.compat.OverrideAllowedState.PACKAGE_DOES_NOT_EXIST;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.AndroidBuildClassifier;
+import com.android.internal.compat.IOverrideValidator;
+import com.android.internal.compat.OverrideAllowedState;
+
+/**
+ * Implementation of the policy for allowing compat change overrides.
+ */
+public class OverrideValidatorImpl extends IOverrideValidator.Stub {
+
+ private AndroidBuildClassifier mAndroidBuildClassifier;
+ private Context mContext;
+ private CompatConfig mCompatConfig;
+
+ @VisibleForTesting
+ OverrideValidatorImpl(AndroidBuildClassifier androidBuildClassifier,
+ Context context, CompatConfig config) {
+ mAndroidBuildClassifier = androidBuildClassifier;
+ mContext = context;
+ mCompatConfig = config;
+ }
+
+ @Override
+ public OverrideAllowedState getOverrideAllowedState(long changeId, String packageName) {
+ boolean debuggableBuild = false;
+ boolean finalBuild = false;
+ int minTargetSdk = mCompatConfig.minTargetSdkForChangeId(changeId);
+
+ debuggableBuild = mAndroidBuildClassifier.isDebuggableBuild();
+ finalBuild = mAndroidBuildClassifier.isFinalBuild();
+
+ // Allow any override for userdebug or eng builds.
+ if (debuggableBuild) {
+ return new OverrideAllowedState(ALLOWED, -1, -1);
+ }
+ PackageManager packageManager = mContext.getPackageManager();
+ if (packageManager == null) {
+ throw new IllegalStateException("No PackageManager!");
+ }
+ ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = packageManager.getApplicationInfo(packageName, 0);
+ } catch (NameNotFoundException e) {
+ return new OverrideAllowedState(PACKAGE_DOES_NOT_EXIST, -1, -1);
+ }
+ int appTargetSdk = applicationInfo.targetSdkVersion;
+ // Only allow overriding debuggable apps.
+ if ((applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
+ return new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1);
+ }
+ // Allow overriding any change for debuggable apps on non-final builds.
+ if (!finalBuild) {
+ return new OverrideAllowedState(ALLOWED, appTargetSdk, minTargetSdk);
+ }
+ // Do not allow overriding non-target sdk gated changes on user builds
+ if (minTargetSdk == -1) {
+ return new OverrideAllowedState(DISABLED_NON_TARGET_SDK, appTargetSdk, minTargetSdk);
+ }
+ // Only allow to opt-in for a targetSdk gated change.
+ if (applicationInfo.targetSdkVersion < minTargetSdk) {
+ return new OverrideAllowedState(ALLOWED, appTargetSdk, minTargetSdk);
+ }
+ return new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, appTargetSdk, minTargetSdk);
+ }
+}
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 4a3d7d6..029b7bc 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -27,9 +27,12 @@
import android.util.Slog;
import android.util.StatsLog;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.AndroidBuildClassifier;
import com.android.internal.compat.ChangeReporter;
import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.compat.CompatibilityChangeInfo;
+import com.android.internal.compat.IOverrideValidator;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.util.DumpUtils;
@@ -45,11 +48,21 @@
private final Context mContext;
private final ChangeReporter mChangeReporter;
+ private final CompatConfig mCompatConfig;
public PlatformCompat(Context context) {
mContext = context;
mChangeReporter = new ChangeReporter(
StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__SOURCE__SYSTEM_SERVER);
+ mCompatConfig = CompatConfig.create(new AndroidBuildClassifier(), mContext);
+ }
+
+ @VisibleForTesting
+ PlatformCompat(Context context, CompatConfig compatConfig) {
+ mContext = context;
+ mChangeReporter = new ChangeReporter(
+ StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__SOURCE__SYSTEM_SERVER);
+ mCompatConfig = compatConfig;
}
@Override
@@ -74,7 +87,7 @@
@Override
public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
- if (CompatConfig.get().isChangeEnabled(changeId, appInfo)) {
+ if (mCompatConfig.isChangeEnabled(changeId, appInfo)) {
reportChange(changeId, appInfo.uid,
StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
return true;
@@ -121,57 +134,59 @@
* otherwise.
*/
public boolean registerListener(long changeId, CompatChange.ChangeListener listener) {
- return CompatConfig.get().registerListener(changeId, listener);
+ return mCompatConfig.registerListener(changeId, listener);
}
@Override
- public void setOverrides(CompatibilityChangeConfig overrides, String packageName) {
- CompatConfig.get().addOverrides(overrides, packageName);
+ public void setOverrides(CompatibilityChangeConfig overrides, String packageName)
+ throws RemoteException, SecurityException {
+ mCompatConfig.addOverrides(overrides, packageName);
killPackage(packageName);
}
@Override
- public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) {
- CompatConfig.get().addOverrides(overrides, packageName);
+ public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName)
+ throws RemoteException, SecurityException {
+ mCompatConfig.addOverrides(overrides, packageName);
}
@Override
- public void clearOverrides(String packageName) {
- CompatConfig config = CompatConfig.get();
- config.removePackageOverrides(packageName);
+ public void clearOverrides(String packageName) throws RemoteException, SecurityException {
+ mCompatConfig.removePackageOverrides(packageName);
killPackage(packageName);
}
@Override
- public void clearOverridesForTest(String packageName) {
- CompatConfig config = CompatConfig.get();
- config.removePackageOverrides(packageName);
+ public void clearOverridesForTest(String packageName)
+ throws RemoteException, SecurityException {
+ mCompatConfig.removePackageOverrides(packageName);
}
@Override
- public boolean clearOverride(long changeId, String packageName) {
- boolean existed = CompatConfig.get().removeOverride(changeId, packageName);
+ public boolean clearOverride(long changeId, String packageName)
+ throws RemoteException, SecurityException {
+ boolean existed = mCompatConfig.removeOverride(changeId, packageName);
killPackage(packageName);
return existed;
}
@Override
public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) {
- return CompatConfig.get().getAppConfig(appInfo);
+ return mCompatConfig.getAppConfig(appInfo);
}
@Override
public CompatibilityChangeInfo[] listAllChanges() {
- return CompatConfig.get().dumpChanges();
+ return mCompatConfig.dumpChanges();
}
/**
* Check whether the change is known to the compat config.
- * @param changeId
+ *
* @return {@code true} if the change is known.
*/
public boolean isKnownChangeId(long changeId) {
- return CompatConfig.get().isKnownChangeId(changeId);
+ return mCompatConfig.isKnownChangeId(changeId);
}
@@ -181,11 +196,11 @@
*
* @param appInfo The app in question
* @return A sorted long array of change IDs. We use a primitive array to minimize memory
- * footprint: Every app process will store this array statically so we aim to reduce
- * overhead as much as possible.
+ * footprint: Every app process will store this array statically so we aim to reduce
+ * overhead as much as possible.
*/
public long[] getDisabledChanges(ApplicationInfo appInfo) {
- return CompatConfig.get().getDisabledChanges(appInfo);
+ return mCompatConfig.getDisabledChanges(appInfo);
}
/**
@@ -195,18 +210,24 @@
* @return The change ID, or {@code -1} if no change with that name exists.
*/
public long lookupChangeId(String name) {
- return CompatConfig.get().lookupChangeId(name);
+ return mCompatConfig.lookupChangeId(name);
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
- CompatConfig.get().dumpConfig(pw);
+ mCompatConfig.dumpConfig(pw);
+ }
+
+ @Override
+ public IOverrideValidator getOverrideValidator() {
+ return mCompatConfig.getOverrideValidator();
}
/**
* Clears information stored about events reported on behalf of an app.
* To be called once upon app start or end. A second call would be a no-op.
+ *
* @param appInfo the app to reset
*/
public void resetReporting(ApplicationInfo appInfo) {
diff --git a/services/core/java/com/android/server/connectivity/DataConnectionStats.java b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
index 1b1c546..5010e46 100644
--- a/services/core/java/com/android/server/connectivity/DataConnectionStats.java
+++ b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
@@ -16,6 +16,9 @@
package com.android.server.connectivity;
+import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
+import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -24,6 +27,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
@@ -91,7 +95,10 @@
boolean visible = (simReadyOrUnknown || isCdma()) // we only check the sim state for GSM
&& hasService()
&& mDataState == TelephonyManager.DATA_CONNECTED;
- int networkType = mServiceState.getDataNetworkType();
+ NetworkRegistrationInfo regInfo =
+ mServiceState.getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN);
+ int networkType = regInfo == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN
+ : regInfo.getAccessNetworkTechnology();
if (DEBUG) Log.d(TAG, String.format("Noting data connection for network type %s: %svisible",
networkType, visible ? "" : "not "));
try {
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 9bae902..af8a366 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -39,11 +39,11 @@
import android.annotation.Nullable;
import android.content.Context;
import android.net.ISocketKeepaliveCallback;
+import android.net.InvalidPacketException;
import android.net.KeepalivePacketData;
import android.net.NattKeepalivePacketData;
import android.net.NetworkAgent;
import android.net.NetworkUtils;
-import android.net.SocketKeepalive.InvalidPacketException;
import android.net.SocketKeepalive.InvalidSocketException;
import android.net.TcpKeepalivePacketData;
import android.net.util.IpUtils;
@@ -657,7 +657,10 @@
final TcpKeepalivePacketData packet;
try {
packet = TcpKeepaliveController.getTcpKeepalivePacket(fd);
- } catch (InvalidPacketException | InvalidSocketException e) {
+ } catch (InvalidSocketException e) {
+ notifyErrorCallback(cb, e.error);
+ return;
+ } catch (InvalidPacketException e) {
notifyErrorCallback(cb, e.error);
return;
}
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 6fa999c..04c792a 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -26,6 +26,7 @@
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN;
@@ -46,19 +47,18 @@
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
import android.net.NetworkStats;
import android.net.NetworkTemplate;
-import android.net.StringNetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.Uri;
import android.os.BestClock;
import android.os.Handler;
import android.os.SystemClock;
-import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.TelephonyManager;
-import android.util.DataUnit;
import android.util.DebugUtils;
-import android.util.Pair;
import android.util.Range;
import android.util.Slog;
@@ -74,7 +74,6 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
-import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@@ -185,7 +184,6 @@
// Track information on mobile networks as they come and go.
class MultipathTracker {
final Network network;
- final int subId;
final String subscriberId;
private long mQuota;
@@ -198,13 +196,14 @@
public MultipathTracker(Network network, NetworkCapabilities nc) {
this.network = network;
this.mNetworkCapabilities = new NetworkCapabilities(nc);
- try {
- subId = Integer.parseInt(
- ((StringNetworkSpecifier) nc.getNetworkSpecifier()).toString());
- } catch (ClassCastException | NullPointerException | NumberFormatException e) {
+ NetworkSpecifier specifier = nc.getNetworkSpecifier();
+ int subId = INVALID_SUBSCRIPTION_ID;
+ if (specifier instanceof TelephonyNetworkSpecifier) {
+ subId = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
+ } else {
throw new IllegalStateException(String.format(
- "Can't get subId from mobile network %s (%s): %s",
- network, nc, e.getMessage()));
+ "Can't get subId from mobile network %s (%s)",
+ network, nc));
}
TelephonyManager tele = mContext.getSystemService(TelephonyManager.class);
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index aea6d8d..f636d67 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -116,7 +116,8 @@
&& !lp.hasIpv4Address();
// If the network tells us it doesn't use clat, respect that.
- final boolean skip464xlat = (nai.netMisc() != null) && nai.netMisc().skip464xlat;
+ final boolean skip464xlat = (nai.netAgentConfig() != null)
+ && nai.netAgentConfig().skip464xlat;
return supported && connected && isIpv6OnlyNetwork && !skip464xlat;
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 5e085ca..d66aec5 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -23,9 +23,9 @@
import android.net.INetworkMonitor;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
-import android.net.NetworkMisc;
import android.net.NetworkMonitorManager;
import android.net.NetworkRequest;
import android.net.NetworkScore;
@@ -127,7 +127,7 @@
// This should only be modified by ConnectivityService, via setNetworkCapabilities().
// TODO: make this private with a getter.
public NetworkCapabilities networkCapabilities;
- public final NetworkMisc networkMisc;
+ public final NetworkAgentConfig networkAgentConfig;
// Indicates if netd has been told to create this Network. From this point on the appropriate
// routing rules are setup and routes are added so packets can begin flowing over the Network.
// This is a sticky bit; once set it is never cleared.
@@ -261,7 +261,7 @@
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
LinkProperties lp, NetworkCapabilities nc, @NonNull NetworkScore ns, Context context,
- Handler handler, NetworkMisc misc, ConnectivityService connService, INetd netd,
+ Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) {
this.messenger = messenger;
asyncChannel = ac;
@@ -274,7 +274,7 @@
mConnService = connService;
mContext = context;
mHandler = handler;
- networkMisc = misc;
+ networkAgentConfig = config;
this.factorySerialNumber = factorySerialNumber;
}
@@ -309,8 +309,8 @@
return mConnService;
}
- public NetworkMisc netMisc() {
- return networkMisc;
+ public NetworkAgentConfig netAgentConfig() {
+ return networkAgentConfig;
}
public Handler handler() {
@@ -451,15 +451,6 @@
&& !isLingering();
}
- /**
- * Returns whether this network is currently suspended. A network is suspended if it is still
- * connected but data temporarily fails to transfer. See {@link NetworkInfo.State#SUSPENDED}
- * and {@link NetworkCapabilities#NET_CAPABILITY_NOT_SUSPENDED}.
- */
- public boolean isSuspended() {
- return networkInfo.getState() == NetworkInfo.State.SUSPENDED;
- }
-
// Does this network satisfy request?
public boolean satisfies(NetworkRequest request) {
return created &&
@@ -487,7 +478,8 @@
// selected and we're trying to see what its score could be. This ensures that we don't tear
// down an explicitly selected network before the user gets a chance to prefer it when
// a higher-scoring network (e.g., Ethernet) is available.
- if (networkMisc.explicitlySelected && (networkMisc.acceptUnvalidated || pretendValidated)) {
+ if (networkAgentConfig.explicitlySelected
+ && (networkAgentConfig.acceptUnvalidated || pretendValidated)) {
return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
}
@@ -533,7 +525,8 @@
synchronized (this) {
// Network objects are outwardly immutable so there is no point in duplicating.
// Duplicating also precludes sharing socket factories and connection pools.
- final String subscriberId = (networkMisc != null) ? networkMisc.subscriberId : null;
+ final String subscriberId = (networkAgentConfig != null)
+ ? networkAgentConfig.subscriberId : null;
return new NetworkState(new NetworkInfo(networkInfo),
new LinkProperties(linkProperties),
new NetworkCapabilities(networkCapabilities), network, subscriberId, null);
@@ -641,13 +634,13 @@
+ "nc{" + networkCapabilities + "} Score{" + getCurrentScore() + "} "
+ "everValidated{" + everValidated + "} lastValidated{" + lastValidated + "} "
+ "created{" + created + "} lingering{" + isLingering() + "} "
- + "explicitlySelected{" + networkMisc.explicitlySelected + "} "
- + "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} "
+ + "explicitlySelected{" + networkAgentConfig.explicitlySelected + "} "
+ + "acceptUnvalidated{" + networkAgentConfig.acceptUnvalidated + "} "
+ "everCaptivePortalDetected{" + everCaptivePortalDetected + "} "
+ "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} "
+ "captivePortalValidationPending{" + captivePortalValidationPending + "} "
+ "partialConnectivity{" + partialConnectivity + "} "
- + "acceptPartialConnectivity{" + networkMisc.acceptPartialConnectivity + "} "
+ + "acceptPartialConnectivity{" + networkAgentConfig.acceptPartialConnectivity + "} "
+ "clat{" + clatd + "} "
+ "}";
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 2179518..2c41557 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -28,7 +28,7 @@
import android.content.Intent;
import android.content.res.Resources;
import android.net.NetworkSpecifier;
-import android.net.StringNetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
import android.net.wifi.WifiInfo;
import android.os.UserHandle;
import android.telephony.SubscriptionManager;
@@ -223,14 +223,8 @@
// name has been added to it
NetworkSpecifier specifier = nai.networkCapabilities.getNetworkSpecifier();
int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
- if (specifier instanceof StringNetworkSpecifier) {
- try {
- subId = Integer.parseInt(
- ((StringNetworkSpecifier) specifier).specifier);
- } catch (NumberFormatException e) {
- Slog.e(TAG, "NumberFormatException on "
- + ((StringNetworkSpecifier) specifier).specifier);
- }
+ if (specifier instanceof TelephonyNetworkSpecifier) {
+ subId = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
}
details = mTelephonyManager.createForSubscriptionId(subId)
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
index e570ef1e..1129899 100644
--- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
@@ -30,8 +30,8 @@
import static android.system.OsConstants.TIOCOUTQ;
import android.annotation.NonNull;
+import android.net.InvalidPacketException;
import android.net.NetworkUtils;
-import android.net.SocketKeepalive.InvalidPacketException;
import android.net.SocketKeepalive.InvalidSocketException;
import android.net.TcpKeepalivePacketData;
import android.net.TcpKeepalivePacketDataParcelable;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 09790c4..69ab47a 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -53,11 +53,11 @@
import android.net.LocalSocketAddress;
import android.net.Network;
import android.net.NetworkAgent;
+import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
-import android.net.NetworkFactory;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
-import android.net.NetworkMisc;
+import android.net.NetworkProvider;
import android.net.RouteInfo;
import android.net.UidRange;
import android.net.VpnService;
@@ -848,7 +848,7 @@
}
public int getNetId() {
- return mNetworkAgent != null ? mNetworkAgent.netId : NETID_UNSET;
+ return mNetworkAgent != null ? mNetworkAgent.network.netId : NETID_UNSET;
}
private LinkProperties makeLinkProperties() {
@@ -914,7 +914,7 @@
* has certain changes, in which case this method would just return {@code false}.
*/
private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) {
- // NetworkMisc cannot be updated without registering a new NetworkAgent.
+ // NetworkAgentConfig cannot be updated without registering a new NetworkAgent.
if (oldConfig.allowBypass != mConfig.allowBypass) {
Log.i(TAG, "Handover not possible due to changes to allowBypass");
return false;
@@ -947,8 +947,8 @@
mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null);
- NetworkMisc networkMisc = new NetworkMisc();
- networkMisc.allowBypass = mConfig.allowBypass && !mLockdown;
+ NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
+ networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown;
mNetworkCapabilities.setEstablishingVpnAppUid(Binder.getCallingUid());
mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserHandle,
@@ -957,8 +957,8 @@
try {
mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE /* logtag */,
mNetworkInfo, mNetworkCapabilities, lp,
- ConnectivityConstants.VPN_DEFAULT_SCORE, networkMisc,
- NetworkFactory.SerialNumber.VPN) {
+ ConnectivityConstants.VPN_DEFAULT_SCORE, networkAgentConfig,
+ NetworkProvider.ID_VPN) {
@Override
public void unwanted() {
// We are user controlled, not driven by NetworkRequest.
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index fa8c48b..a89daff 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -86,7 +86,7 @@
import android.os.UserManager;
import android.os.WorkSource;
import android.provider.Settings;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
@@ -1987,9 +1987,7 @@
if (time == 0) {
return "N/A";
}
- Time tobj = new Time();
- tobj.set(time);
- return tobj.format("%Y-%m-%d %H:%M:%S");
+ return TimeMigrationUtils.formatMillisWithFixedFormat(time);
}
private final static Comparator<SyncOperation> sOpDumpComparator = (op1, op2) -> {
@@ -2555,9 +2553,7 @@
accountKey = "Unknown";
}
final long elapsedTime = item.elapsedTime;
- final Time time = new Time();
final long eventTime = item.eventTime;
- time.set(eventTime);
final String key = authorityName + "/" + accountKey;
final Long lastEventTime = lastTimeMap.get(key);
@@ -2622,9 +2618,7 @@
authorityName = "Unknown";
accountKey = "Unknown";
}
- final Time time = new Time();
final long eventTime = item.eventTime;
- time.set(eventTime);
pw.printf(" #%-3d: %s %8s ",
i + 1,
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 1fc0db3..6dcfade 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -76,7 +76,7 @@
private static final int GLOBAL_ID = -1;
// The tolerance within which we consider something approximately equals.
- private static final float EPSILON = 0.001f;
+ private static final float EPSILON = 0.01f;
private final Object mLock = new Object();
private final Context mContext;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 6330270..69cbc22 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -3454,7 +3454,7 @@
}
/**
- * This is kept due to {@link android.annotation.UnsupportedAppUsage} in
+ * This is kept due to {@link android.compat.annotation.UnsupportedAppUsage} in
* {@link InputMethodManager#getInputMethodWindowVisibleHeight()} and a dependency in
* {@link InputMethodService#onCreate()}.
*
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index eb5d472..e655b35 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -29,7 +29,7 @@
import android.net.Uri;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
@@ -1643,17 +1643,13 @@
if (numFailures != 0) {
pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures);
}
- final Time t = new Time();
- final String format = "%Y-%m-%d %H:%M:%S";
if (mLastSuccessfulRunTime != 0) {
pw.print(prefix); pw.print("Last successful run: ");
- t.set(mLastSuccessfulRunTime);
- pw.println(t.format(format));
+ pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastSuccessfulRunTime));
}
if (mLastFailedRunTime != 0) {
pw.print(prefix); pw.print("Last failed run: ");
- t.set(mLastFailedRunTime);
- pw.println(t.format(format));
+ pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastFailedRunTime));
}
}
diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java
index ababad9..97df557 100644
--- a/services/core/java/com/android/server/job/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -325,8 +325,7 @@
&& !wouldBeReadyWithConstraintLocked(
job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
if (DEBUG) {
- Slog.i(TAG,
- "Skipping " + job + " because delay won't make it ready.");
+ Slog.i(TAG, "Skipping " + job + " because delay won't make it ready.");
}
continue;
}
@@ -385,7 +384,8 @@
/**
* Set an alarm with the {@link android.app.AlarmManager} for the next time at which a job's
* delay will expire.
- * This alarm <b>will</b> wake up the phone.
+ * This alarm <b>will not</b> wake up the phone if
+ * {@link TcConstants#USE_NON_WAKEUP_ALARM_FOR_DELAY} is true.
*/
private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, WorkSource ws) {
alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
@@ -393,8 +393,11 @@
return;
}
mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis;
- updateAlarmWithListenerLocked(DELAY_TAG, mNextDelayExpiredListener,
- mNextDelayExpiredElapsedMillis, ws);
+ final int alarmType =
+ mTcConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY
+ ? AlarmManager.ELAPSED_REALTIME : AlarmManager.ELAPSED_REALTIME_WAKEUP;
+ updateAlarmWithListenerLocked(DELAY_TAG, alarmType,
+ mNextDelayExpiredListener, mNextDelayExpiredElapsedMillis, ws);
}
/**
@@ -408,16 +411,16 @@
return;
}
mNextJobExpiredElapsedMillis = alarmTimeElapsedMillis;
- updateAlarmWithListenerLocked(DEADLINE_TAG, mDeadlineExpiredListener,
- mNextJobExpiredElapsedMillis, ws);
+ updateAlarmWithListenerLocked(DEADLINE_TAG, AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ mDeadlineExpiredListener, mNextJobExpiredElapsedMillis, ws);
}
private long maybeAdjustAlarmTime(long proposedAlarmTimeElapsedMillis) {
return Math.max(proposedAlarmTimeElapsedMillis, sElapsedRealtimeClock.millis());
}
- private void updateAlarmWithListenerLocked(String tag, OnAlarmListener listener,
- long alarmTimeElapsed, WorkSource ws) {
+ private void updateAlarmWithListenerLocked(String tag, @AlarmManager.AlarmType int alarmType,
+ OnAlarmListener listener, long alarmTimeElapsed, WorkSource ws) {
ensureAlarmServiceLocked();
if (alarmTimeElapsed == Long.MAX_VALUE) {
mAlarmService.cancel(listener);
@@ -425,7 +428,7 @@
if (DEBUG) {
Slog.d(TAG, "Setting " + tag + " for: " + alarmTimeElapsed);
}
- mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTimeElapsed,
+ mAlarmService.set(alarmType, alarmTimeElapsed,
AlarmManager.WINDOW_HEURISTIC, 0, tag, listener, null, ws);
}
}
@@ -464,8 +467,11 @@
private final KeyValueListParser mParser = new KeyValueListParser(',');
private static final String KEY_SKIP_NOT_READY_JOBS = "skip_not_ready_jobs";
+ private static final String KEY_USE_NON_WAKEUP_ALARM_FOR_DELAY =
+ "use_non_wakeup_delay_alarm";
private static final boolean DEFAULT_SKIP_NOT_READY_JOBS = true;
+ private static final boolean DEFAULT_USE_NON_WAKEUP_ALARM_FOR_DELAY = true;
/**
* Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
@@ -474,6 +480,12 @@
public boolean SKIP_NOT_READY_JOBS = DEFAULT_SKIP_NOT_READY_JOBS;
/**
+ * Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
+ * ready now.
+ */
+ public boolean USE_NON_WAKEUP_ALARM_FOR_DELAY = DEFAULT_USE_NON_WAKEUP_ALARM_FOR_DELAY;
+
+ /**
* Creates a content observer.
*
* @param handler The handler to run {@link #onChange} on, or null if none.
@@ -510,6 +522,12 @@
recheckAlarmsLocked();
}
}
+
+ USE_NON_WAKEUP_ALARM_FOR_DELAY = mParser.getBoolean(
+ KEY_USE_NON_WAKEUP_ALARM_FOR_DELAY, DEFAULT_USE_NON_WAKEUP_ALARM_FOR_DELAY);
+ // Intentionally not calling checkExpiredDelaysAndResetAlarm() here. There's no need to
+ // iterate through the entire list again for this constant change. The next delay alarm
+ // that is set will make use of the new constant value.
}
private void dump(IndentingPrintWriter pw) {
@@ -517,12 +535,16 @@
pw.println("TimeController:");
pw.increaseIndent();
pw.printPair(KEY_SKIP_NOT_READY_JOBS, SKIP_NOT_READY_JOBS).println();
+ pw.printPair(KEY_USE_NON_WAKEUP_ALARM_FOR_DELAY,
+ USE_NON_WAKEUP_ALARM_FOR_DELAY).println();
pw.decreaseIndent();
}
private void dump(ProtoOutputStream proto) {
final long tcToken = proto.start(ConstantsProto.TIME_CONTROLLER);
proto.write(ConstantsProto.TimeController.SKIP_NOT_READY_JOBS, SKIP_NOT_READY_JOBS);
+ proto.write(ConstantsProto.TimeController.USE_NON_WAKEUP_ALARM_FOR_DELAY,
+ USE_NON_WAKEUP_ALARM_FOR_DELAY);
proto.end(tcToken);
}
}
diff --git a/services/core/java/com/android/server/location/NtpTimeHelper.java b/services/core/java/com/android/server/location/NtpTimeHelper.java
index 296b500..88e9b50 100644
--- a/services/core/java/com/android/server/location/NtpTimeHelper.java
+++ b/services/core/java/com/android/server/location/NtpTimeHelper.java
@@ -130,7 +130,8 @@
// force refresh NTP cache when outdated
boolean refreshSuccess = true;
- if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
+ NtpTrustedTime.TimeResult ntpResult = mNtpTime.getCachedTimeResult();
+ if (ntpResult == null || ntpResult.getAgeMillis() >= NTP_INTERVAL) {
// Blocking network operation.
refreshSuccess = mNtpTime.forceRefresh();
}
@@ -140,17 +141,17 @@
// only update when NTP time is fresh
// If refreshSuccess is false, cacheAge does not drop down.
- if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
- long time = mNtpTime.getCachedNtpTime();
- long timeReference = mNtpTime.getCachedNtpTimeReference();
- long certainty = mNtpTime.getCacheCertainty();
+ ntpResult = mNtpTime.getCachedTimeResult();
+ if (ntpResult != null && ntpResult.getAgeMillis() < NTP_INTERVAL) {
+ long time = ntpResult.getTimeMillis();
+ long timeReference = ntpResult.getElapsedRealtimeMillis();
+ long certainty = ntpResult.getCertaintyMillis();
if (DEBUG) {
long now = System.currentTimeMillis();
Log.d(TAG, "NTP server returned: "
- + time + " (" + new Date(time)
- + ") reference: " + timeReference
- + " certainty: " + certainty
+ + time + " (" + new Date(time) + ")"
+ + " ntpResult: " + ntpResult
+ " system time offset: " + (time - now));
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 7f650ee..b24a938 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -18,8 +18,10 @@
import static com.android.server.net.NetworkPolicyManagerService.isUidNetworkingBlockedInternal;
+import android.annotation.NonNull;
import android.net.Network;
import android.net.NetworkTemplate;
+import android.net.netstats.provider.AbstractNetworkStatsProvider;
import android.telephony.SubscriptionPlan;
import java.util.Set;
@@ -126,4 +128,12 @@
*/
public abstract void setMeteredRestrictedPackagesAsync(
Set<String> packageNames, int userId);
+
+ /**
+ * Notifies that any of the {@link AbstractNetworkStatsProvider} has reached its quota
+ * which was set through {@link AbstractNetworkStatsProvider#setLimit(String, long)}.
+ *
+ * @param tag the human readable identifier of the custom network stats provider.
+ */
+ public abstract void onStatsProviderLimitReached(@NonNull String tag);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index e3e6d9d..9760185 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -75,6 +75,7 @@
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.net.netstats.provider.AbstractNetworkStatsProvider.QUOTA_UNLIMITED;
import static android.os.Trace.TRACE_TAG_NETWORK;
import static android.provider.Settings.Global.NETPOLICY_OVERRIDE_ENABLED;
import static android.provider.Settings.Global.NETPOLICY_QUOTA_ENABLED;
@@ -160,7 +161,7 @@
import android.net.NetworkState;
import android.net.NetworkStats;
import android.net.NetworkTemplate;
-import android.net.StringNetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
import android.net.TrafficStats;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
@@ -168,6 +169,7 @@
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IDeviceIdleController;
import android.os.INetworkManagementService;
@@ -227,7 +229,6 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
import com.android.internal.util.StatLogger;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
@@ -388,6 +389,8 @@
private static final int MSG_SUBSCRIPTION_OVERRIDE = 16;
private static final int MSG_METERED_RESTRICTED_PACKAGES_CHANGED = 17;
private static final int MSG_SET_NETWORK_TEMPLATE_ENABLED = 18;
+ private static final int MSG_SUBSCRIPTION_PLANS_CHANGED = 19;
+ private static final int MSG_STATS_PROVIDER_LIMIT_REACHED = 20;
private static final int UID_MSG_STATE_CHANGED = 100;
private static final int UID_MSG_GONE = 101;
@@ -874,7 +877,8 @@
// Listen for subscriber changes
mContext.getSystemService(SubscriptionManager.class).addOnSubscriptionsChangedListener(
- new OnSubscriptionsChangedListener(mHandler.getLooper()) {
+ new HandlerExecutor(mHandler),
+ new OnSubscriptionsChangedListener() {
@Override
public void onSubscriptionsChanged() {
updateNetworksInternal();
@@ -2867,17 +2871,6 @@
}
@Override
- public void onTetheringChanged(String iface, boolean tethering) {
- // No need to enforce permission because setRestrictBackground() will do it.
- synchronized (mUidRulesFirstLock) {
- if (mRestrictBackground && tethering) {
- Log.d(TAG, "Tethering on (" + iface +"); disable Data Saver");
- setRestrictBackground(false);
- }
- }
- }
-
- @Override
public void setRestrictBackground(boolean restrictBackground) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setRestrictBackground");
try {
@@ -3038,12 +3031,13 @@
// Verify they're not lying about package name
mAppOps.checkPackage(callingUid, callingPackage);
+ final SubscriptionManager sm;
final SubscriptionInfo si;
final PersistableBundle config;
final long token = Binder.clearCallingIdentity();
try {
- si = mContext.getSystemService(SubscriptionManager.class)
- .getActiveSubscriptionInfo(subId);
+ sm = mContext.getSystemService(SubscriptionManager.class);
+ si = sm.getActiveSubscriptionInfo(subId);
config = mCarrierConfigManager.getConfigForSubId(subId);
} finally {
Binder.restoreCallingIdentity(token);
@@ -3051,7 +3045,7 @@
// First check: is caller the CarrierService?
if (si != null) {
- if (si.isEmbedded() && si.canManageSubscription(mContext, callingPackage)) {
+ if (si.isEmbedded() && sm.canManageSubscription(si, callingPackage)) {
return;
}
}
@@ -3091,6 +3085,34 @@
mContext.enforceCallingOrSelfPermission(MANAGE_SUBSCRIPTION_PLANS, TAG);
}
+ private void enforceSubscriptionPlanValidity(SubscriptionPlan[] plans) {
+ // nothing to check if no plans
+ if (plans.length == 0) {
+ return;
+ }
+
+ long applicableNetworkTypes = 0;
+ boolean allNetworks = false;
+ for (SubscriptionPlan plan : plans) {
+ if (plan.getNetworkTypes() == null) {
+ allNetworks = true;
+ } else {
+ if ((applicableNetworkTypes & plan.getNetworkTypesBitMask()) != 0) {
+ throw new IllegalArgumentException(
+ "Multiple subscription plans defined for a single network type.");
+ } else {
+ applicableNetworkTypes |= plan.getNetworkTypesBitMask();
+ }
+ }
+ }
+
+ // ensure at least one plan applies for every network type
+ if (!allNetworks) {
+ throw new IllegalArgumentException(
+ "No generic subscription plan that applies to all network types.");
+ }
+ }
+
@Override
public SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
@@ -3255,6 +3277,7 @@
@Override
public void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
+ enforceSubscriptionPlanValidity(plans);
for (SubscriptionPlan plan : plans) {
Objects.requireNonNull(plan);
@@ -3283,6 +3306,8 @@
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
mContext.sendBroadcast(intent, android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS);
+ mHandler.sendMessage(
+ mHandler.obtainMessage(MSG_SUBSCRIPTION_PLANS_CHANGED, subId, 0, plans));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -4476,6 +4501,16 @@
}
}
+ private void dispatchSubscriptionPlansChanged(INetworkPolicyListener listener, int subId,
+ SubscriptionPlan[] plans) {
+ if (listener != null) {
+ try {
+ listener.onSubscriptionPlansChanged(subId, plans);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
@@ -4501,19 +4536,36 @@
mListeners.finishBroadcast();
return true;
}
- case MSG_LIMIT_REACHED: {
- final String iface = (String) msg.obj;
+ case MSG_STATS_PROVIDER_LIMIT_REACHED: {
+ mNetworkStats.forceUpdate();
synchronized (mNetworkPoliciesSecondLock) {
- if (mMeteredIfaces.contains(iface)) {
- // force stats update to make sure we have
- // numbers that caused alert to trigger.
- mNetworkStats.forceUpdate();
-
- updateNetworkEnabledNL();
- updateNotificationsNL();
+ // Some providers might hit the limit reached event prior to others. Thus,
+ // re-calculate and update interface quota for every provider is needed.
+ updateNetworkRulesNL();
+ updateNetworkEnabledNL();
+ updateNotificationsNL();
+ }
+ return true;
+ }
+ case MSG_LIMIT_REACHED: {
+ final String iface = (String) msg.obj;
+ synchronized (mNetworkPoliciesSecondLock) {
+ // fast return if not needed.
+ if (!mMeteredIfaces.contains(iface)) {
+ return true;
}
}
+
+ // force stats update to make sure the service have the numbers that caused
+ // alert to trigger.
+ mNetworkStats.forceUpdate();
+
+ synchronized (mNetworkPoliciesSecondLock) {
+ updateNetworkRulesNL();
+ updateNetworkEnabledNL();
+ updateNotificationsNL();
+ }
return true;
}
case MSG_RESTRICT_BACKGROUND_CHANGED: {
@@ -4556,14 +4608,18 @@
return true;
}
case MSG_UPDATE_INTERFACE_QUOTA: {
- removeInterfaceQuota((String) msg.obj);
+ final String iface = (String) msg.obj;
// int params need to be stitched back into a long
- setInterfaceQuota((String) msg.obj,
- ((long) msg.arg1 << 32) | (msg.arg2 & 0xFFFFFFFFL));
+ final long quota = ((long) msg.arg1 << 32) | (msg.arg2 & 0xFFFFFFFFL);
+ removeInterfaceQuota(iface);
+ setInterfaceQuota(iface, quota);
+ mNetworkStats.setStatsProviderLimit(iface, quota);
return true;
}
case MSG_REMOVE_INTERFACE_QUOTA: {
- removeInterfaceQuota((String) msg.obj);
+ final String iface = (String) msg.obj;
+ removeInterfaceQuota(iface);
+ mNetworkStats.setStatsProviderLimit(iface, QUOTA_UNLIMITED);
return true;
}
case MSG_RESET_FIREWALL_RULES_BY_UID: {
@@ -4594,6 +4650,17 @@
setNetworkTemplateEnabledInner(template, enabled);
return true;
}
+ case MSG_SUBSCRIPTION_PLANS_CHANGED: {
+ final SubscriptionPlan[] plans = (SubscriptionPlan[]) msg.obj;
+ final int subId = msg.arg1;
+ final int length = mListeners.beginBroadcast();
+ for (int i = 0; i < length; i++) {
+ final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+ dispatchSubscriptionPlansChanged(listener, subId, plans);
+ }
+ mListeners.finishBroadcast();
+ return true;
+ }
default: {
return false;
}
@@ -5203,6 +5270,12 @@
mHandler.obtainMessage(MSG_METERED_RESTRICTED_PACKAGES_CHANGED,
userId, 0, packageNames).sendToTarget();
}
+
+ @Override
+ public void onStatsProviderLimitReached(@NonNull String tag) {
+ Log.v(TAG, "onStatsProviderLimitReached: " + tag);
+ mHandler.obtainMessage(MSG_STATS_PROVIDER_LIMIT_REACHED).sendToTarget();
+ }
}
private void setMeteredRestrictedPackagesInternal(Set<String> packageNames, int userId) {
@@ -5231,16 +5304,12 @@
}
private int parseSubId(NetworkState state) {
- // TODO: moved to using a legitimate NetworkSpecifier instead of string parsing
int subId = INVALID_SUBSCRIPTION_ID;
if (state != null && state.networkCapabilities != null
&& state.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
NetworkSpecifier spec = state.networkCapabilities.getNetworkSpecifier();
- if (spec instanceof StringNetworkSpecifier) {
- try {
- subId = Integer.parseInt(((StringNetworkSpecifier) spec).specifier);
- } catch (NumberFormatException e) {
- }
+ if (spec instanceof TelephonyNetworkSpecifier) {
+ subId = ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
}
}
return subId;
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 3ca1803..22b01be 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -229,7 +229,7 @@
entry.txPackets += reader.nextLong();
}
- stats.addValues(entry);
+ stats.addEntry(entry);
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
@@ -279,7 +279,7 @@
entry.txBytes = reader.nextLong();
entry.txPackets = reader.nextLong();
- stats.addValues(entry);
+ stats.addEntry(entry);
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
@@ -439,7 +439,7 @@
if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface))
&& (limitUid == UID_ALL || limitUid == entry.uid)
&& (limitTag == TAG_ALL || limitTag == entry.tag)) {
- stats.addValues(entry);
+ stats.addEntry(entry);
}
reader.finishLine();
diff --git a/services/core/java/com/android/server/net/NetworkStatsManagerInternal.java b/services/core/java/com/android/server/net/NetworkStatsManagerInternal.java
index 4843ede..6d72cb5 100644
--- a/services/core/java/com/android/server/net/NetworkStatsManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkStatsManagerInternal.java
@@ -16,6 +16,7 @@
package com.android.server.net;
+import android.annotation.NonNull;
import android.net.NetworkStats;
import android.net.NetworkTemplate;
@@ -34,4 +35,10 @@
/** Force update of statistics. */
public abstract void forceUpdate();
+
+ /**
+ * Set the quota limit to all registered custom network stats providers.
+ * Note that invocation of any interface will be sent to all providers.
+ */
+ public abstract void setStatsProviderLimit(@NonNull String iface, long quota);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index a41fb7d..fc39a25 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
+import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.content.Intent.ACTION_SHUTDOWN;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.ACTION_USER_REMOVED;
@@ -27,6 +28,7 @@
import static android.net.NetworkStack.checkNetworkStackPermission;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.IFACE_VT;
import static android.net.NetworkStats.INTERFACES_ALL;
import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.ROAMING_ALL;
@@ -70,6 +72,7 @@
import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.usage.NetworkStatsManager;
@@ -96,6 +99,9 @@
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.TrafficStats;
+import android.net.netstats.provider.INetworkStatsProvider;
+import android.net.netstats.provider.INetworkStatsProviderCallback;
+import android.net.netstats.provider.NetworkStatsProviderCallback;
import android.os.BestClock;
import android.os.Binder;
import android.os.DropBoxManager;
@@ -108,6 +114,7 @@
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -175,7 +182,7 @@
* This avoids firing the global alert too often on devices with high transfer speeds and
* high quota.
*/
- private static final int PERFORM_POLL_DELAY_MS = 1000;
+ private static final int DEFAULT_PERFORM_POLL_DELAY_MS = 1000;
private static final String TAG_NETSTATS_ERROR = "netstats_error";
@@ -211,13 +218,15 @@
/**
* Virtual network interface for video telephony. This is for VT data usage counting purpose.
*/
- public static final String VT_INTERFACE = "vt_data0";
+ // TODO: Remove this after no one is using it.
+ public static final String VT_INTERFACE = NetworkStats.IFACE_VT;
/**
* Settings that can be changed externally.
*/
public interface NetworkStatsSettings {
public long getPollInterval();
+ public long getPollDelay();
public boolean getSampleEnabled();
public boolean getAugmentEnabled();
@@ -246,6 +255,7 @@
}
private final Object mStatsLock = new Object();
+ private final Object mStatsProviderLock = new Object();
/** Set of currently active ifaces. */
@GuardedBy("mStatsLock")
@@ -270,6 +280,9 @@
private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
new DropBoxNonMonotonicObserver();
+ private final RemoteCallbackList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList =
+ new RemoteCallbackList<>();
+
@GuardedBy("mStatsLock")
private NetworkStatsRecorder mDevRecorder;
@GuardedBy("mStatsLock")
@@ -500,9 +513,9 @@
}
/**
- * Register for a global alert that is delivered through
- * {@link INetworkManagementEventObserver} once a threshold amount of data
- * has been transferred.
+ * Register for a global alert that is delivered through {@link INetworkManagementEventObserver}
+ * or {@link NetworkStatsProviderCallback#onAlertReached()} once a threshold amount of data has
+ * been transferred.
*/
private void registerGlobalAlert() {
try {
@@ -512,6 +525,7 @@
} catch (RemoteException e) {
// ignored; service lives in system_server
}
+ invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setAlert(mGlobalAlertBytes));
}
@Override
@@ -712,7 +726,7 @@
final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
final NetworkStats stats = new NetworkStats(end - start, 1);
- stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
+ stats.addEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets,
entry.txBytes, entry.txPackets, entry.operations));
return stats;
@@ -801,8 +815,7 @@
@Override
public void incrementOperationCount(int uid, int tag, int operationCount) {
if (Binder.getCallingUid() != uid) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.UPDATE_DEVICE_STATS, TAG);
+ mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
}
if (operationCount < 0) {
@@ -1093,7 +1106,7 @@
/**
* Observer that watches for {@link INetworkManagementService} alerts.
*/
- private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
+ private final INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
@Override
public void limitReached(String limitName, String iface) {
// only someone like NMS should be calling us
@@ -1104,7 +1117,7 @@
// such a call pending; UID stats are handled during normal polling interval.
if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
- PERFORM_POLL_DELAY_MS);
+ mSettings.getPollDelay());
}
}
}
@@ -1179,8 +1192,8 @@
ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
ident.getRoaming(), true /* metered */,
true /* onDefaultNetwork */);
- findOrCreateNetworkIdentitySet(mActiveIfaces, VT_INTERFACE).add(vtIdent);
- findOrCreateNetworkIdentitySet(mActiveUidIfaces, VT_INTERFACE).add(vtIdent);
+ findOrCreateNetworkIdentitySet(mActiveIfaces, IFACE_VT).add(vtIdent);
+ findOrCreateNetworkIdentitySet(mActiveUidIfaces, IFACE_VT).add(vtIdent);
}
if (isMobile) {
@@ -1250,6 +1263,14 @@
xtSnapshot.combineAllValues(tetherSnapshot);
devSnapshot.combineAllValues(tetherSnapshot);
+ // Snapshot for dev/xt stats from all custom stats providers. Counts per-interface data
+ // from stats providers that isn't already counted by dev and XT stats.
+ Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotStatsProvider");
+ final NetworkStats providersnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
+ Trace.traceEnd(TRACE_TAG_NETWORK);
+ xtSnapshot.combineAllValues(providersnapshot);
+ devSnapshot.combineAllValues(providersnapshot);
+
// For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
// can't be reattributed to responsible apps.
Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev");
@@ -1353,6 +1374,10 @@
performSampleLocked();
}
+ // request asynchronous stats update from all providers for next poll.
+ // TODO: request with a valid token.
+ invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.requestStatsUpdate(0 /* unused */));
+
// finally, dispatch updated event to any listeners
final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -1474,6 +1499,12 @@
public void forceUpdate() {
NetworkStatsService.this.forceUpdate();
}
+
+ @Override
+ public void setStatsProviderLimit(@NonNull String iface, long quota) {
+ Slog.v(TAG, "setStatsProviderLimit(" + iface + "," + quota + ")");
+ invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setLimit(iface, quota));
+ }
}
@Override
@@ -1688,6 +1719,12 @@
uidSnapshot.combineAllValues(vtStats);
}
+ // get a stale copy of uid stats snapshot provided by providers.
+ final NetworkStats providerStats = getNetworkStatsFromProviders(STATS_PER_UID);
+ providerStats.filter(UID_ALL, ifaces, TAG_ALL);
+ mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats, mUseBpfTrafficStats);
+ uidSnapshot.combineAllValues(providerStats);
+
uidSnapshot.combineAllValues(mUidOperations);
return uidSnapshot;
@@ -1724,6 +1761,152 @@
}
}
+ /**
+ * Registers a custom provider of {@link android.net.NetworkStats} to combine the network
+ * statistics that cannot be seen by the kernel to system. To unregister, invoke the
+ * {@code unregister()} of the returned callback.
+ *
+ * @param tag a human readable identifier of the custom network stats provider.
+ * @param provider the binder interface of
+ * {@link android.net.netstats.provider.AbstractNetworkStatsProvider} that
+ * needs to be registered to the system.
+ *
+ * @return a binder interface of
+ * {@link android.net.netstats.provider.NetworkStatsProviderCallback}, which can be
+ * used to report events to the system.
+ */
+ public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider(
+ @NonNull String tag, @NonNull INetworkStatsProvider provider) {
+ mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
+ Objects.requireNonNull(provider, "provider is null");
+ Objects.requireNonNull(tag, "tag is null");
+ try {
+ NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl(
+ tag, provider, mAlertObserver, mStatsProviderCbList);
+ mStatsProviderCbList.register(callback);
+ Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid="
+ + getCallingUid() + "/" + getCallingPid());
+ return callback;
+ } catch (RemoteException e) {
+ Log.e(TAG, "registerNetworkStatsProvider failed", e);
+ }
+ return null;
+ }
+
+ // Collect stats from local cache of providers.
+ private @NonNull NetworkStats getNetworkStatsFromProviders(int how) {
+ final NetworkStats ret = new NetworkStats(0L, 0);
+ invokeForAllStatsProviderCallbacks((cb) -> ret.combineAllValues(cb.getCachedStats(how)));
+ return ret;
+ }
+
+ @FunctionalInterface
+ private interface ThrowingConsumer<S, T extends Throwable> {
+ void accept(S s) throws T;
+ }
+
+ private void invokeForAllStatsProviderCallbacks(
+ @NonNull ThrowingConsumer<NetworkStatsProviderCallbackImpl, RemoteException> task) {
+ synchronized (mStatsProviderCbList) {
+ final int length = mStatsProviderCbList.beginBroadcast();
+ try {
+ for (int i = 0; i < length; i++) {
+ final NetworkStatsProviderCallbackImpl cb =
+ mStatsProviderCbList.getBroadcastItem(i);
+ try {
+ task.accept(cb);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e);
+ }
+ }
+ } finally {
+ mStatsProviderCbList.finishBroadcast();
+ }
+ }
+ }
+
+ private static class NetworkStatsProviderCallbackImpl extends INetworkStatsProviderCallback.Stub
+ implements IBinder.DeathRecipient {
+ @NonNull final String mTag;
+ @NonNull private final Object mProviderStatsLock = new Object();
+ @NonNull final INetworkStatsProvider mProvider;
+ @NonNull final INetworkManagementEventObserver mAlertObserver;
+ @NonNull final RemoteCallbackList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList;
+
+ @GuardedBy("mProviderStatsLock")
+ // STATS_PER_IFACE and STATS_PER_UID
+ private final NetworkStats mIfaceStats = new NetworkStats(0L, 0);
+ @GuardedBy("mProviderStatsLock")
+ private final NetworkStats mUidStats = new NetworkStats(0L, 0);
+
+ NetworkStatsProviderCallbackImpl(
+ @NonNull String tag, @NonNull INetworkStatsProvider provider,
+ @NonNull INetworkManagementEventObserver alertObserver,
+ @NonNull RemoteCallbackList<NetworkStatsProviderCallbackImpl> cbList)
+ throws RemoteException {
+ mTag = tag;
+ mProvider = provider;
+ mProvider.asBinder().linkToDeath(this, 0);
+ mAlertObserver = alertObserver;
+ mStatsProviderCbList = cbList;
+ }
+
+ @NonNull
+ public NetworkStats getCachedStats(int how) {
+ synchronized (mProviderStatsLock) {
+ NetworkStats stats;
+ switch (how) {
+ case STATS_PER_IFACE:
+ stats = mIfaceStats;
+ break;
+ case STATS_PER_UID:
+ stats = mUidStats;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid type: " + how);
+ }
+ // Return a defensive copy instead of local reference.
+ return stats.clone();
+ }
+ }
+
+ @Override
+ public void onStatsUpdated(int token, @Nullable NetworkStats ifaceStats,
+ @Nullable NetworkStats uidStats) {
+ // TODO: 1. Use token to map ifaces to correct NetworkIdentity.
+ // 2. Store the difference and store it directly to the recorder.
+ synchronized (mProviderStatsLock) {
+ if (ifaceStats != null) mIfaceStats.combineAllValues(ifaceStats);
+ if (uidStats != null) mUidStats.combineAllValues(uidStats);
+ }
+ }
+
+ @Override
+ public void onAlertReached() throws RemoteException {
+ mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */);
+ }
+
+ @Override
+ public void onLimitReached() {
+ Log.d(TAG, mTag + ": onLimitReached");
+ LocalServices.getService(NetworkPolicyManagerInternal.class)
+ .onStatsProviderLimitReached(mTag);
+ }
+
+ @Override
+ public void binderDied() {
+ Log.d(TAG, mTag + ": binderDied");
+ mStatsProviderCbList.unregister(this);
+ }
+
+ @Override
+ public void unregister() {
+ Log.d(TAG, mTag + ": unregister");
+ mStatsProviderCbList.unregister(this);
+ }
+
+ }
+
@VisibleForTesting
static class HandlerCallback implements Handler.Callback {
private final NetworkStatsService mService;
@@ -1813,6 +1996,10 @@
return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
}
@Override
+ public long getPollDelay() {
+ return DEFAULT_PERFORM_POLL_DELAY_MS;
+ }
+ @Override
public long getGlobalAlertBytes(long def) {
return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
}
diff --git a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
index 9c1ac34..947405e 100644
--- a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
+++ b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
@@ -56,16 +56,17 @@
// for any device / profile owner checks. The majority of requests for the serial number
// should use the getSerialForPackage method with the calling package specified.
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
- /* callingPackage */ null, "getSerial")) {
+ /* callingPackage */ null, null, "getSerial")) {
return Build.UNKNOWN;
}
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
}
@Override
- public @Nullable String getSerialForPackage(String callingPackage) throws RemoteException {
+ public @Nullable String getSerialForPackage(String callingPackage,
+ String callingFeatureId) throws RemoteException {
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
- callingPackage, "getSerial")) {
+ callingPackage, callingFeatureId, "getSerial")) {
return Build.UNKNOWN;
}
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index e991a91..609a415 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1159,7 +1159,7 @@
}
abandonSession = false;
- if (!params.sessionParams.isStaged || !params.waitForStagedSessionReady) {
+ if (!params.sessionParams.isStaged || !params.mWaitForStagedSessionReady) {
pw.println("Success");
return 0;
}
@@ -1197,7 +1197,7 @@
+ si.getStagedSessionErrorMessage() + "]");
return 1;
}
- pw.println("Success");
+ pw.println("Success. Reboot device to apply staged session");
return 0;
} finally {
if (abandonSession) {
@@ -2487,7 +2487,7 @@
SessionParams sessionParams;
String installerPackageName;
int userId = UserHandle.USER_ALL;
- boolean waitForStagedSessionReady = false;
+ boolean mWaitForStagedSessionReady = true;
long timeoutMs = DEFAULT_WAIT_MS;
}
@@ -2615,13 +2615,16 @@
sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
break;
case "--wait":
- params.waitForStagedSessionReady = true;
+ params.mWaitForStagedSessionReady = true;
try {
params.timeoutMs = Long.parseLong(peekNextArg());
getNextArg();
} catch (NumberFormatException ignore) {
}
break;
+ case "--no-wait":
+ params.mWaitForStagedSessionReady = false;
+ break;
default:
throw new IllegalArgumentException("Unknown option " + opt);
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 2d8a2ac..ebba128 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -79,7 +79,7 @@
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.text.TextUtils;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.KeyValueListParser;
@@ -3981,9 +3981,7 @@
}
static String formatTime(long time) {
- Time tobj = new Time();
- tobj.set(time);
- return tobj.format("%Y-%m-%d %H:%M:%S");
+ return TimeMigrationUtils.formatMillisWithFixedFormat(time);
}
private void dumpCurrentTime(PrintWriter pw) {
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 2705455..349a003 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -41,6 +41,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.os.ParcelableException;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -414,29 +415,28 @@
} else {
params.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;
}
- int apkSessionId = mPi.createSession(
- params, originalSession.getInstallerPackageName(),
- 0 /* UserHandle.SYSTEM */);
- PackageInstallerSession apkSession = mPi.getSession(apkSessionId);
-
try {
+ int apkSessionId = mPi.createSession(
+ params, originalSession.getInstallerPackageName(),
+ 0 /* UserHandle.SYSTEM */);
+ PackageInstallerSession apkSession = mPi.getSession(apkSessionId);
apkSession.open();
for (String apkFilePath : apkFilePaths) {
File apkFile = new File(apkFilePath);
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(apkFile,
ParcelFileDescriptor.MODE_READ_ONLY);
- long sizeBytes = pfd.getStatSize();
+ long sizeBytes = (pfd == null) ? -1 : pfd.getStatSize();
if (sizeBytes < 0) {
Slog.e(TAG, "Unable to get size of: " + apkFilePath);
return null;
}
apkSession.write(apkFile.getName(), 0, sizeBytes, pfd);
}
- } catch (IOException e) {
+ return apkSession;
+ } catch (IOException | ParcelableException e) {
Slog.e(TAG, "Failure to install APK staged session " + originalSession.sessionId, e);
return null;
}
- return apkSession;
}
private boolean commitApkSession(@NonNull PackageInstallerSession apkSession,
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index f56231f..9e86a4b 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -229,6 +229,7 @@
// If the dex file is the primary apk (or a split) and not isUsedByOtherApps
// do not record it. This case does not bring any new usable information
// and can be safely skipped.
+ dexPathIndex++;
continue;
}
diff --git a/services/core/java/com/android/server/stats/OWNERS b/services/core/java/com/android/server/stats/OWNERS
index 8d7f882..fc7fd22 100644
--- a/services/core/java/com/android/server/stats/OWNERS
+++ b/services/core/java/com/android/server/stats/OWNERS
@@ -1,9 +1,8 @@
-bookatz@google.com
-cjyu@google.com
-dwchen@google.com
+jeffreyhuang@google.com
joeo@google.com
+muhammadq@google.com
+ruchirr@google.com
singhtejinder@google.com
-stlafon@google.com
+tsaichristine@google.com
yaochen@google.com
-yanglu@google.com
-yro@google.com
\ No newline at end of file
+yro@google.com
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 172367a..b7d6360 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.app.timedetector.ITimeDetectorService;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
import android.content.ContentResolver;
import android.content.Context;
@@ -105,6 +106,14 @@
mHandler.post(() -> mTimeDetectorStrategy.suggestManualTime(timeSignal));
}
+ @Override
+ public void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSignal) {
+ enforceSuggestNetworkTimePermission();
+ Objects.requireNonNull(timeSignal);
+
+ mHandler.post(() -> mTimeDetectorStrategy.suggestNetworkTime(timeSignal));
+ }
+
@VisibleForTesting
public void handleAutoTimeDetectionToggle() {
mHandler.post(mTimeDetectorStrategy::handleAutoTimeDetectionChanged);
@@ -119,10 +128,20 @@
}
private void enforceSuggestPhoneTimePermission() {
- mContext.enforceCallingPermission(android.Manifest.permission.SET_TIME, "set time");
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE,
+ "suggest phone time and time zone");
}
private void enforceSuggestManualTimePermission() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SET_TIME, "set time");
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE,
+ "suggest manual time and time zone");
+ }
+
+ private void enforceSuggestNetworkTimePermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.SET_TIME,
+ "set time");
}
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index 0a6c2e7..468b806 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -19,9 +19,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
-import android.content.Intent;
-import android.util.TimestampedValue;
+import android.os.TimestampedValue;
import java.io.PrintWriter;
@@ -61,10 +61,10 @@
/** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */
void acquireWakeLock();
- /** Returns the elapsedRealtimeMillis clock value. The WakeLock must be held. */
+ /** Returns the elapsedRealtimeMillis clock value. */
long elapsedRealtimeMillis();
- /** Returns the system clock value. The WakeLock must be held. */
+ /** Returns the system clock value. */
long systemClockMillis();
/** Sets the device system clock. The WakeLock must be held. */
@@ -72,9 +72,6 @@
/** Release the wake lock acquired by a call to {@link #acquireWakeLock()}. */
void releaseWakeLock();
-
- /** Send the supplied intent as a stick broadcast. */
- void sendStickyBroadcast(@NonNull Intent intent);
}
/** Initialize the strategy. */
@@ -86,6 +83,9 @@
/** Process the suggested manually entered time. */
void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion);
+ /** Process the suggested time from network sources. */
+ void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);
+
/** Handle the auto-time setting being toggled on or off. */
void handleAutoTimeDetectionChanged();
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
index 42d59d5..19484db 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
@@ -20,11 +20,9 @@
import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.Intent;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
@@ -90,13 +88,11 @@
@Override
public long elapsedRealtimeMillis() {
- checkWakeLockHeld();
return SystemClock.elapsedRealtime();
}
@Override
public long systemClockMillis() {
- checkWakeLockHeld();
return System.currentTimeMillis();
}
@@ -112,11 +108,6 @@
mWakeLock.release();
}
- @Override
- public void sendStickyBroadcast(@NonNull Intent intent) {
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
private void checkWakeLockHeld() {
if (!mWakeLock.isHeld()) {
Slog.wtf(TAG, "WakeLock " + mWakeLock + " not held");
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index c50248d..e95fc4a 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -21,17 +21,17 @@
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
-import android.content.Intent;
-import android.telephony.TelephonyManager;
+import android.os.TimestampedValue;
import android.util.LocalLog;
import android.util.Slog;
-import android.util.TimestampedValue;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.timezonedetector.ArrayMapWithHistory;
+import com.android.server.timezonedetector.ReferenceWithHistory;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -56,11 +56,11 @@
/** Each bucket is this size. All buckets are equally sized. */
@VisibleForTesting
static final int PHONE_BUCKET_SIZE_MILLIS = 60 * 60 * 1000;
- /** Phone suggestions older than this value are considered too old. */
+ /** Phone and network suggestions older than this value are considered too old to be used. */
@VisibleForTesting
- static final long PHONE_MAX_AGE_MILLIS = PHONE_BUCKET_COUNT * PHONE_BUCKET_SIZE_MILLIS;
+ static final long MAX_UTC_TIME_AGE_MILLIS = PHONE_BUCKET_COUNT * PHONE_BUCKET_SIZE_MILLIS;
- @IntDef({ ORIGIN_PHONE, ORIGIN_MANUAL })
+ @IntDef({ ORIGIN_PHONE, ORIGIN_MANUAL, ORIGIN_NETWORK })
@Retention(RetentionPolicy.SOURCE)
public @interface Origin {}
@@ -72,6 +72,10 @@
@Origin
private static final int ORIGIN_MANUAL = 2;
+ /** Used when a time value originated from a network signal. */
+ @Origin
+ private static final int ORIGIN_NETWORK = 3;
+
/**
* CLOCK_PARANOIA: The maximum difference allowed between the expected system clock time and the
* actual system clock time before a warning is logged. Used to help identify situations where
@@ -101,9 +105,13 @@
* will have a small number of telephony devices and phoneIds are assumed to be stable.
*/
@GuardedBy("this")
- private ArrayMapWithHistory<Integer, PhoneTimeSuggestion> mSuggestionByPhoneId =
+ private final ArrayMapWithHistory<Integer, PhoneTimeSuggestion> mSuggestionByPhoneId =
new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
+ @GuardedBy("this")
+ private final ReferenceWithHistory<NetworkTimeSuggestion> mLastNetworkSuggestion =
+ new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
+
@Override
public void initialize(@NonNull Callback callback) {
mCallback = callback;
@@ -122,6 +130,19 @@
}
@Override
+ public synchronized void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion) {
+ if (!validateSuggestionTime(timeSuggestion.getUtcTime(), timeSuggestion)) {
+ return;
+ }
+ mLastNetworkSuggestion.set(timeSuggestion);
+
+ // Now perform auto time detection. The new suggestion may be used to modify the system
+ // clock.
+ String reason = "New network time suggested. timeSuggestion=" + timeSuggestion;
+ doAutoTimeDetection(reason);
+ }
+
+ @Override
public synchronized void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
// Empty time suggestion means that telephony network connectivity has been lost.
// The passage of time is relentless, and we don't expect our users to use a time machine,
@@ -167,6 +188,12 @@
ipw.increaseIndent(); // level 1
ipw.println("mLastAutoSystemClockTimeSet=" + mLastAutoSystemClockTimeSet);
+ ipw.println("mCallback.isAutoTimeDetectionEnabled()="
+ + mCallback.isAutoTimeDetectionEnabled());
+ ipw.println("mCallback.elapsedRealtimeMillis()=" + mCallback.elapsedRealtimeMillis());
+ ipw.println("mCallback.systemClockMillis()=" + mCallback.systemClockMillis());
+ ipw.println("mCallback.systemClockUpdateThresholdMillis()="
+ + mCallback.systemClockUpdateThresholdMillis());
ipw.println("Time change log:");
ipw.increaseIndent(); // level 2
@@ -178,6 +205,11 @@
mSuggestionByPhoneId.dump(ipw);
ipw.decreaseIndent(); // level 2
+ ipw.println("Network suggestion history:");
+ ipw.increaseIndent(); // level 2
+ mLastNetworkSuggestion.dump(ipw);
+ ipw.decreaseIndent(); // level 2
+
ipw.decreaseIndent(); // level 1
ipw.flush();
}
@@ -247,23 +279,34 @@
return;
}
+ // Android devices currently prioritize any telephony over network signals. There are
+ // carrier compliance tests that would need to be changed before we could ignore NITZ or
+ // prefer NTP generally. This check is cheap on devices without phone hardware.
PhoneTimeSuggestion bestPhoneSuggestion = findBestPhoneSuggestion();
-
- // Work out what to do with the best suggestion.
- if (bestPhoneSuggestion == null) {
- // There is no good phone suggestion.
- if (DBG) {
- Slog.d(LOG_TAG, "Could not determine time: No best phone suggestion."
- + " detectionReason=" + detectionReason);
- }
+ if (bestPhoneSuggestion != null) {
+ final TimestampedValue<Long> newUtcTime = bestPhoneSuggestion.getUtcTime();
+ String cause = "Found good phone suggestion."
+ + ", bestPhoneSuggestion=" + bestPhoneSuggestion
+ + ", detectionReason=" + detectionReason;
+ setSystemClockIfRequired(ORIGIN_PHONE, newUtcTime, cause);
return;
}
- final TimestampedValue<Long> newUtcTime = bestPhoneSuggestion.getUtcTime();
- String cause = "Found good suggestion."
- + ", bestPhoneSuggestion=" + bestPhoneSuggestion
- + ", detectionReason=" + detectionReason;
- setSystemClockIfRequired(ORIGIN_PHONE, newUtcTime, cause);
+ // There is no good phone suggestion, try network.
+ NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion();
+ if (networkSuggestion != null) {
+ final TimestampedValue<Long> newUtcTime = networkSuggestion.getUtcTime();
+ String cause = "Found good network suggestion."
+ + ", networkSuggestion=" + networkSuggestion
+ + ", detectionReason=" + detectionReason;
+ setSystemClockIfRequired(ORIGIN_NETWORK, newUtcTime, cause);
+ return;
+ }
+
+ if (DBG) {
+ Slog.d(LOG_TAG, "Could not determine time: No best phone or network suggestion."
+ + " detectionReason=" + detectionReason);
+ }
}
@GuardedBy("this")
@@ -342,37 +385,50 @@
private static int scorePhoneSuggestion(
long elapsedRealtimeMillis, @NonNull PhoneTimeSuggestion timeSuggestion) {
- // The score is based on the age since receipt. Suggestions are bucketed so two
- // suggestions in the same bucket from different phoneIds are scored the same.
+
+ // Validate first.
TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime();
- long referenceTimeMillis = utcTime.getReferenceTimeMillis();
- if (referenceTimeMillis > elapsedRealtimeMillis) {
- // Future times are ignored. They imply the reference time was wrong, or the elapsed
- // realtime clock has gone backwards, neither of which are supportable situations.
- Slog.w(LOG_TAG, "Existing suggestion found to be in the future. "
+ if (!validateSuggestionUtcTime(elapsedRealtimeMillis, utcTime)) {
+ Slog.w(LOG_TAG, "Existing suggestion found to be invalid "
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ ", timeSuggestion=" + timeSuggestion);
return PHONE_INVALID_SCORE;
}
- long ageMillis = elapsedRealtimeMillis - referenceTimeMillis;
+ // The score is based on the age since receipt. Suggestions are bucketed so two
+ // suggestions in the same bucket from different phoneIds are scored the same.
+ long ageMillis = elapsedRealtimeMillis - utcTime.getReferenceTimeMillis();
- // Any suggestion > MAX_AGE_MILLIS is treated as too old. Although time is relentless and
- // predictable, the accuracy of the reference time clock may be poor over long periods which
- // would lead to errors creeping in. Also, in edge cases where a bad suggestion has been
- // made and never replaced, it could also mean that the time detection code remains
- // opinionated using a bad invalid suggestion. This caps that edge case at MAX_AGE_MILLIS.
- if (ageMillis > PHONE_MAX_AGE_MILLIS) {
+ // Turn the age into a discrete value: 0 <= bucketIndex < PHONE_BUCKET_COUNT.
+ int bucketIndex = (int) (ageMillis / PHONE_BUCKET_SIZE_MILLIS);
+ if (bucketIndex >= PHONE_BUCKET_COUNT) {
return PHONE_INVALID_SCORE;
}
- // Turn the age into a discrete value: 0 <= bucketIndex < MAX_AGE_HOURS.
- int bucketIndex = (int) (ageMillis / PHONE_BUCKET_SIZE_MILLIS);
-
// We want the lowest bucket index to have the highest score. 0 > score >= BUCKET_COUNT.
return PHONE_BUCKET_COUNT - bucketIndex;
}
+ /** Returns the latest, valid, network suggestion. Returns {@code null} if there isn't one. */
+ @GuardedBy("this")
+ @Nullable
+ private NetworkTimeSuggestion findLatestValidNetworkSuggestion() {
+ NetworkTimeSuggestion networkSuggestion = mLastNetworkSuggestion.get();
+ if (networkSuggestion == null) {
+ // No network suggestions received. This is normal if there's no connectivity.
+ return null;
+ }
+
+ TimestampedValue<Long> utcTime = networkSuggestion.getUtcTime();
+ long elapsedRealTimeMillis = mCallback.elapsedRealtimeMillis();
+ if (!validateSuggestionUtcTime(elapsedRealTimeMillis, utcTime)) {
+ // The latest suggestion is not valid, usually due to its age.
+ return null;
+ }
+
+ return networkSuggestion;
+ }
+
@GuardedBy("this")
private void setSystemClockIfRequired(
@Origin int origin, @NonNull TimestampedValue<Long> time, @NonNull String cause) {
@@ -409,7 +465,7 @@
}
private static boolean isOriginAutomatic(@Origin int origin) {
- return origin == ORIGIN_PHONE;
+ return origin != ORIGIN_MANUAL;
}
@GuardedBy("this")
@@ -477,17 +533,6 @@
} else {
mLastAutoSystemClockTimeSet = null;
}
-
- // Historically, Android has sent a TelephonyManager.ACTION_NETWORK_SET_TIME broadcast only
- // when setting the time using NITZ.
- if (origin == ORIGIN_PHONE) {
- // Send a broadcast that telephony code used to send after setting the clock.
- // TODO Remove this broadcast as soon as there are no remaining listeners.
- Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_SET_TIME);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra("time", newSystemClockMillis);
- mCallback.sendStickyBroadcast(intent);
- }
}
/**
@@ -501,6 +546,16 @@
}
/**
+ * Returns the latest valid network suggestion. Not intended for general use: it is used during
+ * tests to check strategy behavior.
+ */
+ @VisibleForTesting
+ @Nullable
+ public NetworkTimeSuggestion findLatestValidNetworkSuggestionForTests() {
+ return findLatestValidNetworkSuggestion();
+ }
+
+ /**
* A method used to inspect state during tests. Not intended for general use.
*/
@VisibleForTesting
@@ -508,4 +563,32 @@
public synchronized PhoneTimeSuggestion getLatestPhoneSuggestion(int phoneId) {
return mSuggestionByPhoneId.get(phoneId);
}
+
+ /**
+ * A method used to inspect state during tests. Not intended for general use.
+ */
+ @VisibleForTesting
+ @Nullable
+ public NetworkTimeSuggestion getLatestNetworkSuggestion() {
+ return mLastNetworkSuggestion.get();
+ }
+
+ private static boolean validateSuggestionUtcTime(
+ long elapsedRealtimeMillis, TimestampedValue<Long> utcTime) {
+ long referenceTimeMillis = utcTime.getReferenceTimeMillis();
+ if (referenceTimeMillis > elapsedRealtimeMillis) {
+ // Future reference times are ignored. They imply the reference time was wrong, or the
+ // elapsed realtime clock used to derive it has gone backwards, neither of which are
+ // supportable situations.
+ return false;
+ }
+
+ // Any suggestion > MAX_AGE_MILLIS is treated as too old. Although time is relentless and
+ // predictable, the accuracy of the reference time clock may be poor over long periods which
+ // would lead to errors creeping in. Also, in edge cases where a bad suggestion has been
+ // made and never replaced, it could also mean that the time detection code remains
+ // opinionated using a bad invalid suggestion. This caps that edge case at MAX_AGE_MILLIS.
+ long ageMillis = elapsedRealtimeMillis - referenceTimeMillis;
+ return ageMillis <= MAX_UTC_TIME_AGE_MILLIS;
+ }
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 18ed51a..5b58199 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1814,8 +1814,8 @@
}
@Override
- public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info, int device)
- throws RemoteException {
+ public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info,
+ @TvInputManager.DvbDeviceType int deviceType) throws RemoteException {
if (mContext.checkCallingPermission(android.Manifest.permission.DVB_DEVICE)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires DVB_DEVICE permission");
@@ -1852,7 +1852,7 @@
final long identity = Binder.clearCallingIdentity();
try {
String deviceFileName;
- switch (device) {
+ switch (deviceType) {
case TvInputManager.DVB_DEVICE_DEMUX:
deviceFileName = String.format(dvbDeviceFound
? "/dev/dvb/adapter%d/demux%d" : "/dev/dvb%d.demux%d",
@@ -1869,14 +1869,14 @@
info.getAdapterId(), info.getDeviceId());
break;
default:
- throw new IllegalArgumentException("Invalid DVB device: " + device);
+ throw new IllegalArgumentException("Invalid DVB device: " + deviceType);
}
try {
// The DVB frontend device only needs to be opened in read/write mode, which
// allows performing tuning operations. The DVB demux and DVR device are enough
// to be opened in read only mode.
return ParcelFileDescriptor.open(new File(deviceFileName),
- TvInputManager.DVB_DEVICE_FRONTEND == device
+ TvInputManager.DVB_DEVICE_FRONTEND == deviceType
? ParcelFileDescriptor.MODE_READ_WRITE
: ParcelFileDescriptor.MODE_READ_ONLY);
} catch (FileNotFoundException e) {
diff --git a/services/core/java/com/android/server/wallpaper/GLHelper.java b/services/core/java/com/android/server/wallpaper/GLHelper.java
new file mode 100644
index 0000000..1d733f5
--- /dev/null
+++ b/services/core/java/com/android/server/wallpaper/GLHelper.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wallpaper;
+
+import static android.opengl.EGL14.EGL_ALPHA_SIZE;
+import static android.opengl.EGL14.EGL_BLUE_SIZE;
+import static android.opengl.EGL14.EGL_CONFIG_CAVEAT;
+import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION;
+import static android.opengl.EGL14.EGL_DEFAULT_DISPLAY;
+import static android.opengl.EGL14.EGL_DEPTH_SIZE;
+import static android.opengl.EGL14.EGL_GREEN_SIZE;
+import static android.opengl.EGL14.EGL_HEIGHT;
+import static android.opengl.EGL14.EGL_NONE;
+import static android.opengl.EGL14.EGL_NO_CONTEXT;
+import static android.opengl.EGL14.EGL_NO_DISPLAY;
+import static android.opengl.EGL14.EGL_NO_SURFACE;
+import static android.opengl.EGL14.EGL_OPENGL_ES2_BIT;
+import static android.opengl.EGL14.EGL_RED_SIZE;
+import static android.opengl.EGL14.EGL_RENDERABLE_TYPE;
+import static android.opengl.EGL14.EGL_STENCIL_SIZE;
+import static android.opengl.EGL14.EGL_WIDTH;
+import static android.opengl.EGL14.eglChooseConfig;
+import static android.opengl.EGL14.eglCreateContext;
+import static android.opengl.EGL14.eglCreatePbufferSurface;
+import static android.opengl.EGL14.eglDestroyContext;
+import static android.opengl.EGL14.eglDestroySurface;
+import static android.opengl.EGL14.eglGetDisplay;
+import static android.opengl.EGL14.eglGetError;
+import static android.opengl.EGL14.eglInitialize;
+import static android.opengl.EGL14.eglMakeCurrent;
+import static android.opengl.EGL14.eglTerminate;
+import static android.opengl.GLES20.GL_MAX_TEXTURE_SIZE;
+import static android.opengl.GLES20.glGetIntegerv;
+
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.opengl.GLUtils;
+import android.os.SystemProperties;
+import android.util.Log;
+
+class GLHelper {
+ private static final String TAG = GLHelper.class.getSimpleName();
+ private static final int sMaxTextureSize;
+
+ static {
+ int maxTextureSize = SystemProperties.getInt("sys.max_texture_size", 0);
+ sMaxTextureSize = maxTextureSize > 0 ? maxTextureSize : retrieveTextureSizeFromGL();
+ }
+
+ private static int retrieveTextureSizeFromGL() {
+ try {
+ String err;
+
+ // Before we can retrieve info from GL,
+ // we have to create EGLContext, EGLConfig and EGLDisplay first.
+ // We will fail at querying info from GL once one of above failed.
+ // When this happens, we will use defValue instead.
+ EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (eglDisplay == null || eglDisplay == EGL_NO_DISPLAY) {
+ err = "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ if (!eglInitialize(eglDisplay, null, 0 /* majorOffset */, null, 1 /* minorOffset */)) {
+ err = "eglInitialize failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ EGLConfig eglConfig = null;
+ int[] configsCount = new int[1];
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] configSpec = new int[] {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, 0,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_NONE
+ };
+
+ if (!eglChooseConfig(eglDisplay, configSpec, 0 /* attrib_listOffset */,
+ configs, 0 /* configOffset */, 1 /* config_size */,
+ configsCount, 0 /* num_configOffset */)) {
+ err = "eglChooseConfig failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ } else if (configsCount[0] > 0) {
+ eglConfig = configs[0];
+ }
+
+ if (eglConfig == null) {
+ throw new RuntimeException("eglConfig not initialized!");
+ }
+
+ int[] attr_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+ EGLContext eglContext = eglCreateContext(
+ eglDisplay, eglConfig, EGL_NO_CONTEXT, attr_list, 0 /* offset */);
+
+ if (eglContext == null || eglContext == EGL_NO_CONTEXT) {
+ err = "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ // We create a push buffer temporarily for querying info from GL.
+ int[] attrs = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
+ EGLSurface eglSurface =
+ eglCreatePbufferSurface(eglDisplay, eglConfig, attrs, 0 /* offset */);
+ eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
+
+ // Now, we are ready to query the info from GL.
+ int[] maxSize = new int[1];
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0 /* offset */);
+
+ // We have got the info we want, release all egl resources.
+ eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(eglDisplay, eglSurface);
+ eglDestroyContext(eglDisplay, eglContext);
+ eglTerminate(eglDisplay);
+ return maxSize[0];
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Retrieve from GL failed", e);
+ return Integer.MAX_VALUE;
+ }
+ }
+
+ static int getMaxTextureSize() {
+ return sMaxTextureSize;
+ }
+}
+
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index b0f1e5d..991c09a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -134,6 +134,9 @@
private static final boolean DEBUG = false;
private static final boolean DEBUG_LIVE = true;
+ // This 100MB limitation is defined in RecordingCanvas.
+ private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024;
+
public static class Lifecycle extends SystemService {
private IWallpaperManagerService mService;
@@ -572,7 +575,9 @@
// Only generate crop for default display.
final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
- Rect cropHint = new Rect(wallpaper.cropHint);
+ final Rect cropHint = new Rect(wallpaper.cropHint);
+ final DisplayInfo displayInfo = new DisplayInfo();
+ mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
if (DEBUG) {
Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
@@ -618,12 +623,12 @@
}
// scale if the crop height winds up not matching the recommended metrics
- needScale = (wpData.mHeight != cropHint.height());
+ needScale = wpData.mHeight != cropHint.height()
+ || cropHint.height() > GLHelper.getMaxTextureSize()
+ || cropHint.width() > GLHelper.getMaxTextureSize();
//make sure screen aspect ratio is preserved if width is scaled under screen size
if (needScale) {
- final DisplayInfo displayInfo = new DisplayInfo();
- mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height();
final int newWidth = (int) (cropHint.width() * scaleByHeight);
if (newWidth < displayInfo.logicalWidth) {
@@ -644,14 +649,29 @@
if (!needCrop && !needScale) {
// Simple case: the nominal crop fits what we want, so we take
// the whole thing and just copy the image file directly.
- if (DEBUG) {
- Slog.v(TAG, "Null crop of new wallpaper; copying");
+
+ // TODO: It is not accurate to estimate bitmap size without decoding it,
+ // may be we can try to remove this optimized way in the future,
+ // that means, we will always go into the 'else' block.
+
+ // This is just a quick estimation, may be smaller than it is.
+ long estimateSize = options.outWidth * options.outHeight * 4;
+
+ // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail.
+ // Please see: RecordingCanvas#throwIfCannotDraw.
+ if (estimateSize < MAX_BITMAP_SIZE) {
+ success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
}
- success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
+
if (!success) {
wallpaper.cropFile.delete();
// TODO: fall back to default wallpaper in this case
}
+
+ if (DEBUG) {
+ Slog.v(TAG, "Null crop of new wallpaper, estimate size="
+ + estimateSize + ", success=" + success);
+ }
} else {
// Fancy case: crop and scale. First, we decode and scale down if appropriate.
FileOutputStream f = null;
@@ -665,49 +685,78 @@
// We calculate the largest power-of-two under the actual ratio rather than
// just let the decode take care of it because we also want to remap where the
// cropHint rectangle lies in the decoded [super]rect.
- final BitmapFactory.Options scaler;
final int actualScale = cropHint.height() / wpData.mHeight;
int scale = 1;
- while (2*scale < actualScale) {
+ while (2 * scale <= actualScale) {
scale *= 2;
}
- if (scale > 1) {
- scaler = new BitmapFactory.Options();
- scaler.inSampleSize = scale;
+ options.inSampleSize = scale;
+ options.inJustDecodeBounds = false;
+
+ final Rect estimateCrop = new Rect(cropHint);
+ estimateCrop.scale(1f / options.inSampleSize);
+ final float hRatio = (float) wpData.mHeight / estimateCrop.height();
+ final int destHeight = (int) (estimateCrop.height() * hRatio);
+ final int destWidth = (int) (estimateCrop.width() * hRatio);
+
+ // We estimated an invalid crop, try to adjust the cropHint to get a valid one.
+ if (destWidth > GLHelper.getMaxTextureSize()) {
+ int newHeight = (int) (wpData.mHeight / hRatio);
+ int newWidth = (int) (wpData.mWidth / hRatio);
+
if (DEBUG) {
- Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
+ Slog.v(TAG, "Invalid crop dimensions, trying to adjust.");
}
- } else {
- scaler = null;
+
+ estimateCrop.set(cropHint);
+ estimateCrop.left += (cropHint.width() - newWidth) / 2;
+ estimateCrop.top += (cropHint.height() - newHeight) / 2;
+ estimateCrop.right = estimateCrop.left + newWidth;
+ estimateCrop.bottom = estimateCrop.top + newHeight;
+ cropHint.set(estimateCrop);
+ estimateCrop.scale(1f / options.inSampleSize);
}
- Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
+
+ // We've got the safe cropHint; now we want to scale it properly to
+ // the desired rectangle.
+ // That's a height-biased operation: make it fit the hinted height.
+ final int safeHeight = (int) (estimateCrop.height() * hRatio);
+ final int safeWidth = (int) (estimateCrop.width() * hRatio);
+
+ if (DEBUG) {
+ Slog.v(TAG, "Decode parameters:");
+ Slog.v(TAG, " cropHint=" + cropHint + ", estimateCrop=" + estimateCrop);
+ Slog.v(TAG, " down sampling=" + options.inSampleSize
+ + ", hRatio=" + hRatio);
+ Slog.v(TAG, " dest=" + destWidth + "x" + destHeight);
+ Slog.v(TAG, " safe=" + safeWidth + "x" + safeHeight);
+ Slog.v(TAG, " maxTextureSize=" + GLHelper.getMaxTextureSize());
+ }
+
+ Bitmap cropped = decoder.decodeRegion(cropHint, options);
decoder.recycle();
if (cropped == null) {
Slog.e(TAG, "Could not decode new wallpaper");
} else {
- // We've got the extracted crop; now we want to scale it properly to
- // the desired rectangle. That's a height-biased operation: make it
- // fit the hinted height, and accept whatever width we end up with.
- cropHint.offsetTo(0, 0);
- cropHint.right /= scale; // adjust by downsampling factor
- cropHint.bottom /= scale;
- final float heightR =
- ((float) wpData.mHeight) / ((float) cropHint.height());
- if (DEBUG) {
- Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
- }
- final int destWidth = (int)(cropHint.width() * heightR);
+ // We are safe to create final crop with safe dimensions now.
final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
- destWidth, wpData.mHeight, true);
+ safeWidth, safeHeight, true);
if (DEBUG) {
Slog.v(TAG, "Final extract:");
Slog.v(TAG, " dims: w=" + wpData.mWidth
+ " h=" + wpData.mHeight);
- Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ " h=" + finalCrop.getHeight());
}
+ // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail.
+ // Please see: RecordingCanvas#throwIfCannotDraw.
+ if (finalCrop.getByteCount() > MAX_BITMAP_SIZE) {
+ throw new RuntimeException(
+ "Too large bitmap, limit=" + MAX_BITMAP_SIZE);
+ }
+
f = new FileOutputStream(wallpaper.cropFile);
bos = new BufferedOutputStream(f, 32*1024);
finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
@@ -1981,6 +2030,11 @@
if (!isWallpaperSupported(callingPackage)) {
return;
}
+
+ // Make sure both width and height are not larger than max texture size.
+ width = Math.min(width, GLHelper.getMaxTextureSize());
+ height = Math.min(height, GLHelper.getMaxTextureSize());
+
synchronized (mLock) {
int userId = UserHandle.getCallingUserId();
WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 2b1c07b..3b66c72 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -124,6 +124,7 @@
"android.hardware.thermal@1.0",
"android.hardware.tv.cec@1.0",
"android.hardware.tv.input@1.0",
+ "android.hardware.vibrator-cpp",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
@@ -133,7 +134,6 @@
"android.frameworks.sensorservice@1.0",
"android.system.suspend@1.0",
"suspend_control_aidl_interface-cpp",
- "vintf-vibrator-cpp",
],
static_libs: [
diff --git a/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp b/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp
index 9cd743b..8b6526f 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp
@@ -20,6 +20,7 @@
#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <vector>
#include <jni.h>
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 4d4a7b4..0275f3e 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -33,7 +33,6 @@
#include "bpf/BpfUtils.h"
#include "netdbpf/BpfNetworkStats.h"
-using android::bpf::Stats;
using android::bpf::bpfGetUidStats;
using android::bpf::bpfGetIfaceStats;
@@ -54,7 +53,7 @@
TCP_TX_PACKETS = 5
};
-static uint64_t getStatsType(struct Stats* stats, StatsType type) {
+static uint64_t getStatsType(Stats* stats, StatsType type) {
switch (type) {
case RX_BYTES:
return stats->rxBytes;
@@ -73,7 +72,7 @@
}
}
-static int parseIfaceStats(const char* iface, struct Stats* stats) {
+static int parseIfaceStats(const char* iface, Stats* stats) {
FILE *fp = fopen(QTAGUID_IFACE_STATS, "r");
if (fp == NULL) {
return -1;
@@ -117,7 +116,7 @@
return 0;
}
-static int parseUidStats(const uint32_t uid, struct Stats* stats) {
+static int parseUidStats(const uint32_t uid, Stats* stats) {
FILE *fp = fopen(QTAGUID_UID_STATS, "r");
if (fp == NULL) {
return -1;
@@ -150,8 +149,7 @@
}
static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) {
- struct Stats stats;
- memset(&stats, 0, sizeof(Stats));
+ Stats stats = {};
if (useBpfStats) {
if (bpfGetIfaceStats(NULL, &stats) == 0) {
@@ -175,8 +173,7 @@
return UNKNOWN;
}
- struct Stats stats;
- memset(&stats, 0, sizeof(Stats));
+ Stats stats = {};
if (useBpfStats) {
if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
@@ -194,8 +191,7 @@
}
static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) {
- struct Stats stats;
- memset(&stats, 0, sizeof(Stats));
+ Stats stats = {};
if (useBpfStats) {
if (bpfGetUidStats(uid, &stats) == 0) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 127b8e0..952a64c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -206,6 +206,7 @@
import android.provider.ContactsInternal;
import android.provider.Settings;
import android.provider.Settings.Global;
+import android.provider.Telephony;
import android.security.IKeyChainAliasCallback;
import android.security.IKeyChainService;
import android.security.KeyChain;
@@ -246,6 +247,7 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
+import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.Preconditions;
import com.android.internal.util.StatLogger;
@@ -2061,6 +2063,10 @@
Binder.withCleanCallingIdentity(action);
}
+ final <T> T binderWithCleanCallingIdentity(@NonNull ThrowingSupplier<T> action) {
+ return Binder.withCleanCallingIdentity(action);
+ }
+
final int userHandleGetCallingUserId() {
return UserHandle.getUserId(binderGetCallingUid());
}
@@ -13936,23 +13942,14 @@
Preconditions.checkNotNull(apnSetting, "ApnSetting is null in addOverrideApn");
enforceDeviceOwner(who);
- int operatedId = -1;
- Uri resultUri;
- final long id = mInjector.binderClearCallingIdentity();
- try {
- resultUri = mContext.getContentResolver().insert(DPC_URI, apnSetting.toContentValues());
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm != null) {
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> tm.addDevicePolicyOverrideApn(mContext, apnSetting));
+ } else {
+ Log.w(LOG_TAG, "TelephonyManager is null when trying to add override apn");
+ return Telephony.Carriers.INVALID_APN_ID;
}
- if (resultUri != null) {
- try {
- operatedId = Integer.parseInt(resultUri.getLastPathSegment());
- } catch (NumberFormatException e) {
- Slog.e(LOG_TAG, "Failed to parse inserted override APN id.", e);
- }
- }
-
- return operatedId;
}
@Override
@@ -13968,13 +13965,13 @@
if (apnId < 0) {
return false;
}
- final long id = mInjector.binderClearCallingIdentity();
- try {
- return mContext.getContentResolver().update(
- Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
- apnSetting.toContentValues(), null, null) > 0;
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm != null) {
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> tm.modifyDevicePolicyOverrideApn(mContext, apnId, apnSetting));
+ } else {
+ Log.w(LOG_TAG, "TelephonyManager is null when trying to modify override apn");
+ return false;
}
}
@@ -14016,28 +14013,13 @@
}
private List<ApnSetting> getOverrideApnsUnchecked() {
- final Cursor cursor;
- final long id = mInjector.binderClearCallingIdentity();
- try {
- cursor = mContext.getContentResolver().query(DPC_URI, null, null, null, null);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm != null) {
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> tm.getDevicePolicyOverrideApns(mContext));
}
-
- if (cursor == null) {
- return Collections.emptyList();
- }
- try {
- List<ApnSetting> apnList = new ArrayList<ApnSetting>();
- cursor.moveToPosition(-1);
- while (cursor.moveToNext()) {
- ApnSetting apn = ApnSetting.makeApnSetting(cursor);
- apnList.add(apn);
- }
- return apnList;
- } finally {
- cursor.close();
- }
+ Log.w(LOG_TAG, "TelephonyManager is null when trying to get override apns");
+ return Collections.emptyList();
}
@Override
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index b5b21f4..c566341 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1695,7 +1695,7 @@
if (!isWatch && !disableNetworkTime) {
traceBeginAndSlog("StartNetworkTimeUpdateService");
try {
- networkTimeUpdater = new NetworkTimeUpdateServiceImpl(context);
+ networkTimeUpdater = new NetworkTimeUpdateService(context);
ServiceManager.addService("network_time_update_service", networkTimeUpdater);
} catch (Throwable e) {
reportWtf("starting NetworkTimeUpdate service", e);
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 9c7cfc1..cf84bdf 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -23,7 +23,6 @@
name: "services-tethering-shared-srcs",
srcs: [
":framework-annotations",
- "java/android/net/util/NetdService.java",
"java/android/net/util/NetworkConstants.java",
],
visibility: ["//frameworks/base/packages/Tethering"],
diff --git a/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java
index 7f2f499..aad75ae 100644
--- a/services/net/java/android/net/TcpKeepalivePacketData.java
+++ b/services/net/java/android/net/TcpKeepalivePacketData.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.SocketKeepalive.InvalidPacketException;
import android.net.util.IpUtils;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/services/net/java/android/net/ip/IpClientCallbacks.java b/services/net/java/android/net/ip/IpClientCallbacks.java
index 61cd88a..c93e5c5 100644
--- a/services/net/java/android/net/ip/IpClientCallbacks.java
+++ b/services/net/java/android/net/ip/IpClientCallbacks.java
@@ -17,6 +17,7 @@
package android.net.ip;
import android.net.DhcpResults;
+import android.net.DhcpResultsParcelable;
import android.net.Layer2PacketParcelable;
import android.net.LinkProperties;
@@ -69,6 +70,18 @@
public void onNewDhcpResults(DhcpResults dhcpResults) {}
/**
+ * Callback called when new DHCP results are available.
+ *
+ * <p>This is purely advisory and not an indication of provisioning success or failure. This is
+ * only here for callers that want to expose DHCPv4 results to other APIs
+ * (e.g., WifiInfo#setInetAddress).
+ *
+ * <p>DHCPv4 or static IPv4 configuration failure or success can be determined by whether or not
+ * the passed-in DhcpResults object is null.
+ */
+ public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {}
+
+ /**
* Indicates that provisioning was successful.
*/
public void onProvisioningSuccess(LinkProperties newLp) {}
diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java
index 4d60e62..7f723b1 100644
--- a/services/net/java/android/net/ip/IpClientUtil.java
+++ b/services/net/java/android/net/ip/IpClientUtil.java
@@ -119,6 +119,7 @@
@Override
public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {
mCb.onNewDhcpResults(fromStableParcelable(dhcpResults));
+ mCb.onNewDhcpResults(dhcpResults);
}
@Override
diff --git a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java b/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
index a8a258f..9c5d4ad 100644
--- a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
+++ b/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
@@ -3,6 +3,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import android.os.Looper;
import android.os.SystemClock;
@@ -52,8 +53,10 @@
@Test
public void handleInjectNtpTime_cachedAgeLow_injectTime() throws InterruptedException {
- doReturn(NtpTimeHelper.NTP_INTERVAL - 1).when(mMockNtpTrustedTime).getCacheAge();
- doReturn(MOCK_NTP_TIME).when(mMockNtpTrustedTime).getCachedNtpTime();
+ NtpTrustedTime.TimeResult result = mock(NtpTrustedTime.TimeResult.class);
+ doReturn(NtpTimeHelper.NTP_INTERVAL - 1).when(result).getAgeMillis();
+ doReturn(MOCK_NTP_TIME).when(result).getTimeMillis();
+ doReturn(result).when(mMockNtpTrustedTime).getCachedTimeResult();
mNtpTimeHelper.retrieveAndInjectNtpTime();
@@ -64,7 +67,9 @@
@Test
public void handleInjectNtpTime_injectTimeFailed_injectTimeDelayed()
throws InterruptedException {
- doReturn(NtpTimeHelper.NTP_INTERVAL + 1).when(mMockNtpTrustedTime).getCacheAge();
+ NtpTrustedTime.TimeResult result1 = mock(NtpTrustedTime.TimeResult.class);
+ doReturn(NtpTimeHelper.NTP_INTERVAL + 1).when(result1).getAgeMillis();
+ doReturn(result1).when(mMockNtpTrustedTime).getCachedTimeResult();
doReturn(false).when(mMockNtpTrustedTime).forceRefresh();
mNtpTimeHelper.retrieveAndInjectNtpTime();
@@ -72,8 +77,10 @@
assertThat(mCountDownLatch.await(2, TimeUnit.SECONDS)).isFalse();
doReturn(true).when(mMockNtpTrustedTime).forceRefresh();
- doReturn(1L).when(mMockNtpTrustedTime).getCacheAge();
- doReturn(MOCK_NTP_TIME).when(mMockNtpTrustedTime).getCachedNtpTime();
+ NtpTrustedTime.TimeResult result2 = mock(NtpTrustedTime.TimeResult.class);
+ doReturn(1L).when(result2).getAgeMillis();
+ doReturn(MOCK_NTP_TIME).when(result2).getTimeMillis();
+ doReturn(result2).when(mMockNtpTrustedTime).getCachedTimeResult();
SystemClock.sleep(NtpTimeHelper.RETRY_INTERVAL);
waitForTasksToBePostedOnHandlerAndRunThem();
diff --git a/services/tests/mockingservicestests/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml
index 32d7d02..1200c0c 100644
--- a/services/tests/mockingservicestests/AndroidManifest.xml
+++ b/services/tests/mockingservicestests/AndroidManifest.xml
@@ -20,6 +20,7 @@
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.HARDWARE_TEST"/>
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application android:testOnly="true"
android:debuggable="true">
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
similarity index 75%
rename from services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java
rename to services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 7166145..698e491 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -25,14 +25,27 @@
import static android.app.AppOpsManager.OP_WIFI_SCAN;
import static android.app.AppOpsManager.OP_WRITE_SMS;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.PackageOps;
import android.content.Context;
+import android.content.pm.PackageManagerInternal;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
@@ -43,12 +56,17 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.server.LocalServices;
+
+import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.quality.Strictness;
import java.io.File;
import java.util.List;
@@ -69,21 +87,46 @@
// State will be persisted into this XML file.
private static final String APP_OPS_FILENAME = "appops-service-test.xml";
+ private static final Context sContext = InstrumentationRegistry.getTargetContext();
+ private static final String sMyPackageName = sContext.getOpPackageName();
+
private File mAppOpsFile;
- private Context mContext;
private Handler mHandler;
- private AppOpsManager mAppOpsManager;
private AppOpsService mAppOpsService;
- private String mMyPackageName;
private int mMyUid;
private long mTestStartMillis;
+ private StaticMockitoSession mMockingSession;
+
+ @Before
+ public void mockPackageManagerInternalGetApplicationInfo() {
+ mMockingSession = mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .spyStatic(LocalServices.class)
+ .startMocking();
+
+ // Mock LocalServices.getService(PackageManagerInternal.class).getApplicationInfo dependency
+ // needed by AppOpsService
+ PackageManagerInternal mockPackageManagerInternal = mock(PackageManagerInternal.class);
+ when(mockPackageManagerInternal.getApplicationInfo(eq(sMyPackageName), anyInt(), anyInt(),
+ anyInt())).thenReturn(sContext.getApplicationInfo());
+ doReturn(mockPackageManagerInternal).when(
+ () -> LocalServices.getService(PackageManagerInternal.class));
+ }
+
+ private void setupAppOpsService() {
+ mAppOpsService = new AppOpsService(mAppOpsFile, mHandler);
+ mAppOpsService.mContext = spy(sContext);
+
+ // Always approve all permission checks
+ doNothing().when(mAppOpsService.mContext).enforcePermission(anyString(), anyInt(),
+ anyInt(), nullable(String.class));
+ }
private static String sDefaultAppopHistoryParameters;
@Before
public void setUp() {
- mContext = InstrumentationRegistry.getTargetContext();
- mAppOpsFile = new File(mContext.getFilesDir(), APP_OPS_FILENAME);
+ mAppOpsFile = new File(sContext.getFilesDir(), APP_OPS_FILENAME);
if (mAppOpsFile.exists()) {
// Start with a clean state (persisted into XML).
mAppOpsFile.delete();
@@ -92,13 +135,10 @@
HandlerThread handlerThread = new HandlerThread(TAG);
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
- mMyPackageName = mContext.getOpPackageName();
mMyUid = Process.myUid();
- mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
- mAppOpsService = new AppOpsService(mAppOpsFile, mHandler);
- mAppOpsService.mHistoricalRegistry.systemReady(mContext.getContentResolver());
- mAppOpsService.mContext = mContext;
+ setupAppOpsService();
+ mAppOpsService.mHistoricalRegistry.systemReady(sContext.getContentResolver());
mTestStartMillis = System.currentTimeMillis();
}
@@ -118,6 +158,11 @@
sDefaultAppopHistoryParameters);
}
+ @After
+ public void resetStaticMocks() {
+ mMockingSession.finishMocking();
+ }
+
@Test
public void testGetOpsForPackage_noOpsLogged() {
assertThat(getLoggedOps()).isNull();
@@ -125,16 +170,16 @@
@Test
public void testNoteOperationAndGetOpsForPackage() {
- mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED);
- mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, mMyPackageName, MODE_ERRORED);
+ mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
+ mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
// Note an op that's allowed.
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
List<PackageOps> loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
// Note another op that's not allowed.
- mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, mMyPackageName);
+ mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName);
loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
@@ -148,17 +193,17 @@
@Test
public void testNoteOperationAndGetOpsForPackage_controlledByDifferentOp() {
// This op controls WIFI_SCAN
- mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, mMyPackageName, MODE_ALLOWED);
+ mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ALLOWED);
- assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName))
.isEqualTo(MODE_ALLOWED);
assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, -1,
MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);
// Now set COARSE_LOCATION to ERRORED -> this will make WIFI_SCAN disabled as well.
- mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, mMyPackageName, MODE_ERRORED);
- assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, mMyPackageName))
+ mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ERRORED);
+ assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName))
.isEqualTo(MODE_ERRORED);
assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, mTestStartMillis,
@@ -168,15 +213,14 @@
// Tests the dumping and restoring of the in-memory state to/from XML.
@Test
public void testStatePersistence() {
- mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED);
- mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, mMyPackageName, MODE_ERRORED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName);
- mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, mMyPackageName);
+ mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
+ mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+ mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName);
mAppOpsService.writeState();
// Create a new app ops service, and initialize its state from XML.
- mAppOpsService = new AppOpsService(mAppOpsFile, mHandler);
- mAppOpsService.mContext = mContext;
+ setupAppOpsService();
mAppOpsService.readState();
// Query the state of the 2nd service.
@@ -188,13 +232,12 @@
// Tests that ops are persisted during shutdown.
@Test
public void testShutdown() {
- mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName);
+ mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
mAppOpsService.shutdown();
// Create a new app ops service, and initialize its state from XML.
- mAppOpsService = new AppOpsService(mAppOpsFile, mHandler);
- mAppOpsService.mContext = mContext;
+ setupAppOpsService();
mAppOpsService.readState();
// Query the state of the 2nd service.
@@ -204,21 +247,21 @@
@Test
public void testGetOpsForPackage() {
- mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName);
+ mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
// Query all ops
List<PackageOps> loggedOps = mAppOpsService.getOpsForPackage(
- mMyUid, mMyPackageName, null /* all ops */);
+ mMyUid, sMyPackageName, null /* all ops */);
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
// Query specific ops
loggedOps = mAppOpsService.getOpsForPackage(
- mMyUid, mMyPackageName, new int[]{OP_READ_SMS, OP_WRITE_SMS});
+ mMyUid, sMyPackageName, new int[]{OP_READ_SMS, OP_WRITE_SMS});
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
// Query unknown UID
- loggedOps = mAppOpsService.getOpsForPackage(mMyUid + 1, mMyPackageName, null /* all ops */);
+ loggedOps = mAppOpsService.getOpsForPackage(mMyUid + 1, sMyPackageName, null /* all ops */);
assertThat(loggedOps).isNull();
// Query unknown package name
@@ -226,31 +269,31 @@
assertThat(loggedOps).isNull();
// Query op code that's not been logged
- loggedOps = mAppOpsService.getOpsForPackage(mMyUid, mMyPackageName,
+ loggedOps = mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName,
new int[]{OP_WRITE_SMS});
assertThat(loggedOps).isNull();
}
@Test
public void testPackageRemoved() {
- mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName);
+ mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
List<PackageOps> loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
- mAppOpsService.packageRemoved(mMyUid, mMyPackageName);
+ mAppOpsService.packageRemoved(mMyUid, sMyPackageName);
assertThat(getLoggedOps()).isNull();
}
@Ignore("Historical appops are disabled in Android Q")
@Test
public void testPackageRemovedHistoricalOps() throws InterruptedException {
- mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName);
+ mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000);
- historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, mMyPackageName,
+ historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName,
AppOpsManager.UID_STATE_PERSISTENT, 0, 1);
mAppOpsService.addHistoricalOps(historicalOps);
@@ -263,7 +306,7 @@
});
// First, do a fetch to ensure it's written
- mAppOpsService.getHistoricalOps(mMyUid, mMyPackageName, null, 0, Long.MAX_VALUE, 0,
+ mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, 0, Long.MAX_VALUE, 0,
callback);
latchRef.get().await(5, TimeUnit.SECONDS);
@@ -271,11 +314,11 @@
assertThat(resultOpsRef.get().isEmpty()).isFalse();
// Then, check it's deleted on removal
- mAppOpsService.packageRemoved(mMyUid, mMyPackageName);
+ mAppOpsService.packageRemoved(mMyUid, sMyPackageName);
latchRef.set(new CountDownLatch(1));
- mAppOpsService.getHistoricalOps(mMyUid, mMyPackageName, null, 0, Long.MAX_VALUE, 0,
+ mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, 0, Long.MAX_VALUE, 0,
callback);
latchRef.get().await(5, TimeUnit.SECONDS);
@@ -285,8 +328,8 @@
@Test
public void testUidRemoved() {
- mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName);
+ mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
List<PackageOps> loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
@@ -297,7 +340,7 @@
private void setupProcStateTests() {
// For the location proc state tests
- mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, mMyPackageName, MODE_FOREGROUND);
+ mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_FOREGROUND);
mAppOpsService.mConstants.FG_SERVICE_STATE_SETTLE_TIME = 0;
mAppOpsService.mConstants.TOP_STATE_SETTLE_TIME = 0;
mAppOpsService.mConstants.BG_STATE_SETTLE_TIME = 0;
@@ -308,18 +351,18 @@
setupProcStateTests();
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
// Second time to make sure that settle time is overcome
Thread.sleep(50);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isNotEqualTo(MODE_ALLOWED);
}
@@ -328,11 +371,11 @@
setupProcStateTests();
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isNotEqualTo(MODE_ALLOWED);
}
@@ -341,12 +384,12 @@
setupProcStateTests();
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid,
PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isEqualTo(MODE_ALLOWED);
}
@@ -355,18 +398,18 @@
setupProcStateTests();
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
// Second time to make sure that settle time is overcome
Thread.sleep(50);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isNotEqualTo(MODE_ALLOWED);
}
@@ -375,30 +418,30 @@
setupProcStateTests();
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
// Second time to make sure that settle time is overcome
Thread.sleep(50);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
// Second time to make sure that settle time is overcome
Thread.sleep(50);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, mMyPackageName))
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
.isNotEqualTo(MODE_ALLOWED);
}
private List<PackageOps> getLoggedOps() {
- return mAppOpsService.getOpsForPackage(mMyUid, mMyPackageName, null /* all ops */);
+ return mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName, null /* all ops */);
}
private void assertContainsOp(List<PackageOps> loggedOps, int opCode, long minMillis,
@@ -407,7 +450,7 @@
boolean opLogged = false;
for (PackageOps pkgOps : loggedOps) {
assertWithMessage("Unexpected UID").that(mMyUid).isEqualTo(pkgOps.getUid());
- assertWithMessage("Unexpected package name").that(mMyPackageName).isEqualTo(
+ assertWithMessage("Unexpected package name").that(sMyPackageName).isEqualTo(
pkgOps.getPackageName());
for (OpEntry opEntry : pkgOps.getOps()) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
index 19369db..6c29f60 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
@@ -530,6 +530,46 @@
}
@Test
+ public void testJobDelayWakeupAlarmToggling() {
+ final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+
+ JobStatus job = createJobStatus(
+ "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
+ createJob().setMinimumLatency(HOUR_IN_MILLIS));
+
+ doReturn(true).when(mTimeController)
+ .wouldBeReadyWithConstraintLocked(eq(job), anyInt());
+
+ // Starting off with using a wakeup alarm.
+ mConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY = false;
+ InOrder inOrder = inOrder(mAlarmManager);
+
+ mTimeController.maybeStartTrackingJobLocked(job, null);
+ inOrder.verify(mAlarmManager, times(1))
+ .set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), eq(now + HOUR_IN_MILLIS), anyLong(),
+ anyLong(),
+ eq(TAG_DELAY), any(), any(), any());
+
+ // Use a non wakeup alarm.
+ mConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY = true;
+
+ mTimeController.maybeStartTrackingJobLocked(job, null);
+ inOrder.verify(mAlarmManager, times(1))
+ .set(eq(AlarmManager.ELAPSED_REALTIME), eq(now + HOUR_IN_MILLIS), anyLong(),
+ anyLong(), eq(TAG_DELAY),
+ any(), any(), any());
+
+ // Back off, use a wakeup alarm.
+ mConstants.USE_NON_WAKEUP_ALARM_FOR_DELAY = false;
+
+ mTimeController.maybeStartTrackingJobLocked(job, null);
+ inOrder.verify(mAlarmManager, times(1))
+ .set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), eq(now + HOUR_IN_MILLIS), anyLong(),
+ anyLong(),
+ eq(TAG_DELAY), any(), any(), any());
+ }
+
+ @Test
public void testCheckExpiredDelaysAndResetAlarm_WithSkipping_AllReady() {
mConstants.SKIP_NOT_READY_JOBS = true;
mTimeController.recheckAlarmsLocked();
diff --git a/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java b/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
new file mode 100644
index 0000000..968a402
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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 com.android.server.BluetoothAirplaneModeListener.AirplaneModeHelper;
+
+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 AirplaneModeHelper mHelper;
+
+ @Mock BluetoothManagerService mBluetoothManagerService;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+
+ mHelper = mock(AirplaneModeHelper.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.isA2dpOrHearingAidConnected()).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.isA2dpOrHearingAidConnected()).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.isA2dpOrHearingAidConnected()).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/DynamicSystemServiceTest.java b/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java
index 50437b4..d367f71 100644
--- a/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java
@@ -36,7 +36,7 @@
public void test1() {
assertTrue("dynamic_system service available", mService != null);
try {
- mService.startInstallation();
+ mService.startInstallation("dsu");
fail("DynamicSystemService did not throw SecurityException as expected");
} catch (SecurityException e) {
// expected
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 8fd8d04..ca5dfb1 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -16,7 +16,7 @@
package com.android.server;
-import static android.net.NetworkScoreManager.CACHE_FILTER_NONE;
+import static android.net.NetworkScoreManager.SCORE_FILTER_NONE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -29,6 +29,7 @@
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
@@ -57,7 +58,6 @@
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import android.net.wifi.WifiSsid;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
@@ -180,8 +180,8 @@
}
private ScanResult createScanResult(String ssid, String bssid) {
- ScanResult result = new ScanResult();
- result.wifiSsid = WifiSsid.createFromAsciiEncoded(ssid);
+ ScanResult result = mock(ScanResult.class);
+ result.SSID = ssid;
result.BSSID = bssid;
return result;
}
@@ -304,7 +304,7 @@
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
- mNetworkScoreCache, CACHE_FILTER_NONE);
+ mNetworkScoreCache, SCORE_FILTER_NONE);
mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
@@ -319,9 +319,9 @@
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
- mNetworkScoreCache, CACHE_FILTER_NONE);
+ mNetworkScoreCache, SCORE_FILTER_NONE);
mNetworkScoreService.registerNetworkScoreCache(
- NetworkKey.TYPE_WIFI, mNetworkScoreCache2, CACHE_FILTER_NONE);
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache2, SCORE_FILTER_NONE);
// updateScores should update both caches
mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
@@ -376,7 +376,7 @@
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
- CACHE_FILTER_NONE);
+ SCORE_FILTER_NONE);
mNetworkScoreService.clearScores();
verify(mNetworkScoreCache).clearScores();
@@ -390,7 +390,7 @@
.thenReturn(PackageManager.PERMISSION_GRANTED);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
- CACHE_FILTER_NONE);
+ SCORE_FILTER_NONE);
mNetworkScoreService.clearScores();
verify(mNetworkScoreCache).clearScores();
@@ -470,7 +470,7 @@
try {
mNetworkScoreService.registerNetworkScoreCache(
- NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE);
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache, SCORE_FILTER_NONE);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
@@ -613,7 +613,7 @@
new ArrayList<>(scoredNetworkList),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_NONE);
verify(mNetworkScoreCache).updateScores(scoredNetworkList);
verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
@@ -654,7 +654,7 @@
Collections.emptyList(),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_NONE);
verifyZeroInteractions(mNetworkScoreCache, mCurrentNetworkFilter, mScanResultsFilter);
}
@@ -671,7 +671,7 @@
List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
filteredList.remove(SCORED_NETWORK);
when(mCurrentNetworkFilter.apply(scoredNetworkList)).thenReturn(filteredList);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_CURRENT_NETWORK);
verify(mNetworkScoreCache).updateScores(filteredList);
verifyZeroInteractions(mScanResultsFilter);
@@ -689,7 +689,7 @@
List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
filteredList.remove(SCORED_NETWORK);
when(mScanResultsFilter.apply(scoredNetworkList)).thenReturn(filteredList);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_SCAN_RESULTS);
verify(mNetworkScoreCache).updateScores(filteredList);
verifyZeroInteractions(mCurrentNetworkFilter);
@@ -792,7 +792,7 @@
@Test
public void testScanResultsScoreCacheFilter_invalidScanResults() throws Exception {
List<ScanResult> invalidScanResults = Lists.newArrayList(
- new ScanResult(),
+ mock(ScanResult.class),
createScanResult("", SCORED_NETWORK.networkKey.wifiKey.bssid),
createScanResult(WifiManager.UNKNOWN_SSID, SCORED_NETWORK.networkKey.wifiKey.bssid),
createScanResult(SSID, null),
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index f3c76b6..8871348 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -28,6 +28,7 @@
import android.app.admin.DevicePolicyManagerInternal;
import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetManagerInternal;
import android.appwidget.AppWidgetProviderInfo;
import android.appwidget.PendingHostUpdate;
import android.content.BroadcastReceiver;
@@ -80,6 +81,7 @@
super.setUp();
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
+ LocalServices.removeServiceForTest(AppWidgetManagerInternal.class);
mTestContext = new TestContext();
mPkgName = mTestContext.getOpPackageName();
diff --git a/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java b/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java
new file mode 100644
index 0000000..d0767cc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.compat;
+
+import android.content.pm.ApplicationInfo;
+
+class ApplicationInfoBuilder {
+ private boolean mIsDebuggable;
+ private int mTargetSdk;
+ private String mPackageName;
+
+ private ApplicationInfoBuilder() {
+ mTargetSdk = -1;
+ }
+
+ static ApplicationInfoBuilder create() {
+ return new ApplicationInfoBuilder();
+ }
+
+ ApplicationInfoBuilder withTargetSdk(int targetSdk) {
+ mTargetSdk = targetSdk;
+ return this;
+ }
+
+ ApplicationInfoBuilder debuggable() {
+ mIsDebuggable = true;
+ return this;
+ }
+
+ ApplicationInfoBuilder withPackageName(String packageName) {
+ mPackageName = packageName;
+ return this;
+ }
+
+ ApplicationInfo build() {
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ if (mIsDebuggable) {
+ applicationInfo.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
+ }
+ applicationInfo.packageName = mPackageName;
+ applicationInfo.targetSdkVersion = mTargetSdk;
+ return applicationInfo;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
new file mode 100644
index 0000000..328c71d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.compat;
+
+import android.content.Context;
+
+import com.android.internal.compat.AndroidBuildClassifier;
+
+import java.util.ArrayList;
+
+/**
+ * Helper class for creating a CompatConfig.
+ */
+class CompatConfigBuilder {
+ private ArrayList<CompatChange> mChanges;
+ private AndroidBuildClassifier mBuildClassifier;
+ private Context mContext;
+
+ private CompatConfigBuilder(AndroidBuildClassifier buildClassifier, Context context) {
+ mChanges = new ArrayList<>();
+ mBuildClassifier = buildClassifier;
+ mContext = context;
+ }
+
+ static CompatConfigBuilder create(AndroidBuildClassifier buildClassifier, Context context) {
+ return new CompatConfigBuilder(buildClassifier, context);
+ }
+
+ CompatConfigBuilder addTargetSdkChangeWithId(int sdk, long id) {
+ mChanges.add(new CompatChange(id, "", sdk, false, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addTargetSdkDisabledChangeWithId(int sdk, long id) {
+ mChanges.add(new CompatChange(id, "", sdk, true, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addTargetSdkChangeWithIdAndName(int sdk, long id, String name) {
+ mChanges.add(new CompatChange(id, name, sdk, false, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addTargetSdkChangeWithIdAndDescription(int sdk, long id,
+ String description) {
+ mChanges.add(new CompatChange(id, "", sdk, false, description));
+ return this;
+ }
+
+ CompatConfigBuilder addEnabledChangeWithId(long id) {
+ mChanges.add(new CompatChange(id, "", -1, false, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addEnabledChangeWithIdAndName(long id, String name) {
+ mChanges.add(new CompatChange(id, name, -1, false, ""));
+ return this;
+ }
+ CompatConfigBuilder addEnabledChangeWithIdAndDescription(long id, String description) {
+ mChanges.add(new CompatChange(id, "", -1, false, description));
+ return this;
+ }
+
+ CompatConfigBuilder addDisabledChangeWithId(long id) {
+ mChanges.add(new CompatChange(id, "", -1, true, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addDisabledChangeWithIdAndName(long id, String name) {
+ mChanges.add(new CompatChange(id, name, -1, true, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addDisabledChangeWithIdAndDescription(long id, String description) {
+ mChanges.add(new CompatChange(id, "", -1, true, description));
+ return this;
+ }
+
+ CompatConfig build() {
+ CompatConfig config = new CompatConfig(mBuildClassifier, mContext);
+ for (CompatChange change : mChanges) {
+ config.addChange(change);
+ }
+ return config;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index cb99c11..407f67e 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -18,12 +18,25 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.compat.AndroidBuildClassifier;
+
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.io.File;
import java.io.FileOutputStream;
@@ -34,12 +47,12 @@
@RunWith(AndroidJUnit4.class)
public class CompatConfigTest {
- private ApplicationInfo makeAppInfo(String pName, int targetSdkVersion) {
- ApplicationInfo ai = new ApplicationInfo();
- ai.packageName = pName;
- ai.targetSdkVersion = targetSdkVersion;
- return ai;
- }
+ @Mock
+ private Context mContext;
+ @Mock
+ PackageManager mPackageManager;
+ @Mock
+ private AndroidBuildClassifier mBuildClassifier;
private File createTempDir() {
String base = System.getProperty("java.io.tmpdir");
@@ -54,112 +67,206 @@
os.close();
}
- @Test
- public void testUnknownChangeEnabled() {
- CompatConfig pc = new CompatConfig();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isTrue();
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ // Assume userdebug/eng non-final build
+ when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
+ when(mBuildClassifier.isFinalBuild()).thenReturn(false);
}
@Test
- public void testDisabledChangeDisabled() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, true, ""));
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isFalse();
+ public void testUnknownChangeEnabled() throws Exception {
+ CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create().build()))
+ .isTrue();
}
@Test
- public void testTargetSdkChangeDisabled() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", 2, false, null));
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 2))).isFalse();
+ public void testDisabledChangeDisabled() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .build();
+
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create().build()))
+ .isFalse();
}
@Test
- public void testTargetSdkChangeEnabled() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", 2, false, ""));
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isTrue();
+ public void testTargetSdkChangeDisabled() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addTargetSdkChangeWithId(2, 1234L)
+ .build();
+
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(2).build()))
+ .isFalse();
}
@Test
- public void testDisabledOverrideTargetSdkChange() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", 2, true, null));
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isFalse();
+ public void testTargetSdkChangeEnabled() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addTargetSdkChangeWithId(2, 1234L)
+ .build();
+
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(3).build())).isTrue();
}
@Test
- public void testGetDisabledChanges() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, true, null));
- pc.addChange(new CompatChange(2345L, "OTHER_CHANGE", -1, false, null));
- assertThat(pc.getDisabledChanges(
- makeAppInfo("com.some.package", 2))).asList().containsExactly(1234L);
+ public void testDisabledOverrideTargetSdkChange() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addTargetSdkDisabledChangeWithId(2, 1234L)
+ .build();
+
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(3).build())).isFalse();
}
@Test
- public void testGetDisabledChangesSorted() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", 2, true, null));
- pc.addChange(new CompatChange(123L, "OTHER_CHANGE", 2, true, null));
- pc.addChange(new CompatChange(12L, "THIRD_CHANGE", 2, true, null));
- assertThat(pc.getDisabledChanges(
- makeAppInfo("com.some.package", 2))).asList().containsExactly(12L, 123L, 1234L);
+ public void testGetDisabledChanges() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .addEnabledChangeWithId(2345L)
+ .build();
+
+ assertThat(compatConfig.getDisabledChanges(
+ ApplicationInfoBuilder.create().build())).asList().containsExactly(1234L);
}
@Test
- public void testPackageOverrideEnabled() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, true, null)); // disabled
- pc.addOverride(1234L, "com.some.package", true);
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 2))).isTrue();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.other.package", 2))).isFalse();
+ public void testGetDisabledChangesSorted() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .addDisabledChangeWithId(123L)
+ .addDisabledChangeWithId(12L)
+ .build();
+
+ assertThat(compatConfig.getDisabledChanges(ApplicationInfoBuilder.create().build()))
+ .asList().containsExactly(12L, 123L, 1234L);
}
@Test
- public void testPackageOverrideDisabled() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, false, null));
- pc.addOverride(1234L, "com.some.package", false);
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 2))).isFalse();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.other.package", 2))).isTrue();
+ public void testPackageOverrideEnabled() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .build();
+
+ compatConfig.addOverride(1234L, "com.some.package", true);
+
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package").build())).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.other.package").build())).isFalse();
}
@Test
- public void testPackageOverrideUnknownPackage() {
- CompatConfig pc = new CompatConfig();
- pc.addOverride(1234L, "com.some.package", false);
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 2))).isFalse();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.other.package", 2))).isTrue();
+ public void testPackageOverrideDisabled() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addEnabledChangeWithId(1234L)
+ .build();
+
+ compatConfig.addOverride(1234L, "com.some.package", false);
+
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package").build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.other.package").build())).isTrue();
}
@Test
- public void testPackageOverrideUnknownChange() {
- CompatConfig pc = new CompatConfig();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isTrue();
+ public void testPackageOverrideUnknownPackage() throws Exception {
+ CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
+
+ compatConfig.addOverride(1234L, "com.some.package", false);
+
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package").build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.other.package").build())).isTrue();
}
@Test
- public void testRemovePackageOverride() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, false, null));
- pc.addOverride(1234L, "com.some.package", false);
- pc.removeOverride(1234L, "com.some.package");
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 2))).isTrue();
+ public void testPreventAddOverride() throws Exception {
+ final long changeId = 1234L;
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .build();
+ ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package")
+ .build();
+ PackageManager packageManager = mock(PackageManager.class);
+ when(mContext.getPackageManager()).thenReturn(packageManager);
+ when(packageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
+ .thenReturn(applicationInfo);
+
+ // Force the validator to prevent overriding the change by using a user build.
+ when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
+ when(mBuildClassifier.isFinalBuild()).thenReturn(true);
+
+ assertThrows(SecurityException.class,
+ () -> compatConfig.addOverride(1234L, "com.some.package", true)
+ );
+ assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
}
@Test
- public void testLookupChangeId() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, false, null));
- pc.addChange(new CompatChange(2345L, "ANOTHER_CHANGE", -1, false, null));
- assertThat(pc.lookupChangeId("MY_CHANGE")).isEqualTo(1234L);
+ public void testPreventRemoveOverride() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .build();
+ ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package")
+ .build();
+ when(mPackageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
+ .thenReturn(applicationInfo);
+ // Assume the override was allowed to be added.
+ compatConfig.addOverride(1234L, "com.some.package", true);
+
+ // Validator allows turning on the change.
+ assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
+
+ // Reject all override attempts.
+ // Force the validator to prevent overriding the change by using a user build.
+ when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
+ when(mBuildClassifier.isFinalBuild()).thenReturn(true);
+ // Try to turn off change, but validator prevents it.
+ assertThrows(SecurityException.class,
+ () -> compatConfig.removeOverride(1234L, "com.some.package"));
+ assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
}
@Test
- public void testLookupChangeIdNotPresent() {
- CompatConfig pc = new CompatConfig();
- assertThat(pc.lookupChangeId("MY_CHANGE")).isEqualTo(-1L);
+ public void testRemovePackageOverride() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addEnabledChangeWithId(1234L)
+ .build();
+ ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package")
+ .build();
+
+ assertThat(compatConfig.addOverride(1234L, "com.some.package", false)).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
+
+ compatConfig.removeOverride(1234L, "com.some.package");
+ assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
+ }
+
+ @Test
+ public void testLookupChangeId() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addEnabledChangeWithIdAndName(1234L, "MY_CHANGE")
+ .addEnabledChangeWithIdAndName(2345L, "MY_OTHER_CHANGE")
+ .build();
+
+ assertThat(compatConfig.lookupChangeId("MY_CHANGE")).isEqualTo(1234L);
+ }
+
+ @Test
+ public void testLookupChangeIdNotPresent() throws Exception {
+ CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
+ assertThat(compatConfig.lookupChangeId("MY_CHANGE")).isEqualTo(-1L);
}
@Test
@@ -172,14 +279,17 @@
File dir = createTempDir();
writeToFile(dir, "platform_compat_config.xml", configXml);
+ CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
+ compatConfig.initConfigFromLib(dir);
- CompatConfig pc = new CompatConfig();
- pc.initConfigFromLib(dir);
-
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isFalse();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isTrue();
- assertThat(pc.isChangeEnabled(1235L, makeAppInfo("com.some.package", 5))).isFalse();
- assertThat(pc.isChangeEnabled(1236L, makeAppInfo("com.some.package", 1))).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(1).build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(3).build())).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1235L,
+ ApplicationInfoBuilder.create().withTargetSdk(5).build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1236L,
+ ApplicationInfoBuilder.create().withTargetSdk(1).build())).isTrue();
}
@Test
@@ -195,15 +305,16 @@
File dir = createTempDir();
writeToFile(dir, "libcore_platform_compat_config.xml", configXml1);
writeToFile(dir, "frameworks_platform_compat_config.xml", configXml2);
+ CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
+ compatConfig.initConfigFromLib(dir);
- CompatConfig pc = new CompatConfig();
- pc.initConfigFromLib(dir);
-
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isFalse();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isTrue();
- assertThat(pc.isChangeEnabled(1235L, makeAppInfo("com.some.package", 5))).isFalse();
- assertThat(pc.isChangeEnabled(1236L, makeAppInfo("com.some.package", 1))).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(1).build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(3).build())).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1235L,
+ ApplicationInfoBuilder.create().withTargetSdk(5).build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1236L,
+ ApplicationInfoBuilder.create().withTargetSdk(1).build())).isTrue();
}
}
-
-
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatibilityChangeConfigBuilder.java b/services/tests/servicestests/src/com/android/server/compat/CompatibilityChangeConfigBuilder.java
new file mode 100644
index 0000000..793296e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatibilityChangeConfigBuilder.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.compat;
+
+import android.compat.Compatibility;
+
+import com.android.internal.compat.CompatibilityChangeConfig;
+
+import java.util.HashSet;
+import java.util.Set;
+
+class CompatibilityChangeConfigBuilder {
+ private Set<Long> mEnabled;
+ private Set<Long> mDisabled;
+
+ private CompatibilityChangeConfigBuilder() {
+ mEnabled = new HashSet<>();
+ mDisabled = new HashSet<>();
+ }
+
+ static CompatibilityChangeConfigBuilder create() {
+ return new CompatibilityChangeConfigBuilder();
+ }
+
+ CompatibilityChangeConfigBuilder enable(Long id) {
+ mEnabled.add(id);
+ return this;
+ }
+
+ CompatibilityChangeConfigBuilder disable(Long id) {
+ mDisabled.add(id);
+ return this;
+ }
+
+ CompatibilityChangeConfig build() {
+ return new CompatibilityChangeConfig(new Compatibility.ChangeConfig(mEnabled, mDisabled));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java
new file mode 100644
index 0000000..b14291b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.compat;
+
+import static com.android.internal.compat.OverrideAllowedState.ALLOWED;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_NON_TARGET_SDK;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_NOT_DEBUGGABLE;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_SDK_TOO_HIGH;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.compat.AndroidBuildClassifier;
+import com.android.internal.compat.IOverrideValidator;
+import com.android.internal.compat.OverrideAllowedState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class OverrideValidatorImplTest {
+ private static final String PACKAGE_NAME = "my.package";
+ private static final int TARGET_SDK = 10;
+ private static final int TARGET_SDK_BEFORE = 9;
+ private static final int TARGET_SDK_AFTER = 11;
+
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ Context mContext;
+
+ private AndroidBuildClassifier debuggableBuild() {
+ AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class);
+ when(buildClassifier.isDebuggableBuild()).thenReturn(true);
+ return buildClassifier;
+ }
+
+ private AndroidBuildClassifier betaBuild() {
+ AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class);
+ when(buildClassifier.isDebuggableBuild()).thenReturn(false);
+ when(buildClassifier.isFinalBuild()).thenReturn(false);
+ return buildClassifier;
+ }
+
+ private AndroidBuildClassifier finalBuild() {
+ AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class);
+ when(buildClassifier.isDebuggableBuild()).thenReturn(false);
+ when(buildClassifier.isFinalBuild()).thenReturn(true);
+ return buildClassifier;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ }
+
+ @Test
+ public void getOverrideAllowedState_debugBuildAnyChangeDebugApp_allowOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnabledChangeWithId(4)
+ .addDisabledChangeWithId(5).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .debuggable()
+ .withTargetSdk(TARGET_SDK)
+ .withPackageName(PACKAGE_NAME).build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkAfterChange =
+ overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
+ OverrideAllowedState stateEnabledChange =
+ overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
+ OverrideAllowedState stateDisabledChange =
+ overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateTargetSdkEqualChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateTargetSdkAfterChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateEnabledChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateDisabledChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_debugBuildAnyChangeReleaseApp_allowOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnabledChangeWithId(4)
+ .addDisabledChangeWithId(5).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .withTargetSdk(TARGET_SDK).build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkAfterChange =
+ overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
+ OverrideAllowedState stateEnabledChange =
+ overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
+ OverrideAllowedState stateDisabledChange =
+ overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateTargetSdkEqualChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateTargetSdkAfterChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateEnabledChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateDisabledChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_betaBuildTargetSdkChangeDebugApp_allowOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .debuggable()
+ .withTargetSdk(TARGET_SDK)
+ .withPackageName(PACKAGE_NAME).build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkAfterChange =
+ overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK_BEFORE));
+ assertThat(stateTargetSdkEqualChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK));
+ assertThat(stateTargetSdkAfterChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK_AFTER));
+ }
+
+ @Test
+ public void getOverrideAllowedState_betaBuildEnabledChangeDebugApp_allowOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
+ .addEnabledChangeWithId(1).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .debuggable()
+ .build());
+
+ OverrideAllowedState allowedState =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+
+ assertThat(allowedState)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_betaBuildDisabledChangeDebugApp_allowOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
+ .addDisabledChangeWithId(1).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .debuggable()
+ .withPackageName(PACKAGE_NAME).build());
+
+ OverrideAllowedState allowedState =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+
+ assertThat(allowedState)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_betaBuildAnyChangeReleaseApp_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnabledChangeWithId(4)
+ .addDisabledChangeWithId(5).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .withTargetSdk(TARGET_SDK).build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkAfterChange =
+ overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
+ OverrideAllowedState stateEnabledChange =
+ overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
+ OverrideAllowedState stateDisabledChange =
+ overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateTargetSdkEqualChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateTargetSdkAfterChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateEnabledChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateDisabledChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_finalBuildTargetSdkChangeDebugAppOptin_allowOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 1).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .debuggable()
+ .withTargetSdk(TARGET_SDK)
+ .withPackageName(PACKAGE_NAME).build());
+
+ OverrideAllowedState allowedState =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+
+ assertThat(allowedState)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK_AFTER));
+ }
+
+ @Test
+ public void getOverrideAllowedState_finalBuildTargetSdkChangeDebugAppOptout_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .withTargetSdk(TARGET_SDK)
+ .debuggable()
+ .build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange).isEqualTo(
+ new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, TARGET_SDK,
+ TARGET_SDK_BEFORE));
+ assertThat(stateTargetSdkEqualChange).isEqualTo(
+ new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, TARGET_SDK, TARGET_SDK));
+ }
+
+ @Test
+ public void getOverrideAllowedState_finalBuildEnabledChangeDebugApp_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
+ .addEnabledChangeWithId(1).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .debuggable().build());
+
+ OverrideAllowedState allowedState =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+
+ assertThat(allowedState)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NON_TARGET_SDK, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_finalBuildDisabledChangeDebugApp_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
+ .addDisabledChangeWithId(1).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .debuggable().build());
+
+ OverrideAllowedState allowedState =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+
+ assertThat(allowedState)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NON_TARGET_SDK, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_finalBuildAnyChangeReleaseApp_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnabledChangeWithId(4)
+ .addDisabledChangeWithId(5).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .withTargetSdk(TARGET_SDK).build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkAfterChange =
+ overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
+ OverrideAllowedState stateEnabledChange =
+ overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
+ OverrideAllowedState stateDisabledChange =
+ overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateTargetSdkEqualChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateTargetSdkAfterChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateEnabledChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateDisabledChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
index c406876..ce5d6d9 100644
--- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
@@ -26,21 +26,20 @@
import static org.mockito.internal.verification.VerificationModeFactory.times;
import static org.testng.Assert.assertThrows;
-import android.compat.Compatibility;
import android.content.Context;
import android.content.pm.PackageManager;
-import com.android.internal.compat.CompatibilityChangeConfig;
+import androidx.test.runner.AndroidJUnit4;
-import com.google.common.collect.ImmutableSet;
+import com.android.internal.compat.AndroidBuildClassifier;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.MockitoAnnotations;
-@RunWith(MockitoJUnitRunner.class)
+@RunWith(AndroidJUnit4.class)
public class PlatformCompatTest {
private static final String PACKAGE_NAME = "my.package";
@@ -50,84 +49,77 @@
private PackageManager mPackageManager;
@Mock
CompatChange.ChangeListener mListener1, mListener2;
-
+ PlatformCompat mPlatformCompat;
+ CompatConfig mCompatConfig;
+ @Mock
+ private AndroidBuildClassifier mBuildClassifier;
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getPackageUid(eq(PACKAGE_NAME), eq(0))).thenThrow(
new PackageManager.NameNotFoundException());
- CompatConfig.get().clearChanges();
+ mCompatConfig = new CompatConfig(mBuildClassifier, mContext);
+ mPlatformCompat = new PlatformCompat(mContext, mCompatConfig);
+ // Assume userdebug/eng non-final build
+ when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
+ when(mBuildClassifier.isFinalBuild()).thenReturn(false);
}
@Test
- public void testRegisterListenerToSameIdThrows() {
- PlatformCompat pc = new PlatformCompat(mContext);
-
+ public void testRegisterListenerToSameIdThrows() throws Exception {
// Registering a listener to change 1 is successful.
- pc.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(1, mListener1);
// Registering a listener to change 2 is successful.
- pc.registerListener(2, mListener1);
+ mPlatformCompat.registerListener(2, mListener1);
// Trying to register another listener to change id 1 fails.
- assertThrows(IllegalStateException.class, () -> pc.registerListener(1, mListener1));
+ assertThrows(IllegalStateException.class,
+ () -> mPlatformCompat.registerListener(1, mListener1));
}
@Test
- public void testRegisterListenerReturn() {
- PlatformCompat pc = new PlatformCompat(mContext);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of())),
+ public void testRegisterListenerReturn() throws Exception {
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).build(),
PACKAGE_NAME);
// Change id 1 is known (added in setOverrides).
- assertThat(pc.registerListener(1, mListener1)).isTrue();
+ assertThat(mPlatformCompat.registerListener(1, mListener1)).isTrue();
// Change 2 is unknown.
- assertThat(pc.registerListener(2, mListener1)).isFalse();
+ assertThat(mPlatformCompat.registerListener(2, mListener1)).isFalse();
}
@Test
- public void testListenerCalledOnSetOverrides() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnSetOverrides() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener1);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener1);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of(2L))),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(2)).onCompatChange(PACKAGE_NAME);
}
@Test
- public void testListenerNotCalledOnWrongPackage() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerNotCalledOnWrongPackage() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener1);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener1);
-
- pc.setOverridesForTest(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of(2L))),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, never()).onCompatChange("other.package");
}
@Test
- public void testListenerCalledOnSetOverridesTwoListeners() {
- PlatformCompat pc = new PlatformCompat(mContext);
- pc.registerListener(1, mListener1);
+ public void testListenerCalledOnSetOverridesTwoListeners() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
- final ImmutableSet<Long> enabled = ImmutableSet.of(1L);
- final ImmutableSet<Long> disabled = ImmutableSet.of(2L);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled)),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
@@ -136,11 +128,10 @@
reset(mListener1);
reset(mListener2);
- pc.registerListener(2, mListener2);
+ mPlatformCompat.registerListener(2, mListener2);
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled)),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
@@ -148,31 +139,23 @@
}
@Test
- public void testListenerCalledOnSetOverridesForTest() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnSetOverridesForTest() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener1);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener1);
-
- pc.setOverridesForTest(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of(2L))),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(2)).onCompatChange(PACKAGE_NAME);
}
@Test
- public void testListenerCalledOnSetOverridesTwoListenersForTest() {
- PlatformCompat pc = new PlatformCompat(mContext);
- pc.registerListener(1, mListener1);
+ public void testListenerCalledOnSetOverridesTwoListenersForTest() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
- final ImmutableSet<Long> enabled = ImmutableSet.of(1L);
- final ImmutableSet<Long> disabled = ImmutableSet.of(2L);
-
- pc.setOverridesForTest(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled)),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
@@ -181,10 +164,10 @@
reset(mListener1);
reset(mListener2);
- pc.registerListener(2, mListener2);
- pc.setOverridesForTest(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled)),
+ mPlatformCompat.registerListener(2, mListener2);
+
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
@@ -192,15 +175,12 @@
}
@Test
- public void testListenerCalledOnClearOverrides() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnClearOverrides() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener2);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener2);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of())),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, never()).onCompatChange(PACKAGE_NAME);
@@ -208,21 +188,18 @@
reset(mListener1);
reset(mListener2);
- pc.clearOverrides(PACKAGE_NAME);
+ mPlatformCompat.clearOverrides(PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, never()).onCompatChange(PACKAGE_NAME);
}
@Test
- public void testListenerCalledOnClearOverridesMultipleOverrides() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnClearOverridesMultipleOverrides() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener2);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener2);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of(2L))),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, times(1)).onCompatChange(PACKAGE_NAME);
@@ -230,21 +207,18 @@
reset(mListener1);
reset(mListener2);
- pc.clearOverrides(PACKAGE_NAME);
+ mPlatformCompat.clearOverrides(PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, times(1)).onCompatChange(PACKAGE_NAME);
}
@Test
- public void testListenerCalledOnClearOverrideExists() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnClearOverrideExists() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener2);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener2);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of())),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, never()).onCompatChange(PACKAGE_NAME);
@@ -252,21 +226,17 @@
reset(mListener1);
reset(mListener2);
- pc.clearOverride(1, PACKAGE_NAME);
+ mPlatformCompat.clearOverride(1, PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, never()).onCompatChange(PACKAGE_NAME);
}
@Test
- public void testListenerCalledOnClearOverrideDoesntExist() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnClearOverrideDoesntExist() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
- pc.registerListener(1, mListener1);
-
- pc.clearOverride(1, PACKAGE_NAME);
+ mPlatformCompat.clearOverride(1, PACKAGE_NAME);
// Listener not called when a non existing override is removed.
verify(mListener1, never()).onCompatChange(PACKAGE_NAME);
}
-
-
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 1a67576..960f670 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -217,6 +217,8 @@
return mMockSystemServices.wifiManager;
case Context.ACCOUNT_SERVICE:
return mMockSystemServices.accountManager;
+ case Context.TELEPHONY_SERVICE:
+ return mMockSystemServices.telephonyManager;
}
throw new UnsupportedOperationException();
}
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 7e08d95..2e58ad6 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -37,6 +37,7 @@
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.TAG_ALL;
+import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.MB_IN_BYTES;
@@ -111,7 +112,7 @@
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
-import android.net.StringNetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
import android.os.Binder;
import android.os.Handler;
import android.os.INetworkManagementService;
@@ -1197,11 +1198,11 @@
history.recordData(start, end,
new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1440), 0L, 0L, 0L, 0));
stats.clear();
- stats.addValues(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
+ stats.addEntry(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
- stats.addValues(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
+ stats.addEntry(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
- stats.addValues(IFACE_ALL, UID_C, SET_ALL, TAG_ALL,
+ stats.addEntry(IFACE_ALL, UID_C, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
reset(mNotifManager);
@@ -1225,9 +1226,9 @@
history.recordData(start, end,
new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1440), 0L, 0L, 0L, 0));
stats.clear();
- stats.addValues(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
+ stats.addEntry(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(960), 0, 0, 0, 0);
- stats.addValues(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
+ stats.addEntry(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
reset(mNotifManager);
@@ -1683,6 +1684,59 @@
}
/**
+ * Test that when StatsProvider triggers limit reached, new limit will be calculated and
+ * re-armed.
+ */
+ @Test
+ public void testStatsProviderLimitReached() throws Exception {
+ final int CYCLE_DAY = 15;
+
+ final NetworkStats stats = new NetworkStats(0L, 1);
+ stats.addEntry(TEST_IFACE, UID_A, SET_ALL, TAG_NONE,
+ 2999, 1, 2000, 1, 0);
+ when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
+ .thenReturn(stats.getTotalBytes());
+ when(mStatsService.getNetworkUidBytes(any(), anyLong(), anyLong()))
+ .thenReturn(stats);
+
+ // Get active mobile network in place
+ expectMobileDefaults();
+ mService.updateNetworks();
+ verify(mStatsService).setStatsProviderLimit(TEST_IFACE, Long.MAX_VALUE);
+
+ // Set limit to 10KB.
+ setNetworkPolicies(new NetworkPolicy(
+ sTemplateMobileAll, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, 10000L,
+ true));
+ postMsgAndWaitForCompletion();
+
+ // Verifies that remaining quota is set to providers.
+ verify(mStatsService).setStatsProviderLimit(TEST_IFACE, 10000L - 4999L);
+
+ reset(mStatsService);
+
+ // Increase the usage.
+ stats.addEntry(TEST_IFACE, UID_A, SET_ALL, TAG_NONE,
+ 1000, 1, 999, 1, 0);
+ when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
+ .thenReturn(stats.getTotalBytes());
+ when(mStatsService.getNetworkUidBytes(any(), anyLong(), anyLong()))
+ .thenReturn(stats);
+
+ // Simulates that limit reached fires earlier by provider, but actually the quota is not
+ // yet reached.
+ final NetworkPolicyManagerInternal npmi = LocalServices
+ .getService(NetworkPolicyManagerInternal.class);
+ npmi.onStatsProviderLimitReached("TEST");
+
+ // Verifies that the limit reached leads to a force update and new limit should be set.
+ postMsgAndWaitForCompletion();
+ verify(mStatsService).forceUpdate();
+ postMsgAndWaitForCompletion();
+ verify(mStatsService).setStatsProviderLimit(TEST_IFACE, 10000L - 4999L - 1999L);
+ }
+
+ /**
* Exhaustively test isUidNetworkingBlocked to output the expected results based on external
* conditions.
*/
@@ -1784,7 +1838,8 @@
if (!roaming) {
nc.addCapability(NET_CAPABILITY_NOT_ROAMING);
}
- nc.setNetworkSpecifier(new StringNetworkSpecifier(String.valueOf(subId)));
+ nc.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
+ .setSubscriptionId(subId).build());
return nc;
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java b/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
index bd3d9ab..3852b9f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
@@ -17,6 +17,7 @@
import android.content.Context;
import android.content.pm.ModuleInfo;
+import android.content.pm.PackageManager;
import android.test.InstrumentationTestCase;
import com.android.frameworks.servicestests.R;
@@ -28,7 +29,7 @@
public void testSuccessfulParse() {
ModuleInfoProvider provider = getProvider(R.xml.well_formed_metadata);
- List<ModuleInfo> mi = provider.getInstalledModules(0);
+ List<ModuleInfo> mi = provider.getInstalledModules(PackageManager.MATCH_ALL);
assertEquals(2, mi.size());
Collections.sort(mi, (ModuleInfo m1, ModuleInfo m2) ->
@@ -49,18 +50,18 @@
public void testParseFailure_incorrectTopLevelElement() {
ModuleInfoProvider provider = getProvider(R.xml.unparseable_metadata1);
- assertEquals(0, provider.getInstalledModules(0).size());
+ assertEquals(0, provider.getInstalledModules(PackageManager.MATCH_ALL).size());
}
public void testParseFailure_incorrectModuleElement() {
ModuleInfoProvider provider = getProvider(R.xml.unparseable_metadata2);
- assertEquals(0, provider.getInstalledModules(0).size());
+ assertEquals(0, provider.getInstalledModules(PackageManager.MATCH_ALL).size());
}
public void testParse_unknownAttributesIgnored() {
ModuleInfoProvider provider = getProvider(R.xml.well_formed_metadata);
- List<ModuleInfo> mi = provider.getInstalledModules(0);
+ List<ModuleInfo> mi = provider.getInstalledModules(PackageManager.MATCH_ALL);
assertEquals(2, mi.size());
ModuleInfo mi1 = provider.getModuleInfo("com.android.module1", 0);
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index 0196279..a4ba056 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -160,6 +160,31 @@
}
@Test
+ public void testNotifyPrimaryAndSecondary() {
+ List<String> dexFiles = mFooUser0.getBaseAndSplitDexPaths();
+ List<String> secondaries = mFooUser0.getSecondaryDexPaths();
+ int baseAndSplitCount = dexFiles.size();
+ dexFiles.addAll(secondaries);
+
+ notifyDexLoad(mFooUser0, dexFiles, mUser0);
+
+ PackageUseInfo pui = getPackageUseInfo(mFooUser0);
+ assertIsUsedByOtherApps(mFooUser0, pui, false);
+ assertEquals(secondaries.size(), pui.getDexUseInfoMap().size());
+
+ String[] allExpectedContexts = DexoptUtils.processContextForDexLoad(
+ Arrays.asList(mFooUser0.mClassLoader),
+ Arrays.asList(String.join(File.pathSeparator, dexFiles)));
+ String[] secondaryExpectedContexts = Arrays.copyOfRange(allExpectedContexts,
+ baseAndSplitCount, dexFiles.size());
+
+ assertSecondaryUse(mFooUser0, pui, secondaries, /*isUsedByOtherApps*/false, mUser0,
+ secondaryExpectedContexts);
+
+ assertHasDclInfo(mFooUser0, mFooUser0, secondaries);
+ }
+
+ @Test
public void testNotifySecondaryForeign() {
// Foo loads bar secondary files.
List<String> barSecondaries = mBarUser0.getSecondaryDexPaths();
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 72a7f50..ae53692 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -18,15 +18,18 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -34,7 +37,7 @@
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
-import android.util.TimestampedValue;
+import android.os.TimestampedValue;
import androidx.test.runner.AndroidJUnit4;
@@ -77,6 +80,22 @@
mHandlerThread.join();
}
+ @Test(expected = SecurityException.class)
+ public void testSuggestPhoneTime_withoutPermission() {
+ doThrow(new SecurityException("Mock"))
+ .when(mMockContext).enforceCallingPermission(anyString(), any());
+ PhoneTimeSuggestion phoneTimeSuggestion = createPhoneTimeSuggestion();
+
+ try {
+ mTimeDetectorService.suggestPhoneTime(phoneTimeSuggestion);
+ fail();
+ } finally {
+ verify(mMockContext).enforceCallingPermission(
+ eq(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE),
+ anyString());
+ }
+ }
+
@Test
public void testSuggestPhoneTime() throws Exception {
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
@@ -86,13 +105,29 @@
mTestHandler.assertTotalMessagesEnqueued(1);
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.SET_TIME),
+ eq(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE),
anyString());
mTestHandler.waitForEmptyQueue();
mStubbedTimeDetectorStrategy.verifySuggestPhoneTimeCalled(phoneTimeSuggestion);
}
+ @Test(expected = SecurityException.class)
+ public void testSuggestManualTime_withoutPermission() {
+ doThrow(new SecurityException("Mock"))
+ .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+ ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion();
+
+ try {
+ mTimeDetectorService.suggestManualTime(manualTimeSuggestion);
+ fail();
+ } finally {
+ verify(mMockContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE),
+ anyString());
+ }
+ }
+
@Test
public void testSuggestManualTime() throws Exception {
doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
@@ -102,13 +137,43 @@
mTestHandler.assertTotalMessagesEnqueued(1);
verify(mMockContext).enforceCallingOrSelfPermission(
- eq(android.Manifest.permission.SET_TIME),
+ eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE),
anyString());
mTestHandler.waitForEmptyQueue();
mStubbedTimeDetectorStrategy.verifySuggestManualTimeCalled(manualTimeSuggestion);
}
+ @Test(expected = SecurityException.class)
+ public void testSuggestNetworkTime_withoutPermission() {
+ doThrow(new SecurityException("Mock"))
+ .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+ NetworkTimeSuggestion NetworkTimeSuggestion = createNetworkTimeSuggestion();
+
+ try {
+ mTimeDetectorService.suggestNetworkTime(NetworkTimeSuggestion);
+ fail();
+ } finally {
+ verify(mMockContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.SET_TIME), anyString());
+ }
+ }
+
+ @Test
+ public void testSuggestNetworkTime() throws Exception {
+ doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+
+ NetworkTimeSuggestion NetworkTimeSuggestion = createNetworkTimeSuggestion();
+ mTimeDetectorService.suggestNetworkTime(NetworkTimeSuggestion);
+ mTestHandler.assertTotalMessagesEnqueued(1);
+
+ verify(mMockContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.SET_TIME), anyString());
+
+ mTestHandler.waitForEmptyQueue();
+ mStubbedTimeDetectorStrategy.verifySuggestNetworkTimeCalled(NetworkTimeSuggestion);
+ }
+
@Test
public void testDump() {
when(mMockContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP))
@@ -146,11 +211,17 @@
return new ManualTimeSuggestion(timeValue);
}
+ private static NetworkTimeSuggestion createNetworkTimeSuggestion() {
+ TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
+ return new NetworkTimeSuggestion(timeValue);
+ }
+
private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
// Call tracking.
private PhoneTimeSuggestion mLastPhoneSuggestion;
private ManualTimeSuggestion mLastManualSuggestion;
+ private NetworkTimeSuggestion mLastNetworkSuggestion;
private boolean mLastAutoTimeDetectionToggleCalled;
private boolean mDumpCalled;
@@ -171,6 +242,12 @@
}
@Override
+ public void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion) {
+ resetCallTracking();
+ mLastNetworkSuggestion = timeSuggestion;
+ }
+
+ @Override
public void handleAutoTimeDetectionChanged() {
resetCallTracking();
mLastAutoTimeDetectionToggleCalled = true;
@@ -185,6 +262,7 @@
void resetCallTracking() {
mLastPhoneSuggestion = null;
mLastManualSuggestion = null;
+ mLastNetworkSuggestion = null;
mLastAutoTimeDetectionToggleCalled = false;
mDumpCalled = false;
}
@@ -197,6 +275,10 @@
assertEquals(expectedSuggestion, mLastManualSuggestion);
}
+ public void verifySuggestNetworkTimeCalled(NetworkTimeSuggestion expectedSuggestion) {
+ assertEquals(expectedSuggestion, mLastNetworkSuggestion);
+ }
+
void verifyHandleAutoTimeDetectionToggleCalled() {
assertTrue(mLastAutoTimeDetectionToggleCalled);
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 1aa3d8f..d940a6a 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -18,18 +18,17 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
-import android.content.Intent;
import android.icu.util.Calendar;
import android.icu.util.GregorianCalendar;
import android.icu.util.TimeZone;
-import android.util.TimestampedValue;
+import android.os.TimestampedValue;
import androidx.test.runner.AndroidJUnit4;
@@ -45,14 +44,16 @@
private static final TimestampedValue<Long> ARBITRARY_CLOCK_INITIALIZATION_INFO =
new TimestampedValue<>(
123456789L /* realtimeClockMillis */,
- createUtcTime(1977, 1, 1, 12, 0, 0));
+ createUtcTime(2008, 5, 23, 12, 0, 0));
+ /**
+ * An arbitrary time, very different from the {@link #ARBITRARY_CLOCK_INITIALIZATION_INFO}
+ * time. Can be used as the basis for time suggestions.
+ */
private static final long ARBITRARY_TEST_TIME_MILLIS = createUtcTime(2018, 1, 1, 12, 0, 0);
private static final int ARBITRARY_PHONE_ID = 123456;
- private static final long ONE_DAY_MILLIS = Duration.ofDays(1).toMillis();
-
private Script mScript;
@Before
@@ -67,15 +68,15 @@
int phoneId = ARBITRARY_PHONE_ID;
long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+
PhoneTimeSuggestion timeSuggestion =
mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
- int clockIncrement = 1000;
- long expectedSystemClockMillis = testTimeMillis + clockIncrement;
+ mScript.simulateTimePassing()
+ .simulatePhoneTimeSuggestion(timeSuggestion);
- mScript.simulateTimePassing(clockIncrement)
- .simulatePhoneTimeSuggestion(timeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
.assertLatestPhoneSuggestion(phoneId, timeSuggestion);
}
@@ -94,30 +95,27 @@
@Test
public void testSuggestPhoneTime_systemClockThreshold() {
- int systemClockUpdateThresholdMillis = 1000;
+ final int systemClockUpdateThresholdMillis = 1000;
+ final int clockIncrementMillis = 100;
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeThresholds(systemClockUpdateThresholdMillis)
.pokeAutoTimeDetectionEnabled(true);
- final int clockIncrement = 100;
int phoneId = ARBITRARY_PHONE_ID;
// Send the first time signal. It should be used.
{
- long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
PhoneTimeSuggestion timeSuggestion1 =
- mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
- TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
+ mScript.generatePhoneTimeSuggestion(phoneId, ARBITRARY_TEST_TIME_MILLIS);
// Increment the the device clocks to simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis1 =
- TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+ mScript.calculateTimeInMillisForNow(timeSuggestion1.getUtcTime());
mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis1, true /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
.assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
}
@@ -127,7 +125,7 @@
int underThresholdMillis = systemClockUpdateThresholdMillis - 1;
PhoneTimeSuggestion timeSuggestion2 = mScript.generatePhoneTimeSuggestion(
phoneId, mScript.peekSystemClockMillis() + underThresholdMillis);
- mScript.simulateTimePassing(clockIncrement)
+ mScript.simulateTimePassing(clockIncrementMillis)
.simulatePhoneTimeSuggestion(timeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
@@ -138,15 +136,13 @@
PhoneTimeSuggestion timeSuggestion3 = mScript.generatePhoneTimeSuggestion(
phoneId,
mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis3 =
- TimeDetectorStrategy.getTimeAt(timeSuggestion3.getUtcTime(),
- mScript.peekElapsedRealtimeMillis());
+ mScript.calculateTimeInMillisForNow(timeSuggestion3.getUtcTime());
mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis3, true /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis3)
.assertLatestPhoneSuggestion(phoneId, timeSuggestion3);
}
}
@@ -162,50 +158,48 @@
int phone1Id = ARBITRARY_PHONE_ID;
int phone2Id = ARBITRARY_PHONE_ID + 1;
long phone1TimeMillis = ARBITRARY_TEST_TIME_MILLIS;
- long phone2TimeMillis = phone1TimeMillis + 60000;
-
- final int clockIncrement = 999;
+ long phone2TimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(1).toMillis();
// Make a suggestion with phone2Id.
{
PhoneTimeSuggestion phone2TimeSuggestion =
mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
- long expectedSystemClockMillis = phone2TimeMillis + clockIncrement;
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(phone2TimeSuggestion.getUtcTime());
mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
.assertLatestPhoneSuggestion(phone1Id, null)
.assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
}
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
// Now make a different suggestion with phone1Id.
{
PhoneTimeSuggestion phone1TimeSuggestion =
mScript.generatePhoneTimeSuggestion(phone1Id, phone1TimeMillis);
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
- long expectedSystemClockMillis = phone1TimeMillis + clockIncrement;
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(phone1TimeSuggestion.getUtcTime());
mScript.simulatePhoneTimeSuggestion(phone1TimeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
.assertLatestPhoneSuggestion(phone1Id, phone1TimeSuggestion);
}
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
// Make another suggestion with phone2Id. It should be stored but not used because the
// phone1Id suggestion will still "win".
{
PhoneTimeSuggestion phone2TimeSuggestion =
mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
@@ -220,13 +214,13 @@
{
PhoneTimeSuggestion phone2TimeSuggestion =
mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
- long expectedSystemClockMillis = phone2TimeMillis + clockIncrement;
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(phone2TimeSuggestion.getUtcTime());
mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
.assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
}
}
@@ -239,7 +233,7 @@
int phoneId = ARBITRARY_PHONE_ID;
PhoneTimeSuggestion timeSuggestion =
mScript.generatePhoneTimeSuggestion(phoneId, ARBITRARY_TEST_TIME_MILLIS);
- mScript.simulateTimePassing(1000)
+ mScript.simulateTimePassing()
.simulatePhoneTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestPhoneSuggestion(phoneId, timeSuggestion);
@@ -260,12 +254,10 @@
TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
// Initialize the strategy / device with a time set from a phone suggestion.
- mScript.simulateTimePassing(100);
- long expectedSystemClockMillis1 =
- TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+ mScript.simulateTimePassing();
+ long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(utcTime1);
mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis1, true /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
.assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
// The UTC time increment should be larger than the system clock update threshold so we
@@ -299,13 +291,11 @@
long validReferenceTimeMillis = utcTime1.getReferenceTimeMillis() + 100;
TimestampedValue<Long> utcTime4 = new TimestampedValue<>(
validReferenceTimeMillis, validUtcTimeMillis);
- long expectedSystemClockMillis4 =
- TimeDetectorStrategy.getTimeAt(utcTime4, mScript.peekElapsedRealtimeMillis());
+ long expectedSystemClockMillis4 = mScript.calculateTimeInMillisForNow(utcTime4);
PhoneTimeSuggestion timeSuggestion4 =
createPhoneTimeSuggestion(phoneId, utcTime4);
mScript.simulatePhoneTimeSuggestion(timeSuggestion4)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis4, true /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis4)
.assertLatestPhoneSuggestion(phoneId, timeSuggestion4);
}
@@ -335,13 +325,11 @@
// Simulate more time passing.
mScript.simulateTimePassing(clockIncrementMillis);
- long expectedSystemClockMillis1 =
- TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+ long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(utcTime1);
// Turn on auto time detection.
mScript.simulateAutoTimeDetectionToggle()
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis1, true /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
.assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
// Turn off auto time detection.
@@ -357,8 +345,8 @@
// Simulate more time passing.
mScript.simulateTimePassing(clockIncrementMillis);
- long expectedSystemClockMillis2 = TimeDetectorStrategy.getTimeAt(
- timeSuggestion2.getUtcTime(), mScript.peekElapsedRealtimeMillis());
+ long expectedSystemClockMillis2 =
+ mScript.calculateTimeInMillisForNow(timeSuggestion2.getUtcTime());
// The new time, though valid, should not be set in the system clock because auto time is
// disabled.
@@ -368,8 +356,7 @@
// Turn on auto time detection.
mScript.simulateAutoTimeDetectionToggle()
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis2, true /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis2)
.assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
}
@@ -382,19 +369,21 @@
long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
PhoneTimeSuggestion phoneSuggestion =
mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
- int clockIncrementMillis = 1000;
- mScript.simulateTimePassing(clockIncrementMillis)
- .simulatePhoneTimeSuggestion(phoneSuggestion)
+ mScript.simulateTimePassing();
+
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(phoneSuggestion.getUtcTime());
+ mScript.simulatePhoneTimeSuggestion(phoneSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
- testTimeMillis + clockIncrementMillis, true /* expectedNetworkBroadcast */)
+ expectedSystemClockMillis /* expectedNetworkBroadcast */)
.assertLatestPhoneSuggestion(phoneId, phoneSuggestion);
// Look inside and check what the strategy considers the current best phone suggestion.
assertEquals(phoneSuggestion, mScript.peekBestPhoneSuggestion());
// Simulate time passing, long enough that phoneSuggestion is now too old.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.PHONE_MAX_AGE_MILLIS);
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS);
// Look inside and check what the strategy considers the current best phone suggestion. It
// should still be the, it's just no longer used.
@@ -407,15 +396,15 @@
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(false);
- long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
- ManualTimeSuggestion timeSuggestion = mScript.generateManualTimeSuggestion(testTimeMillis);
- final int clockIncrement = 1000;
- long expectedSystemClockMillis = testTimeMillis + clockIncrement;
+ ManualTimeSuggestion timeSuggestion =
+ mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
- mScript.simulateTimePassing(clockIncrement)
- .simulateManualTimeSuggestion(timeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis, false /* expectNetworkBroadcast */);
+ mScript.simulateTimePassing();
+
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.simulateManualTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@Test
@@ -430,21 +419,18 @@
long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
PhoneTimeSuggestion phoneTimeSuggestion =
mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
- long expectedAutoClockMillis = phoneTimeSuggestion.getUtcTime().getValue();
- final int clockIncrement = 1000;
// Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
+ mScript.simulateTimePassing();
+ long expectedAutoClockMillis =
+ mScript.calculateTimeInMillisForNow(phoneTimeSuggestion.getUtcTime());
mScript.simulatePhoneTimeSuggestion(phoneTimeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedAutoClockMillis, true /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
.assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
// Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
+ mScript.simulateTimePassing();
// Switch to manual.
mScript.simulateAutoTimeDetectionToggle()
@@ -452,28 +438,29 @@
.assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
// Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
+ mScript.simulateTimePassing();
// Simulate a manual suggestion 1 day different from the auto suggestion.
- long manualTimeMillis = testTimeMillis + ONE_DAY_MILLIS;
- long expectedManualClockMillis = manualTimeMillis;
+ long manualTimeMillis = testTimeMillis + Duration.ofDays(1).toMillis();
ManualTimeSuggestion manualTimeSuggestion =
mScript.generateManualTimeSuggestion(manualTimeMillis);
+ mScript.simulateTimePassing();
+
+ long expectedManualClockMillis =
+ mScript.calculateTimeInMillisForNow(manualTimeSuggestion.getUtcTime());
mScript.simulateManualTimeSuggestion(manualTimeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedManualClockMillis, false /* expectNetworkBroadcast */)
+ .verifySystemClockWasSetAndResetCallTracking(expectedManualClockMillis)
.assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
// Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
+ mScript.simulateTimePassing();
// Switch back to auto.
mScript.simulateAutoTimeDetectionToggle();
- mScript.verifySystemClockWasSetAndResetCallTracking(
- expectedAutoClockMillis, true /* expectNetworkBroadcast */)
+ expectedAutoClockMillis =
+ mScript.calculateTimeInMillisForNow(phoneTimeSuggestion.getUtcTime());
+ mScript.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
.assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
// Switch back to manual - nothing should happen to the clock.
@@ -492,13 +479,139 @@
ManualTimeSuggestion timeSuggestion =
mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
- final int clockIncrement = 1000;
- mScript.simulateTimePassing(clockIncrement)
+ mScript.simulateTimePassing()
.simulateManualTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
+ @Test
+ public void testSuggestNetworkTime_autoTimeEnabled() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ NetworkTimeSuggestion timeSuggestion =
+ mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
+
+ mScript.simulateTimePassing();
+
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
+ }
+
+ @Test
+ public void testSuggestNetworkTime_autoTimeDisabled() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(false);
+
+ NetworkTimeSuggestion timeSuggestion =
+ mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
+
+ mScript.simulateTimePassing()
+ .simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestNetworkTime_phoneSuggestionsBeatNetworkSuggestions() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ // Three obviously different times that could not be mistaken for each other.
+ long networkTimeMillis1 = ARBITRARY_TEST_TIME_MILLIS;
+ long networkTimeMillis2 = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(30).toMillis();
+ long phoneTimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(60).toMillis();
+ // A small increment used to simulate the passage of time, but not enough to interfere with
+ // macro-level time changes associated with suggestion age.
+ final long smallTimeIncrementMillis = 101;
+
+ // A network suggestion is made. It should be used because there is no phone suggestion.
+ NetworkTimeSuggestion networkTimeSuggestion1 =
+ mScript.generateNetworkTimeSuggestion(networkTimeMillis1);
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .simulateNetworkTimeSuggestion(networkTimeSuggestion1)
+ .verifySystemClockWasSetAndResetCallTracking(
+ mScript.calculateTimeInMillisForNow(networkTimeSuggestion1.getUtcTime()));
+
+ // Check internal state.
+ mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, null)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion1);
+ assertEquals(networkTimeSuggestion1, mScript.peekLatestValidNetworkSuggestion());
+ assertNull(mScript.peekBestPhoneSuggestion());
+
+ // Simulate a little time passing.
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Now a phone suggestion is made. Phone suggestions are prioritized over network
+ // suggestions so it should "win".
+ PhoneTimeSuggestion phoneTimeSuggestion =
+ mScript.generatePhoneTimeSuggestion(ARBITRARY_PHONE_ID, phoneTimeMillis);
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .simulatePhoneTimeSuggestion(phoneTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ mScript.calculateTimeInMillisForNow(phoneTimeSuggestion.getUtcTime()));
+
+ // Check internal state.
+ mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion1);
+ assertEquals(networkTimeSuggestion1, mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(phoneTimeSuggestion, mScript.peekBestPhoneSuggestion());
+
+ // Simulate some significant time passing: half the time allowed before a time signal
+ // becomes "too old to use".
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Now another network suggestion is made. Phone suggestions are prioritized over network
+ // suggestions so the latest phone suggestion should still "win".
+ NetworkTimeSuggestion networkTimeSuggestion2 =
+ mScript.generateNetworkTimeSuggestion(networkTimeMillis2);
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .simulateNetworkTimeSuggestion(networkTimeSuggestion2)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Check internal state.
+ mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion2);
+ assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(phoneTimeSuggestion, mScript.peekBestPhoneSuggestion());
+
+ // Simulate some significant time passing: half the time allowed before a time signal
+ // becomes "too old to use". This should mean that phoneTimeSuggestion is now too old to be
+ // used but networkTimeSuggestion2 is not.
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2);
+
+ // NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
+ // suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle
+ // to re-run the detection logic. This may change in future but until then we rely on a
+ // steady stream of suggestions to re-evaluate.
+ mScript.verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Check internal state.
+ mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion2);
+ assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
+ assertNull(mScript.peekBestPhoneSuggestion());
+
+ // Toggle auto-time off and on to force the detection logic to run.
+ mScript.simulateAutoTimeDetectionToggle()
+ .simulateTimePassing(smallTimeIncrementMillis)
+ .simulateAutoTimeDetectionToggle();
+
+ // Verify the latest network time now wins.
+ mScript.verifySystemClockWasSetAndResetCallTracking(
+ mScript.calculateTimeInMillisForNow(networkTimeSuggestion2.getUtcTime()));
+
+ // Check internal state.
+ mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion2);
+ assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
+ assertNull(mScript.peekBestPhoneSuggestion());
+ }
+
/**
* A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
* like the real thing should, it also asserts preconditions.
@@ -512,7 +625,6 @@
// Tracking operations.
private boolean mSystemClockWasSet;
- private Intent mBroadcastSent;
@Override
public int systemClockUpdateThresholdMillis() {
@@ -539,7 +651,6 @@
@Override
public long systemClockMillis() {
- assertWakeLockAcquired();
return mSystemClockMillis;
}
@@ -556,12 +667,6 @@
mWakeLockAcquired = false;
}
- @Override
- public void sendStickyBroadcast(Intent intent) {
- assertNotNull(intent);
- mBroadcastSent = intent;
- }
-
// Methods below are for managing the fake's behavior.
void pokeSystemClockUpdateThreshold(int thresholdMillis) {
@@ -606,17 +711,8 @@
assertEquals(expectedSystemClockMillis, mSystemClockMillis);
}
- void verifyIntentWasBroadcast() {
- assertTrue(mBroadcastSent != null);
- }
-
- void verifyIntentWasNotBroadcast() {
- assertNull(mBroadcastSent);
- }
-
void resetCallTracking() {
mSystemClockWasSet = false;
- mBroadcastSent = null;
}
private void assertWakeLockAcquired() {
@@ -674,6 +770,11 @@
return this;
}
+ Script simulateNetworkTimeSuggestion(NetworkTimeSuggestion timeSuggestion) {
+ mTimeDetectorStrategy.suggestNetworkTime(timeSuggestion);
+ return this;
+ }
+
Script simulateAutoTimeDetectionToggle() {
mFakeCallback.simulateAutoTimeZoneDetectionToggle();
mTimeDetectorStrategy.handleAutoTimeDetectionChanged();
@@ -685,19 +786,21 @@
return this;
}
+ /**
+ * Simulates time passing by an arbitrary (but relatively small) amount.
+ */
+ Script simulateTimePassing() {
+ return simulateTimePassing(999);
+ }
+
Script verifySystemClockWasNotSetAndResetCallTracking() {
mFakeCallback.verifySystemClockNotSet();
- mFakeCallback.verifyIntentWasNotBroadcast();
mFakeCallback.resetCallTracking();
return this;
}
- Script verifySystemClockWasSetAndResetCallTracking(
- long expectedSystemClockMillis, boolean expectNetworkBroadcast) {
+ Script verifySystemClockWasSetAndResetCallTracking(long expectedSystemClockMillis) {
mFakeCallback.verifySystemClockWasSet(expectedSystemClockMillis);
- if (expectNetworkBroadcast) {
- mFakeCallback.verifyIntentWasBroadcast();
- }
mFakeCallback.resetCallTracking();
return this;
}
@@ -711,14 +814,30 @@
}
/**
+ * White box test info: Asserts the latest network suggestion is as expected.
+ */
+ Script assertLatestNetworkSuggestion(NetworkTimeSuggestion expected) {
+ assertEquals(expected, mTimeDetectorStrategy.getLatestNetworkSuggestion());
+ return this;
+ }
+
+ /**
* White box test info: Returns the phone suggestion that would be used, if any, given the
- * current elapsed real time clock.
+ * current elapsed real time clock and regardless of origin prioritization.
*/
PhoneTimeSuggestion peekBestPhoneSuggestion() {
return mTimeDetectorStrategy.findBestPhoneSuggestionForTests();
}
/**
+ * White box test info: Returns the network suggestion that would be used, if any, given the
+ * current elapsed real time clock and regardless of origin prioritization.
+ */
+ NetworkTimeSuggestion peekLatestValidNetworkSuggestion() {
+ return mTimeDetectorStrategy.findLatestValidNetworkSuggestionForTests();
+ }
+
+ /**
* Generates a ManualTimeSuggestion using the current elapsed realtime clock for the
* reference time.
*/
@@ -739,6 +858,24 @@
}
return createPhoneTimeSuggestion(phoneId, time);
}
+
+ /**
+ * Generates a NetworkTimeSuggestion using the current elapsed realtime clock for the
+ * reference time.
+ */
+ NetworkTimeSuggestion generateNetworkTimeSuggestion(long timeMillis) {
+ TimestampedValue<Long> utcTime =
+ new TimestampedValue<>(mFakeCallback.peekElapsedRealtimeMillis(), timeMillis);
+ return new NetworkTimeSuggestion(utcTime);
+ }
+
+ /**
+ * Calculates what the supplied time would be when adjusted for the movement of the fake
+ * elapsed realtime clock.
+ */
+ long calculateTimeInMillisForNow(TimestampedValue<Long> utcTime) {
+ return TimeDetectorStrategy.getTimeAt(utcTime, peekElapsedRealtimeMillis());
+ }
}
private static PhoneTimeSuggestion createPhoneTimeSuggestion(int phoneId,
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyTest.java
index 239d413..f1e9191 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyTest.java
@@ -18,7 +18,7 @@
import static org.junit.Assert.assertEquals;
-import android.util.TimestampedValue;
+import android.os.TimestampedValue;
import androidx.test.runner.AndroidJUnit4;
diff --git a/telecomm/TEST_MAPPING b/telecomm/TEST_MAPPING
new file mode 100644
index 0000000..d585666
--- /dev/null
+++ b/telecomm/TEST_MAPPING
@@ -0,0 +1,29 @@
+{
+ "presubmit": [
+ {
+ "name": "TeleServiceTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TelecomUnitTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TelephonyProviderTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java
index 8b8c86b..ea641f8 100644
--- a/telecomm/java/android/telecom/AudioState.java
+++ b/telecomm/java/android/telecom/AudioState.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 0ebf71f..acf51f3 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -20,12 +20,11 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import com.android.internal.telecom.IVideoProvider;
@@ -575,6 +574,7 @@
private final Bundle mExtras;
private final Bundle mIntentExtras;
private final long mCreationTimeMillis;
+ private final String mContactDisplayName;
private final @CallDirection int mCallDirection;
private final @Connection.VerificationStatus int mCallerNumberVerificationStatus;
@@ -882,6 +882,17 @@
}
/**
+ * Returns the name of the caller on the remote end, as derived from a
+ * {@link android.provider.ContactsContract} lookup of the call's handle.
+ * @return The name of the caller, or {@code null} if the lookup is not yet complete, if
+ * there's no contacts entry for the caller, or if the {@link InCallService} does
+ * not hold the {@link android.Manifest.permission#READ_CONTACTS} permission.
+ */
+ public @Nullable String getContactDisplayName() {
+ return mContactDisplayName;
+ }
+
+ /**
* Indicates whether the call is an incoming or outgoing call.
* @return The call's direction.
*/
@@ -919,6 +930,7 @@
areBundlesEqual(mExtras, d.mExtras) &&
areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
+ Objects.equals(mContactDisplayName, d.mContactDisplayName) &&
Objects.equals(mCallDirection, d.mCallDirection) &&
Objects.equals(mCallerNumberVerificationStatus,
d.mCallerNumberVerificationStatus);
@@ -943,6 +955,7 @@
mExtras,
mIntentExtras,
mCreationTimeMillis,
+ mContactDisplayName,
mCallDirection,
mCallerNumberVerificationStatus);
}
@@ -965,6 +978,7 @@
Bundle extras,
Bundle intentExtras,
long creationTimeMillis,
+ String contactDisplayName,
int callDirection,
int callerNumberVerificationStatus) {
mTelecomCallId = telecomCallId;
@@ -983,6 +997,7 @@
mExtras = extras;
mIntentExtras = intentExtras;
mCreationTimeMillis = creationTimeMillis;
+ mContactDisplayName = contactDisplayName;
mCallDirection = callDirection;
mCallerNumberVerificationStatus = callerNumberVerificationStatus;
}
@@ -1006,6 +1021,7 @@
parcelableCall.getExtras(),
parcelableCall.getIntentExtras(),
parcelableCall.getCreationTimeMillis(),
+ parcelableCall.getContactDisplayName(),
parcelableCall.getCallDirection(),
parcelableCall.getCallerNumberVerificationStatus());
}
@@ -1455,6 +1471,7 @@
private boolean mChildrenCached;
private String mParentId = null;
+ private String mActiveGenericConferenceChild = null;
private int mState;
private List<String> mCannedTextResponses = null;
private String mCallingPackage;
@@ -1953,6 +1970,20 @@
}
/**
+ * Returns the child {@link Call} in a generic conference that is currently active.
+ * For calls that are not generic conferences, or when the generic conference has more than
+ * 2 children, returns {@code null}.
+ * @see Details#PROPERTY_GENERIC_CONFERENCE
+ * @return The active child call.
+ */
+ public @Nullable Call getGenericConferenceActiveChildCall() {
+ if (mActiveGenericConferenceChild != null) {
+ return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild);
+ }
+ return null;
+ }
+
+ /**
* Obtains a list of canned, pre-configured message responses to present to the user as
* ways of rejecting this {@code Call} using via a text message.
*
@@ -2200,6 +2231,13 @@
mChildrenCached = false;
}
+ String activeChildCallId = parcelableCall.getActiveChildCallId();
+ boolean activeChildChanged = !Objects.equals(activeChildCallId,
+ mActiveGenericConferenceChild);
+ if (activeChildChanged) {
+ mActiveGenericConferenceChild = activeChildCallId;
+ }
+
List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
for (String otherId : conferenceableCallIds) {
@@ -2259,7 +2297,7 @@
if (parentChanged) {
fireParentChanged(getParent());
}
- if (childrenChanged) {
+ if (childrenChanged || activeChildChanged) {
fireChildrenChanged(getChildren());
}
if (isRttChanged) {
diff --git a/telecomm/java/android/telecom/CallerInfo.java b/telecomm/java/android/telecom/CallerInfo.java
index a5d25e2..fb6f994 100644
--- a/telecomm/java/android/telecom/CallerInfo.java
+++ b/telecomm/java/android/telecom/CallerInfo.java
@@ -17,7 +17,7 @@
package android.telecom;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -41,8 +41,8 @@
import com.android.i18n.phonenumbers.PhoneNumberUtil;
import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.android.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
-
import com.android.internal.annotations.VisibleForTesting;
+
import java.util.Locale;
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index a6f79fc..c934625 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -21,9 +21,9 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Notification;
import android.bluetooth.BluetoothDevice;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.hardware.camera2.CameraManager;
import android.net.Uri;
@@ -511,51 +511,116 @@
//**********************************************************************************************
/**
- * Define IMS Audio Codec
+ * Indicates that the audio codec is currently not specified or is unknown.
*/
- // Current audio codec is NONE
public static final int AUDIO_CODEC_NONE = ImsStreamMediaProfile.AUDIO_QUALITY_NONE; // 0
- // Current audio codec is AMR
+ /**
+ * Adaptive Multi-rate audio codec.
+ */
public static final int AUDIO_CODEC_AMR = ImsStreamMediaProfile.AUDIO_QUALITY_AMR; // 1
- // Current audio codec is AMR_WB
+ /**
+ * Adaptive Multi-rate wideband audio codec.
+ */
public static final int AUDIO_CODEC_AMR_WB = ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB; // 2
- // Current audio codec is QCELP13K
+ /**
+ * Qualcomm code-excited linear prediction 13 kilobit audio codec.
+ */
public static final int AUDIO_CODEC_QCELP13K = ImsStreamMediaProfile.AUDIO_QUALITY_QCELP13K; //3
- // Current audio codec is EVRC
+ /**
+ * Enhanced Variable Rate Codec. See 3GPP2 C.S0014-A.
+ */
public static final int AUDIO_CODEC_EVRC = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC; // 4
- // Current audio codec is EVRC_B
+ /**
+ * Enhanced Variable Rate Codec B. Commonly used on CDMA networks.
+ */
public static final int AUDIO_CODEC_EVRC_B = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_B; // 5
- // Current audio codec is EVRC_WB
+ /**
+ * Enhanced Variable Rate Wideband Codec. See RFC5188.
+ */
public static final int AUDIO_CODEC_EVRC_WB = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB; // 6
- // Current audio codec is EVRC_NW
+ /**
+ * Enhanced Variable Rate Narrowband-Wideband Codec.
+ */
public static final int AUDIO_CODEC_EVRC_NW = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_NW; // 7
- // Current audio codec is GSM_EFR
+ /**
+ * GSM Enhanced Full-Rate audio codec, also known as GSM-EFR, GSM 06.60, or simply EFR.
+ */
public static final int AUDIO_CODEC_GSM_EFR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_EFR; // 8
- // Current audio codec is GSM_FR
+ /**
+ * GSM Full-Rate audio codec, also known as GSM-FR, GSM 06.10, GSM, or simply FR.
+ */
public static final int AUDIO_CODEC_GSM_FR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_FR; // 9
- // Current audio codec is GSM_HR
+ /**
+ * GSM Half Rate audio codec.
+ */
public static final int AUDIO_CODEC_GSM_HR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_HR; // 10
- // Current audio codec is G711U
+ /**
+ * ITU-T G711U audio codec.
+ */
public static final int AUDIO_CODEC_G711U = ImsStreamMediaProfile.AUDIO_QUALITY_G711U; // 11
- // Current audio codec is G723
+ /**
+ * ITU-T G723 audio codec.
+ */
public static final int AUDIO_CODEC_G723 = ImsStreamMediaProfile.AUDIO_QUALITY_G723; // 12
- // Current audio codec is G711A
+ /**
+ * ITU-T G711A audio codec.
+ */
public static final int AUDIO_CODEC_G711A = ImsStreamMediaProfile.AUDIO_QUALITY_G711A; // 13
- // Current audio codec is G722
+ /**
+ * ITU-T G722 audio codec.
+ */
public static final int AUDIO_CODEC_G722 = ImsStreamMediaProfile.AUDIO_QUALITY_G722; // 14
- // Current audio codec is G711AB
+ /**
+ * ITU-T G711AB audio codec.
+ */
public static final int AUDIO_CODEC_G711AB = ImsStreamMediaProfile.AUDIO_QUALITY_G711AB; // 15
- // Current audio codec is G729
+ /**
+ * ITU-T G729 audio codec.
+ */
public static final int AUDIO_CODEC_G729 = ImsStreamMediaProfile.AUDIO_QUALITY_G729; // 16
- // Current audio codec is EVS_NB
+ /**
+ * Enhanced Voice Services Narrowband audio codec. See 3GPP TS 26.441.
+ */
public static final int AUDIO_CODEC_EVS_NB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_NB; // 17
- // Current audio codec is EVS_WB
+ /**
+ * Enhanced Voice Services Wideband audio codec. See 3GPP TS 26.441.
+ */
public static final int AUDIO_CODEC_EVS_WB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_WB; // 18
- // Current audio codec is EVS_SWB
+ /**
+ * Enhanced Voice Services Super-Wideband audio codec. See 3GPP TS 26.441.
+ */
public static final int AUDIO_CODEC_EVS_SWB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB; // 19
- // Current audio codec is EVS_FB
+ /**
+ * Enhanced Voice Services Fullband audio codec. See 3GPP TS 26.441.
+ */
public static final int AUDIO_CODEC_EVS_FB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_FB; // 20
+ /**@hide*/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "AUDIO_CODEC_", value = {
+ AUDIO_CODEC_NONE,
+ AUDIO_CODEC_AMR,
+ AUDIO_CODEC_AMR_WB,
+ AUDIO_CODEC_QCELP13K,
+ AUDIO_CODEC_EVRC,
+ AUDIO_CODEC_EVRC_B,
+ AUDIO_CODEC_EVRC_WB,
+ AUDIO_CODEC_EVRC_NW,
+ AUDIO_CODEC_GSM_EFR,
+ AUDIO_CODEC_GSM_FR,
+ AUDIO_CODEC_GSM_HR,
+ AUDIO_CODEC_G711U,
+ AUDIO_CODEC_G723,
+ AUDIO_CODEC_G711A,
+ AUDIO_CODEC_G722,
+ AUDIO_CODEC_G711AB,
+ AUDIO_CODEC_G729,
+ AUDIO_CODEC_EVS_NB,
+ AUDIO_CODEC_EVS_SWB,
+ AUDIO_CODEC_EVS_FB
+ })
+ public @interface AudioCodec {}
+
/**
* Connection extra key used to store the last forwarded number associated with the current
* connection. Used to communicate to the user interface that the connection was forwarded via
@@ -649,10 +714,10 @@
"android.telecom.extra.IS_RTT_AUDIO_PRESENT";
/**
- * The audio codec in use for the current {@link Connection}, if known. Valid values include
- * {@link #AUDIO_CODEC_AMR_WB} and {@link #AUDIO_CODEC_EVS_WB}.
+ * The audio codec in use for the current {@link Connection}, if known. Examples of valid
+ * values include {@link #AUDIO_CODEC_AMR_WB} and {@link #AUDIO_CODEC_EVS_WB}.
*/
- public static final String EXTRA_AUDIO_CODEC =
+ public static final @AudioCodec String EXTRA_AUDIO_CODEC =
"android.telecom.extra.AUDIO_CODEC";
/**
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 7d4ee76..4f6a9d6 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -16,7 +16,7 @@
package android.telecom;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index a234bb0..415a817 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -16,27 +16,286 @@
package android.telecom;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.Nullable;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.telecom.Call.Details.CallDirection;
+import com.android.internal.telecom.IVideoProvider;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import com.android.internal.telecom.IVideoProvider;
-
/**
* Information about a call that is used between InCallService and Telecom.
* @hide
*/
public final class ParcelableCall implements Parcelable {
+
+ public static class ParcelableCallBuilder {
+ private String mId;
+ private int mState;
+ private DisconnectCause mDisconnectCause;
+ private List<String> mCannedSmsResponses;
+ private int mCapabilities;
+ private int mProperties;
+ private int mSupportedAudioRoutes;
+ private long mConnectTimeMillis;
+ private Uri mHandle;
+ private int mHandlePresentation;
+ private String mCallerDisplayName;
+ private int mCallerDisplayNamePresentation;
+ private GatewayInfo mGatewayInfo;
+ private PhoneAccountHandle mAccountHandle;
+ private boolean mIsVideoCallProviderChanged;
+ private IVideoProvider mVideoCallProvider;
+ private boolean mIsRttCallChanged;
+ private ParcelableRttCall mRttCall;
+ private String mParentCallId;
+ private List<String> mChildCallIds;
+ private StatusHints mStatusHints;
+ private int mVideoState;
+ private List<String> mConferenceableCallIds;
+ private Bundle mIntentExtras;
+ private Bundle mExtras;
+ private long mCreationTimeMillis;
+ private int mCallDirection;
+ private int mCallerNumberVerificationStatus;
+ private String mContactDisplayName;
+ private String mActiveChildCallId;
+
+ public ParcelableCallBuilder setId(String id) {
+ mId = id;
+ return this;
+ }
+
+ public ParcelableCallBuilder setState(int state) {
+ mState = state;
+ return this;
+ }
+
+ public ParcelableCallBuilder setDisconnectCause(DisconnectCause disconnectCause) {
+ mDisconnectCause = disconnectCause;
+ return this;
+ }
+
+ public ParcelableCallBuilder setCannedSmsResponses(List<String> cannedSmsResponses) {
+ mCannedSmsResponses = cannedSmsResponses;
+ return this;
+ }
+
+ public ParcelableCallBuilder setCapabilities(int capabilities) {
+ mCapabilities = capabilities;
+ return this;
+ }
+
+ public ParcelableCallBuilder setProperties(int properties) {
+ mProperties = properties;
+ return this;
+ }
+
+ public ParcelableCallBuilder setSupportedAudioRoutes(int supportedAudioRoutes) {
+ mSupportedAudioRoutes = supportedAudioRoutes;
+ return this;
+ }
+
+ public ParcelableCallBuilder setConnectTimeMillis(long connectTimeMillis) {
+ mConnectTimeMillis = connectTimeMillis;
+ return this;
+ }
+
+ public ParcelableCallBuilder setHandle(Uri handle) {
+ mHandle = handle;
+ return this;
+ }
+
+ public ParcelableCallBuilder setHandlePresentation(int handlePresentation) {
+ mHandlePresentation = handlePresentation;
+ return this;
+ }
+
+ public ParcelableCallBuilder setCallerDisplayName(String callerDisplayName) {
+ mCallerDisplayName = callerDisplayName;
+ return this;
+ }
+
+ public ParcelableCallBuilder setCallerDisplayNamePresentation(
+ int callerDisplayNamePresentation) {
+ mCallerDisplayNamePresentation = callerDisplayNamePresentation;
+ return this;
+ }
+
+ public ParcelableCallBuilder setGatewayInfo(GatewayInfo gatewayInfo) {
+ mGatewayInfo = gatewayInfo;
+ return this;
+ }
+
+ public ParcelableCallBuilder setAccountHandle(PhoneAccountHandle accountHandle) {
+ mAccountHandle = accountHandle;
+ return this;
+ }
+
+ public ParcelableCallBuilder setIsVideoCallProviderChanged(
+ boolean isVideoCallProviderChanged) {
+ mIsVideoCallProviderChanged = isVideoCallProviderChanged;
+ return this;
+ }
+
+ public ParcelableCallBuilder setVideoCallProvider(IVideoProvider videoCallProvider) {
+ mVideoCallProvider = videoCallProvider;
+ return this;
+ }
+
+ public ParcelableCallBuilder setIsRttCallChanged(boolean isRttCallChanged) {
+ mIsRttCallChanged = isRttCallChanged;
+ return this;
+ }
+
+ public ParcelableCallBuilder setRttCall(ParcelableRttCall rttCall) {
+ mRttCall = rttCall;
+ return this;
+ }
+
+ public ParcelableCallBuilder setParentCallId(String parentCallId) {
+ mParentCallId = parentCallId;
+ return this;
+ }
+
+ public ParcelableCallBuilder setChildCallIds(List<String> childCallIds) {
+ mChildCallIds = childCallIds;
+ return this;
+ }
+
+ public ParcelableCallBuilder setStatusHints(StatusHints statusHints) {
+ mStatusHints = statusHints;
+ return this;
+ }
+
+ public ParcelableCallBuilder setVideoState(int videoState) {
+ mVideoState = videoState;
+ return this;
+ }
+
+ public ParcelableCallBuilder setConferenceableCallIds(
+ List<String> conferenceableCallIds) {
+ mConferenceableCallIds = conferenceableCallIds;
+ return this;
+ }
+
+ public ParcelableCallBuilder setIntentExtras(Bundle intentExtras) {
+ mIntentExtras = intentExtras;
+ return this;
+ }
+
+ public ParcelableCallBuilder setExtras(Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ public ParcelableCallBuilder setCreationTimeMillis(long creationTimeMillis) {
+ mCreationTimeMillis = creationTimeMillis;
+ return this;
+ }
+
+ public ParcelableCallBuilder setCallDirection(int callDirection) {
+ mCallDirection = callDirection;
+ return this;
+ }
+
+ public ParcelableCallBuilder setCallerNumberVerificationStatus(
+ int callerNumberVerificationStatus) {
+ mCallerNumberVerificationStatus = callerNumberVerificationStatus;
+ return this;
+ }
+
+ public ParcelableCallBuilder setContactDisplayName(String contactDisplayName) {
+ mContactDisplayName = contactDisplayName;
+ return this;
+ }
+
+ public ParcelableCallBuilder setActiveChildCallId(String activeChildCallId) {
+ mActiveChildCallId = activeChildCallId;
+ return this;
+ }
+
+ public ParcelableCall createParcelableCall() {
+ return new ParcelableCall(
+ mId,
+ mState,
+ mDisconnectCause,
+ mCannedSmsResponses,
+ mCapabilities,
+ mProperties,
+ mSupportedAudioRoutes,
+ mConnectTimeMillis,
+ mHandle,
+ mHandlePresentation,
+ mCallerDisplayName,
+ mCallerDisplayNamePresentation,
+ mGatewayInfo,
+ mAccountHandle,
+ mIsVideoCallProviderChanged,
+ mVideoCallProvider,
+ mIsRttCallChanged,
+ mRttCall,
+ mParentCallId,
+ mChildCallIds,
+ mStatusHints,
+ mVideoState,
+ mConferenceableCallIds,
+ mIntentExtras,
+ mExtras,
+ mCreationTimeMillis,
+ mCallDirection,
+ mCallerNumberVerificationStatus,
+ mContactDisplayName,
+ mActiveChildCallId);
+ }
+
+ public static ParcelableCallBuilder fromParcelableCall(ParcelableCall parcelableCall) {
+ ParcelableCallBuilder newBuilder = new ParcelableCallBuilder();
+ newBuilder.mId = parcelableCall.mId;
+ newBuilder.mState = parcelableCall.mState;
+ newBuilder.mDisconnectCause = parcelableCall.mDisconnectCause;
+ newBuilder.mCannedSmsResponses = parcelableCall.mCannedSmsResponses;
+ newBuilder.mCapabilities = parcelableCall.mCapabilities;
+ newBuilder.mProperties = parcelableCall.mProperties;
+ newBuilder.mSupportedAudioRoutes = parcelableCall.mSupportedAudioRoutes;
+ newBuilder.mConnectTimeMillis = parcelableCall.mConnectTimeMillis;
+ newBuilder.mHandle = parcelableCall.mHandle;
+ newBuilder.mHandlePresentation = parcelableCall.mHandlePresentation;
+ newBuilder.mCallerDisplayName = parcelableCall.mCallerDisplayName;
+ newBuilder.mCallerDisplayNamePresentation =
+ parcelableCall.mCallerDisplayNamePresentation;
+ newBuilder.mGatewayInfo = parcelableCall.mGatewayInfo;
+ newBuilder.mAccountHandle = parcelableCall.mAccountHandle;
+ newBuilder.mIsVideoCallProviderChanged = parcelableCall.mIsVideoCallProviderChanged;
+ newBuilder.mVideoCallProvider = parcelableCall.mVideoCallProvider;
+ newBuilder.mIsRttCallChanged = parcelableCall.mIsRttCallChanged;
+ newBuilder.mRttCall = parcelableCall.mRttCall;
+ newBuilder.mParentCallId = parcelableCall.mParentCallId;
+ newBuilder.mChildCallIds = parcelableCall.mChildCallIds;
+ newBuilder.mStatusHints = parcelableCall.mStatusHints;
+ newBuilder.mVideoState = parcelableCall.mVideoState;
+ newBuilder.mConferenceableCallIds = parcelableCall.mConferenceableCallIds;
+ newBuilder.mIntentExtras = parcelableCall.mIntentExtras;
+ newBuilder.mExtras = parcelableCall.mExtras;
+ newBuilder.mCreationTimeMillis = parcelableCall.mCreationTimeMillis;
+ newBuilder.mCallDirection = parcelableCall.mCallDirection;
+ newBuilder.mCallerNumberVerificationStatus =
+ parcelableCall.mCallerNumberVerificationStatus;
+ newBuilder.mContactDisplayName = parcelableCall.mContactDisplayName;
+ newBuilder.mActiveChildCallId = parcelableCall.mActiveChildCallId;
+ return newBuilder;
+ }
+ }
+
private final String mId;
private final int mState;
private final DisconnectCause mDisconnectCause;
@@ -66,6 +325,8 @@
private final long mCreationTimeMillis;
private final int mCallDirection;
private final int mCallerNumberVerificationStatus;
+ private final String mContactDisplayName;
+ private final String mActiveChildCallId; // Only valid for CDMA conferences
public ParcelableCall(
String id,
@@ -95,7 +356,10 @@
Bundle extras,
long creationTimeMillis,
int callDirection,
- int callerNumberVerificationStatus) {
+ int callerNumberVerificationStatus,
+ String contactDisplayName,
+ String activeChildCallId
+ ) {
mId = id;
mState = state;
mDisconnectCause = disconnectCause;
@@ -124,6 +388,8 @@
mCreationTimeMillis = creationTimeMillis;
mCallDirection = callDirection;
mCallerNumberVerificationStatus = callerNumberVerificationStatus;
+ mContactDisplayName = contactDisplayName;
+ mActiveChildCallId = activeChildCallId;
}
/** The unique ID of the call. */
@@ -333,6 +599,21 @@
return mCallerNumberVerificationStatus;
}
+ /**
+ * @return the name of the remote party as derived from a contacts DB lookup.
+ */
+ public @Nullable String getContactDisplayName() {
+ return mContactDisplayName;
+ }
+
+ /**
+ * @return On a CDMA conference with two participants, returns the ID of the child call that's
+ * currently active.
+ */
+ public @Nullable String getActiveChildCallId() {
+ return mActiveChildCallId;
+ }
+
/** Responsible for creating ParcelableCall objects for deserialized Parcels. */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public static final @android.annotation.NonNull Parcelable.Creator<ParcelableCall> CREATOR =
@@ -372,35 +653,40 @@
long creationTimeMillis = source.readLong();
int callDirection = source.readInt();
int callerNumberVerificationStatus = source.readInt();
- return new ParcelableCall(
- id,
- state,
- disconnectCause,
- cannedSmsResponses,
- capabilities,
- properties,
- supportedAudioRoutes,
- connectTimeMillis,
- handle,
- handlePresentation,
- callerDisplayName,
- callerDisplayNamePresentation,
- gatewayInfo,
- accountHandle,
- isVideoCallProviderChanged,
- videoCallProvider,
- isRttCallChanged,
- rttCall,
- parentCallId,
- childCallIds,
- statusHints,
- videoState,
- conferenceableCallIds,
- intentExtras,
- extras,
- creationTimeMillis,
- callDirection,
- callerNumberVerificationStatus);
+ String contactDisplayName = source.readString();
+ String activeChildCallId = source.readString();
+ return new ParcelableCallBuilder()
+ .setId(id)
+ .setState(state)
+ .setDisconnectCause(disconnectCause)
+ .setCannedSmsResponses(cannedSmsResponses)
+ .setCapabilities(capabilities)
+ .setProperties(properties)
+ .setSupportedAudioRoutes(supportedAudioRoutes)
+ .setConnectTimeMillis(connectTimeMillis)
+ .setHandle(handle)
+ .setHandlePresentation(handlePresentation)
+ .setCallerDisplayName(callerDisplayName)
+ .setCallerDisplayNamePresentation(callerDisplayNamePresentation)
+ .setGatewayInfo(gatewayInfo)
+ .setAccountHandle(accountHandle)
+ .setIsVideoCallProviderChanged(isVideoCallProviderChanged)
+ .setVideoCallProvider(videoCallProvider)
+ .setIsRttCallChanged(isRttCallChanged)
+ .setRttCall(rttCall)
+ .setParentCallId(parentCallId)
+ .setChildCallIds(childCallIds)
+ .setStatusHints(statusHints)
+ .setVideoState(videoState)
+ .setConferenceableCallIds(conferenceableCallIds)
+ .setIntentExtras(intentExtras)
+ .setExtras(extras)
+ .setCreationTimeMillis(creationTimeMillis)
+ .setCallDirection(callDirection)
+ .setCallerNumberVerificationStatus(callerNumberVerificationStatus)
+ .setContactDisplayName(contactDisplayName)
+ .setActiveChildCallId(activeChildCallId)
+ .createParcelableCall();
}
@Override
@@ -447,6 +733,8 @@
destination.writeLong(mCreationTimeMillis);
destination.writeInt(mCallDirection);
destination.writeInt(mCallerNumberVerificationStatus);
+ destination.writeString(mContactDisplayName);
+ destination.writeString(mActiveChildCallId);
}
@Override
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 61a639a1..a427ed6 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -17,8 +17,8 @@
package android.telecom;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.bluetooth.BluetoothDevice;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.util.ArrayMap;
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index eb568e0..e1bcb5f 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Build;
import android.os.Parcel;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 68f5bf6..f1dca03 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -26,7 +26,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -848,6 +848,17 @@
*/
public static final int PRESENTATION_PAYPHONE = 4;
+
+ /*
+ * Values for the adb property "persist.radio.videocall.audio.output"
+ */
+ /** @hide */
+ public static final int AUDIO_OUTPUT_ENABLE_SPEAKER = 0;
+ /** @hide */
+ public static final int AUDIO_OUTPUT_DISABLE_SPEAKER = 1;
+ /** @hide */
+ public static final int AUDIO_OUTPUT_DEFAULT = AUDIO_OUTPUT_ENABLE_SPEAKER;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index 4a1aa0a..109e7f8 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -16,7 +16,7 @@
package android.telecom;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index 64e6ca3..4197f3c 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -19,7 +19,6 @@
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 2a6e8de..58a7ea0 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -14,4 +14,5 @@
refuhoo@google.com
paulye@google.com
nazaninb@google.com
-sarahchin@google.com
\ No newline at end of file
+sarahchin@google.com
+dbright@google.com
diff --git a/telephony/TEST_MAPPING b/telephony/TEST_MAPPING
new file mode 100644
index 0000000..d585666
--- /dev/null
+++ b/telephony/TEST_MAPPING
@@ -0,0 +1,29 @@
+{
+ "presubmit": [
+ {
+ "name": "TeleServiceTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TelecomUnitTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TelephonyProviderTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java
similarity index 92%
rename from telephony/java/android/telephony/LocationAccessPolicy.java
rename to telephony/common/android/telephony/LocationAccessPolicy.java
index d4526a4..8ac6755 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -11,13 +11,14 @@
* 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
+ * limitations under the License.
*/
package android.telephony;
import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -59,8 +60,10 @@
DENIED_HARD,
}
+ /** Data structure for location permission query */
public static class LocationPermissionQuery {
public final String callingPackage;
+ public final String callingFeatureId;
public final int callingUid;
public final int callingPid;
public final int minSdkVersionForCoarse;
@@ -68,10 +71,11 @@
public final boolean logAsInfo;
public final String method;
- private LocationPermissionQuery(String callingPackage, int callingUid, int callingPid,
- int minSdkVersionForCoarse, int minSdkVersionForFine, boolean logAsInfo,
- String method) {
+ private LocationPermissionQuery(String callingPackage, @Nullable String callingFeatureId,
+ int callingUid, int callingPid, int minSdkVersionForCoarse,
+ int minSdkVersionForFine, boolean logAsInfo, String method) {
this.callingPackage = callingPackage;
+ this.callingFeatureId = callingFeatureId;
this.callingUid = callingUid;
this.callingPid = callingPid;
this.minSdkVersionForCoarse = minSdkVersionForCoarse;
@@ -80,8 +84,10 @@
this.method = method;
}
+ /** Builder for LocationPermissionQuery */
public static class Builder {
private String mCallingPackage;
+ private String mCallingFeatureId;
private int mCallingUid;
private int mCallingPid;
private int mMinSdkVersionForCoarse = Integer.MAX_VALUE;
@@ -100,6 +106,11 @@
/**
* Mandatory parameter, used for performing permission checks.
*/
+ public Builder setCallingFeatureId(@Nullable String callingFeatureId) {
+ mCallingFeatureId = callingFeatureId;
+ return this;
+ }
+
public Builder setCallingUid(int callingUid) {
mCallingUid = callingUid;
return this;
@@ -149,9 +160,10 @@
return this;
}
+ /** build LocationPermissionQuery */
public LocationPermissionQuery build() {
- return new LocationPermissionQuery(mCallingPackage, mCallingUid,
- mCallingPid, mMinSdkVersionForCoarse, mMinSdkVersionForFine,
+ return new LocationPermissionQuery(mCallingPackage, mCallingFeatureId,
+ mCallingUid, mCallingPid, mMinSdkVersionForCoarse, mMinSdkVersionForFine,
mLogAsInfo, mMethod);
}
}
@@ -235,6 +247,7 @@
}
}
+ /** Check if location permissions have been granted */
public static LocationPermissionResult checkLocationPermission(
Context context, LocationPermissionQuery query) {
// Always allow the phone process and system server to access location. This avoid
@@ -341,4 +354,4 @@
}
return false;
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
similarity index 91%
rename from telephony/java/com/android/internal/telephony/CarrierAppUtils.java
rename to telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index 0630454..3f5aa0f 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package com.android.internal.telephony;
@@ -24,10 +24,10 @@
import android.content.res.Resources;
import android.os.RemoteException;
import android.provider.Settings;
+import android.util.Log;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.Slog;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -73,11 +73,11 @@
* system startup prior to any application running, as well as any time the set of carrier
* privileged apps may have changed.
*/
- public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
+ public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
IPackageManager packageManager, TelephonyManager telephonyManager,
ContentResolver contentResolver, int userId) {
if (DEBUG) {
- Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
+ Log.d(TAG, "disableCarrierAppsUntilPrivileged");
}
SystemConfig config = SystemConfig.getInstance();
ArraySet<String> systemCarrierAppsDisabledUntilUsed =
@@ -100,10 +100,10 @@
* broadcasts. The app will continue to run (briefly) after being disabled, before the Package
* Manager can kill it, and this can lead to crashes as the app is in an unexpected state.
*/
- public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
+ public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
IPackageManager packageManager, ContentResolver contentResolver, int userId) {
if (DEBUG) {
- Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
+ Log.d(TAG, "disableCarrierAppsUntilPrivileged");
}
SystemConfig config = SystemConfig.getInstance();
ArraySet<String> systemCarrierAppsDisabledUntilUsed =
@@ -117,7 +117,10 @@
systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed);
}
- // Must be public b/c framework unit tests can't access package-private methods.
+ /**
+ * Disable carrier apps until they are privileged
+ * Must be public b/c framework unit tests can't access package-private methods.
+ */
@VisibleForTesting
public static void disableCarrierAppsUntilPrivileged(String callingPackage,
IPackageManager packageManager, @Nullable TelephonyManager telephonyManager,
@@ -166,12 +169,12 @@
// Only update enabled state for the app on /system. Once it has been
// updated we shouldn't touch it.
if (!ai.isUpdatedSystemApp()
- && (ai.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
- || ai.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
+ && (ai.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ || ai.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
|| (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0)) {
- Slog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+ Log.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+ userId);
packageManager.setSystemAppInstallState(
packageName,
@@ -188,13 +191,13 @@
// Also enable any associated apps for this carrier app.
if (associatedAppList != null) {
for (ApplicationInfo associatedApp : associatedAppList) {
- if (associatedApp.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
- || associatedApp.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
+ if (associatedApp.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ || associatedApp.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
|| (associatedApp.flags
& ApplicationInfo.FLAG_INSTALLED) == 0) {
- Slog.i(TAG, "Update associated state(" + associatedApp.packageName
+ Log.i(TAG, "Update associated state(" + associatedApp.packageName
+ "): ENABLED for user " + userId);
packageManager.setSystemAppInstallState(
associatedApp.packageName,
@@ -216,10 +219,10 @@
// Only update enabled state for the app on /system. Once it has been
// updated we shouldn't touch it.
if (!ai.isUpdatedSystemApp()
- && ai.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ && ai.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
&& (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
- Slog.i(TAG, "Update state(" + packageName
+ Log.i(TAG, "Update state(" + packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
packageManager.setSystemAppInstallState(
packageName,
@@ -237,7 +240,7 @@
== PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
&& (associatedApp.flags
& ApplicationInfo.FLAG_INSTALLED) != 0) {
- Slog.i(TAG,
+ Log.i(TAG,
"Update associated state(" + associatedApp.packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
packageManager.setSystemAppInstallState(
@@ -265,7 +268,7 @@
packageManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId);
}
} catch (RemoteException e) {
- Slog.w(TAG, "Could not reach PackageManager", e);
+ Log.w(TAG, "Could not reach PackageManager", e);
}
}
@@ -291,8 +294,8 @@
ApplicationInfo ai = candidates.get(i);
String packageName = ai.packageName;
boolean hasPrivileges =
- telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
- TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
if (!hasPrivileges) {
candidates.remove(i);
}
@@ -387,7 +390,7 @@
return ai;
}
} catch (RemoteException e) {
- Slog.w(TAG, "Could not reach PackageManager", e);
+ Log.w(TAG, "Could not reach PackageManager", e);
}
return null;
}
diff --git a/telephony/common/com/android/internal/telephony/EncodeException.java b/telephony/common/com/android/internal/telephony/EncodeException.java
index cdc853e..bb723a0 100644
--- a/telephony/common/com/android/internal/telephony/EncodeException.java
+++ b/telephony/common/com/android/internal/telephony/EncodeException.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* {@hide}
diff --git a/telephony/common/com/android/internal/telephony/GsmAlphabet.java b/telephony/common/com/android/internal/telephony/GsmAlphabet.java
index 79d3660..60cd400 100644
--- a/telephony/common/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/common/com/android/internal/telephony/GsmAlphabet.java
@@ -16,10 +16,10 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.os.Build;
-import android.telephony.Rlog;
+import android.util.Log;
import android.text.TextUtils;
import android.util.SparseIntArray;
@@ -496,11 +496,11 @@
StringBuilder ret = new StringBuilder(lengthSeptets);
if (languageTable < 0 || languageTable > sLanguageTables.length) {
- Rlog.w(TAG, "unknown language table " + languageTable + ", using default");
+ Log.w(TAG, "unknown language table " + languageTable + ", using default");
languageTable = 0;
}
if (shiftTable < 0 || shiftTable > sLanguageShiftTables.length) {
- Rlog.w(TAG, "unknown single shift table " + shiftTable + ", using default");
+ Log.w(TAG, "unknown single shift table " + shiftTable + ", using default");
shiftTable = 0;
}
@@ -510,11 +510,11 @@
String shiftTableToChar = sLanguageShiftTables[shiftTable];
if (languageTableToChar.isEmpty()) {
- Rlog.w(TAG, "no language table for code " + languageTable + ", using default");
+ Log.w(TAG, "no language table for code " + languageTable + ", using default");
languageTableToChar = sLanguageTables[0];
}
if (shiftTableToChar.isEmpty()) {
- Rlog.w(TAG, "no single shift table for code " + shiftTable + ", using default");
+ Log.w(TAG, "no single shift table for code " + shiftTable + ", using default");
shiftTableToChar = sLanguageShiftTables[0];
}
@@ -554,7 +554,7 @@
}
}
} catch (RuntimeException ex) {
- Rlog.e(TAG, "Error GSM 7 bit packed: ", ex);
+ Log.e(TAG, "Error GSM 7 bit packed: ", ex);
return null;
}
@@ -811,7 +811,7 @@
for (int i = 0; i < sz; i++) {
char c = s.charAt(i);
if (c == GSM_EXTENDED_ESCAPE) {
- Rlog.w(TAG, "countGsmSeptets() string contains Escape character, skipping.");
+ Log.w(TAG, "countGsmSeptets() string contains Escape character, skipping.");
continue;
}
if (charToLanguageTable.get(c, -1) != -1) {
@@ -890,7 +890,7 @@
for (int i = 0; i < sz && !lpcList.isEmpty(); i++) {
char c = s.charAt(i);
if (c == GSM_EXTENDED_ESCAPE) {
- Rlog.w(TAG, "countGsmSeptets() string contains Escape character, ignoring!");
+ Log.w(TAG, "countGsmSeptets() string contains Escape character, ignoring!");
continue;
}
// iterate through enabled locking shift tables
@@ -1494,7 +1494,7 @@
int numTables = sLanguageTables.length;
int numShiftTables = sLanguageShiftTables.length;
if (numTables != numShiftTables) {
- Rlog.e(TAG, "Error: language tables array length " + numTables +
+ Log.e(TAG, "Error: language tables array length " + numTables +
" != shift tables array length " + numShiftTables);
}
@@ -1504,7 +1504,7 @@
int tableLen = table.length();
if (tableLen != 0 && tableLen != 128) {
- Rlog.e(TAG, "Error: language tables index " + i +
+ Log.e(TAG, "Error: language tables index " + i +
" length " + tableLen + " (expected 128 or 0)");
}
@@ -1522,7 +1522,7 @@
int shiftTableLen = shiftTable.length();
if (shiftTableLen != 0 && shiftTableLen != 128) {
- Rlog.e(TAG, "Error: language shift tables index " + i +
+ Log.e(TAG, "Error: language shift tables index " + i +
" length " + shiftTableLen + " (expected 128 or 0)");
}
diff --git a/telephony/common/com/android/internal/telephony/HbpcdUtils.java b/telephony/common/com/android/internal/telephony/HbpcdUtils.java
index 2f31942..714f5a6 100644
--- a/telephony/common/com/android/internal/telephony/HbpcdUtils.java
+++ b/telephony/common/com/android/internal/telephony/HbpcdUtils.java
@@ -19,7 +19,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
-import android.telephony.Rlog;
+import android.util.Log;
import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch;
import com.android.internal.telephony.HbpcdLookup.MccIdd;
@@ -54,16 +54,16 @@
if (c2 != null) {
int c2Counter = c2.getCount();
if (DBG) {
- Rlog.d(LOG_TAG, "Query unresolved arbitrary table, entries are " + c2Counter);
+ Log.d(LOG_TAG, "Query unresolved arbitrary table, entries are " + c2Counter);
}
if (c2Counter == 1) {
if (DBG) {
- Rlog.d(LOG_TAG, "Query Unresolved arbitrary returned the cursor " + c2);
+ Log.d(LOG_TAG, "Query Unresolved arbitrary returned the cursor " + c2);
}
c2.moveToFirst();
tmpMcc = c2.getInt(0);
if (DBG) {
- Rlog.d(LOG_TAG, "MCC found in arbitrary_mcc_sid_match: " + tmpMcc);
+ Log.d(LOG_TAG, "MCC found in arbitrary_mcc_sid_match: " + tmpMcc);
}
c2.close();
return tmpMcc;
@@ -85,18 +85,18 @@
int c3Counter = c3.getCount();
if (c3Counter > 0) {
if (c3Counter > 1) {
- Rlog.w(LOG_TAG, "something wrong, get more results for 1 conflict SID: " + c3);
+ Log.w(LOG_TAG, "something wrong, get more results for 1 conflict SID: " + c3);
}
- if (DBG) Rlog.d(LOG_TAG, "Query conflict sid returned the cursor " + c3);
+ if (DBG) Log.d(LOG_TAG, "Query conflict sid returned the cursor " + c3);
c3.moveToFirst();
tmpMcc = c3.getInt(0);
if (DBG) {
- Rlog.d(LOG_TAG, "MCC found in mcc_lookup_table. Return tmpMcc = " + tmpMcc);
+ Log.d(LOG_TAG, "MCC found in mcc_lookup_table. Return tmpMcc = " + tmpMcc);
}
if (!isNitzTimeZone) {
// time zone is not accurate, it may get wrong mcc, ignore it.
if (DBG) {
- Rlog.d(LOG_TAG, "time zone is not accurate, mcc may be " + tmpMcc);
+ Log.d(LOG_TAG, "time zone is not accurate, mcc may be " + tmpMcc);
}
tmpMcc = 0;
}
@@ -115,18 +115,18 @@
null, null);
if (c5 != null) {
if (c5.getCount() > 0) {
- if (DBG) Rlog.d(LOG_TAG, "Query Range returned the cursor " + c5);
+ if (DBG) Log.d(LOG_TAG, "Query Range returned the cursor " + c5);
c5.moveToFirst();
tmpMcc = c5.getInt(0);
- if (DBG) Rlog.d(LOG_TAG, "SID found in mcc_sid_range. Return tmpMcc = " + tmpMcc);
+ if (DBG) Log.d(LOG_TAG, "SID found in mcc_sid_range. Return tmpMcc = " + tmpMcc);
c5.close();
return tmpMcc;
}
c5.close();
}
- if (DBG) Rlog.d(LOG_TAG, "SID NOT found in mcc_sid_range.");
+ if (DBG) Log.d(LOG_TAG, "SID NOT found in mcc_sid_range.");
- if (DBG) Rlog.d(LOG_TAG, "Exit getMccByOtherFactors. Return tmpMcc = " + tmpMcc);
+ if (DBG) Log.d(LOG_TAG, "Exit getMccByOtherFactors. Return tmpMcc = " + tmpMcc);
// If unknown MCC still could not be resolved,
return tmpMcc;
}
@@ -135,7 +135,7 @@
* Gets country information with given MCC.
*/
public String getIddByMcc(int mcc) {
- if (DBG) Rlog.d(LOG_TAG, "Enter getHbpcdInfoByMCC.");
+ if (DBG) Log.d(LOG_TAG, "Enter getHbpcdInfoByMCC.");
String idd = "";
Cursor c = null;
@@ -145,19 +145,19 @@
MccIdd.MCC + "=" + mcc, null, null);
if (cur != null) {
if (cur.getCount() > 0) {
- if (DBG) Rlog.d(LOG_TAG, "Query Idd returned the cursor " + cur);
+ if (DBG) Log.d(LOG_TAG, "Query Idd returned the cursor " + cur);
// TODO: for those country having more than 1 IDDs, need more information
// to decide which IDD would be used. currently just use the first 1.
cur.moveToFirst();
idd = cur.getString(0);
- if (DBG) Rlog.d(LOG_TAG, "IDD = " + idd);
+ if (DBG) Log.d(LOG_TAG, "IDD = " + idd);
}
cur.close();
}
if (c != null) c.close();
- if (DBG) Rlog.d(LOG_TAG, "Exit getHbpcdInfoByMCC.");
+ if (DBG) Log.d(LOG_TAG, "Exit getHbpcdInfoByMCC.");
return idd;
}
}
diff --git a/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java b/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
index 922af12..0b47547 100644
--- a/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
+++ b/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
@@ -24,17 +24,17 @@
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.UserHandle;
-import com.android.internal.os.BackgroundThread;
-
/**
* Helper class for monitoring the state of packages: adding, removing,
* updating, and disappearing and reappearing on the SD card.
*/
public abstract class PackageChangeReceiver extends BroadcastReceiver {
static final IntentFilter sPackageIntentFilter = new IntentFilter();
+ private static HandlerThread sHandlerThread;
static {
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -43,28 +43,24 @@
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
sPackageIntentFilter.addDataScheme("package");
}
+ // Keep an instance of Context around as long as we still want the receiver:
+ // if the instance of Context gets garbage-collected, it'll unregister the receiver, so only
+ // unset when we want to unregister.
Context mRegisteredContext;
/**
- * To register the intents that needed for monitoring the state of packages
+ * To register the intents that needed for monitoring the state of packages. Once this method
+ * has been called on an instance of {@link PackageChangeReceiver}, all subsequent calls must
+ * have the same {@code user} argument.
*/
public void register(@NonNull Context context, @Nullable Looper thread,
@Nullable UserHandle user) {
if (mRegisteredContext != null) {
throw new IllegalStateException("Already registered");
}
- Handler handler = (thread == null) ? BackgroundThread.getHandler() : new Handler(thread);
- mRegisteredContext = context;
- if (handler != null) {
- if (user != null) {
- context.registerReceiverAsUser(this, user, sPackageIntentFilter, null, handler);
- } else {
- context.registerReceiver(this, sPackageIntentFilter,
- null, handler);
- }
- } else {
- throw new NullPointerException();
- }
+ Handler handler = new Handler(thread == null ? getStaticLooper() : thread);
+ mRegisteredContext = user == null ? context : context.createContextAsUser(user, 0);
+ mRegisteredContext.registerReceiver(this, sPackageIntentFilter, null, handler);
}
/**
@@ -78,6 +74,14 @@
mRegisteredContext = null;
}
+ private static synchronized Looper getStaticLooper() {
+ if (sHandlerThread == null) {
+ sHandlerThread = new HandlerThread(PackageChangeReceiver.class.getSimpleName());
+ sHandlerThread.start();
+ }
+ return sHandlerThread.getLooper();
+ }
+
/**
* This method is invoked when receive the Intent.ACTION_PACKAGE_ADDED
*/
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index df668ea..3a900d9 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.role.RoleManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -40,15 +41,14 @@
import android.provider.Telephony;
import android.provider.Telephony.Sms.Intents;
import android.telephony.PackageChangeReceiver;
-import android.telephony.Rlog;
+import android.util.Log;
import android.telephony.TelephonyManager;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -57,7 +57,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
-
+import java.util.stream.Collectors;
/**
@@ -67,10 +67,10 @@
*/
public final class SmsApplication {
static final String LOG_TAG = "SmsApplication";
- private static final String PHONE_PACKAGE_NAME = "com.android.phone";
- private static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
- private static final String MMS_SERVICE_PACKAGE_NAME = "com.android.mms.service";
- private static final String TELEPHONY_PROVIDER_PACKAGE_NAME = "com.android.providers.telephony";
+ public static final String PHONE_PACKAGE_NAME = "com.android.phone";
+ public static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
+ public static final String MMS_SERVICE_PACKAGE_NAME = "com.android.mms.service";
+ public static final String TELEPHONY_PROVIDER_PACKAGE_NAME = "com.android.providers.telephony";
private static final String SCHEME_SMS = "sms";
private static final String SCHEME_SMSTO = "smsto";
@@ -79,13 +79,13 @@
private static final boolean DEBUG = false;
private static final boolean DEBUG_MULTIUSER = false;
- private static final int[] DEFAULT_APP_EXCLUSIVE_APPOPS = {
- AppOpsManager.OP_READ_SMS,
- AppOpsManager.OP_WRITE_SMS,
- AppOpsManager.OP_RECEIVE_SMS,
- AppOpsManager.OP_RECEIVE_WAP_PUSH,
- AppOpsManager.OP_SEND_SMS,
- AppOpsManager.OP_READ_CELL_BROADCASTS
+ private static final String[] DEFAULT_APP_EXCLUSIVE_APPOPS = {
+ AppOpsManager.OPSTR_READ_SMS,
+ AppOpsManager.OPSTR_WRITE_SMS,
+ AppOpsManager.OPSTR_RECEIVE_SMS,
+ AppOpsManager.OPSTR_RECEIVE_WAP_PUSH,
+ AppOpsManager.OPSTR_SEND_SMS,
+ AppOpsManager.OPSTR_READ_CELL_BROADCASTS
};
private static SmsPackageMonitor sSmsPackageMonitor = null;
@@ -249,6 +249,7 @@
private static Collection<SmsApplicationData> getApplicationCollectionInternal(
Context context, int userId) {
PackageManager packageManager = context.getPackageManager();
+ UserHandle userHandle = UserHandle.of(userId);
// Get the list of apps registered for SMS
Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
@@ -257,7 +258,7 @@
}
List<ResolveInfo> smsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
+ userHandle);
HashMap<String, SmsApplicationData> receivers = new HashMap<String, SmsApplicationData>();
@@ -284,7 +285,7 @@
intent.setDataAndType(null, "application/vnd.wap.mms-message");
List<ResolveInfo> mmsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
+ userHandle);
for (ResolveInfo resolveInfo : mmsReceivers) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo == null) {
@@ -326,7 +327,7 @@
Uri.fromParts(SCHEME_SMSTO, "", null));
List<ResolveInfo> sendToActivities = packageManager.queryIntentActivitiesAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
+ userHandle);
for (ResolveInfo resolveInfo : sendToActivities) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo == null) {
@@ -344,7 +345,7 @@
List<ResolveInfo> smsAppChangedReceivers =
packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
if (DEBUG_MULTIUSER) {
Log.i(LOG_TAG, "getApplicationCollectionInternal smsAppChangedActivities=" +
smsAppChangedReceivers);
@@ -371,7 +372,7 @@
List<ResolveInfo> providerChangedReceivers =
packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
if (DEBUG_MULTIUSER) {
Log.i(LOG_TAG, "getApplicationCollectionInternal providerChangedActivities=" +
providerChangedReceivers);
@@ -398,7 +399,7 @@
List<ResolveInfo> simFullReceivers =
packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
if (DEBUG_MULTIUSER) {
Log.i(LOG_TAG, "getApplicationCollectionInternal simFullReceivers="
+ simFullReceivers);
@@ -501,7 +502,7 @@
// If we found a package, make sure AppOps permissions are set up correctly
if (applicationData != null) {
- // We can only call checkOp if we are privileged (updateIfNeeded) or if the app we
+ // We can only call unsafeCheckOp if we are privileged (updateIfNeeded) or if the app we
// are checking is for our current uid. Doing this check from the unprivileged current
// SMS app allows us to tell the current SMS app that it is not in a good state and
// needs to ask to be the current SMS app again to work properly.
@@ -555,23 +556,23 @@
// apps, all of them should be able to write to telephony provider.
// This is to allow the proxy package permission check in telephony provider
// to pass.
- for (int appop : DEFAULT_APP_EXCLUSIVE_APPOPS) {
- appOps.setUidMode(appop, Process.PHONE_UID, AppOpsManager.MODE_ALLOWED);
+ for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+ appOps.setUidMode(opStr, Process.PHONE_UID, AppOpsManager.MODE_ALLOWED);
}
}
private static boolean tryFixExclusiveSmsAppops(Context context,
SmsApplicationData applicationData, boolean updateIfNeeded) {
AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
- for (int appOp : DEFAULT_APP_EXCLUSIVE_APPOPS) {
- int mode = appOps.checkOp(appOp, applicationData.mUid,
+ for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+ int mode = appOps.unsafeCheckOp(opStr, applicationData.mUid,
applicationData.mPackageName);
if (mode != AppOpsManager.MODE_ALLOWED) {
- Rlog.e(LOG_TAG, applicationData.mPackageName + " lost "
- + AppOpsManager.modeToName(appOp) + ": "
+ Log.e(LOG_TAG, applicationData.mPackageName + " lost "
+ + opStr + ": "
+ (updateIfNeeded ? " (fixing)" : " (no permission to fix)"));
if (updateIfNeeded) {
- appOps.setUidMode(appOp, applicationData.mUid, AppOpsManager.MODE_ALLOWED);
+ appOps.setUidMode(opStr, applicationData.mUid, AppOpsManager.MODE_ALLOWED);
} else {
return false;
}
@@ -630,7 +631,8 @@
}
// We only make the change if the new package is valid
- PackageManager packageManager = context.getPackageManager();
+ PackageManager packageManager =
+ context.createContextAsUser(userHandle, 0).getPackageManager();
Collection<SmsApplicationData> applications = getApplicationCollectionInternal(
context, userId);
SmsApplicationData oldAppData = oldPackageName != null ?
@@ -641,11 +643,10 @@
AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
if (oldPackageName != null) {
try {
- int uid = packageManager.getPackageInfoAsUser(
- oldPackageName, 0, userId).applicationInfo.uid;
+ int uid = packageManager.getPackageInfo(oldPackageName, 0).applicationInfo.uid;
setExclusiveAppops(oldPackageName, appOps, uid, AppOpsManager.MODE_DEFAULT);
} catch (NameNotFoundException e) {
- Rlog.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
+ Log.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
}
}
@@ -752,29 +753,29 @@
// the package signature matches system signature.
final int result = packageManager.checkSignatures(context.getPackageName(), packageName);
if (result != PackageManager.SIGNATURE_MATCH) {
- Rlog.e(LOG_TAG, packageName + " does not have system signature");
+ Log.e(LOG_TAG, packageName + " does not have system signature");
return;
}
try {
PackageInfo info = packageManager.getPackageInfo(packageName, 0);
- int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
+ int mode = appOps.unsafeCheckOp(AppOpsManager.OPSTR_WRITE_SMS, info.applicationInfo.uid,
packageName);
if (mode != AppOpsManager.MODE_ALLOWED) {
- Rlog.w(LOG_TAG, packageName + " does not have OP_WRITE_SMS: (fixing)");
+ Log.w(LOG_TAG, packageName + " does not have OP_WRITE_SMS: (fixing)");
setExclusiveAppops(packageName, appOps, info.applicationInfo.uid,
AppOpsManager.MODE_ALLOWED);
}
} catch (NameNotFoundException e) {
// No whitelisted system app on this device
- Rlog.e(LOG_TAG, "Package not found: " + packageName);
+ Log.e(LOG_TAG, "Package not found: " + packageName);
}
}
private static void setExclusiveAppops(String pkg, AppOpsManager appOpsManager, int uid,
int mode) {
- for (int appop : DEFAULT_APP_EXCLUSIVE_APPOPS) {
- appOpsManager.setUidMode(appop, uid, mode);
+ for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+ appOpsManager.setUidMode(opStr, uid, mode);
}
}
@@ -806,9 +807,16 @@
}
private void onPackageChanged() {
- PackageManager packageManager = mContext.getPackageManager();
+ int userId;
+ try {
+ userId = getSendingUser().getIdentifier();
+ } catch (NullPointerException e) {
+ // This should never happen in prod -- unit tests will put the receiver into a
+ // unusual state where the pending result is null, which produces a NPE when calling
+ // getSendingUserId. Just pretend like it's the system user for testing.
+ userId = UserHandle.USER_SYSTEM;
+ }
Context userContext = mContext;
- final int userId = getSendingUserId();
if (userId != UserHandle.USER_SYSTEM) {
try {
userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
@@ -819,10 +827,11 @@
}
}
}
+ PackageManager packageManager = userContext.getPackageManager();
// Ensure this component is still configured as the preferred activity
ComponentName componentName = getDefaultSendToApplication(userContext, true);
if (componentName != null) {
- configurePreferredActivity(packageManager, componentName, userId);
+ configurePreferredActivity(packageManager, componentName);
}
}
}
@@ -834,41 +843,36 @@
@UnsupportedAppUsage
private static void configurePreferredActivity(PackageManager packageManager,
- ComponentName componentName, int userId) {
+ ComponentName componentName) {
// Add the four activity preferences we want to direct to this app.
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMS);
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMSTO);
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMS);
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMSTO);
+ replacePreferredActivity(packageManager, componentName, SCHEME_SMS);
+ replacePreferredActivity(packageManager, componentName, SCHEME_SMSTO);
+ replacePreferredActivity(packageManager, componentName, SCHEME_MMS);
+ replacePreferredActivity(packageManager, componentName, SCHEME_MMSTO);
}
/**
* Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
*/
private static void replacePreferredActivity(PackageManager packageManager,
- ComponentName componentName, int userId, String scheme) {
+ ComponentName componentName, String scheme) {
// Build the set of existing activities that handle this scheme
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
- List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivitiesAsUser(
- intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER,
- userId);
+ List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(
+ intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);
- // Build the set of ComponentNames for these activities
- final int n = resolveInfoList.size();
- ComponentName[] set = new ComponentName[n];
- for (int i = 0; i < n; i++) {
- ResolveInfo info = resolveInfoList.get(i);
- set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
- }
+ List<ComponentName> components = resolveInfoList.stream().map(info ->
+ new ComponentName(info.activityInfo.packageName, info.activityInfo.name))
+ .collect(Collectors.toList());
// Update the preferred SENDTO activity for the specified scheme
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SENDTO);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
intentFilter.addDataScheme(scheme);
- packageManager.replacePreferredActivityAsUser(intentFilter,
+ packageManager.replacePreferredActivity(intentFilter,
IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
- set, componentName, userId);
+ components, componentName);
}
/**
@@ -899,6 +903,7 @@
* @param userId target user ID.
* @return component name of the app and class to deliver SMS messages to
*/
+ @VisibleForTesting
public static ComponentName getDefaultSmsApplicationAsUser(Context context,
boolean updateIfNeeded, int userId) {
final long token = Binder.clearCallingIdentity();
diff --git a/telephony/common/com/android/internal/telephony/SmsConstants.java b/telephony/common/com/android/internal/telephony/SmsConstants.java
index 19f52b0..3aa8bbf 100644
--- a/telephony/common/com/android/internal/telephony/SmsConstants.java
+++ b/telephony/common/com/android/internal/telephony/SmsConstants.java
@@ -15,7 +15,7 @@
*/
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* SMS Constants and must be the same as the corresponding
diff --git a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
index 06c08f5..cd365a1 100644
--- a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
+++ b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
@@ -24,13 +24,16 @@
import android.os.SystemProperties;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.Base64;
+import android.util.Log;
import com.android.internal.telephony.HbpcdLookup.MccIdd;
import com.android.internal.telephony.HbpcdLookup.MccLookup;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -143,7 +146,7 @@
// First check whether the number is a NANP number.
int nanpState = checkNANP(numberEntry, allIDDs);
- if (DBG) Rlog.d(TAG, "NANP type: " + getNumberPlanType(nanpState));
+ if (DBG) Log.d(TAG, "NANP type: " + getNumberPlanType(nanpState));
if ((nanpState == NP_NANP_LOCAL)
|| (nanpState == NP_NANP_AREA_LOCAL)
@@ -173,7 +176,7 @@
int internationalState = checkInternationalNumberPlan(context, numberEntry, allIDDs,
NANP_IDD);
- if (DBG) Rlog.d(TAG, "International type: " + getNumberPlanType(internationalState));
+ if (DBG) Log.d(TAG, "International type: " + getNumberPlanType(internationalState));
String returnNumber = null;
switch (internationalState) {
@@ -272,7 +275,7 @@
}
}
} catch (SQLException e) {
- Rlog.e(TAG, "Can't access HbpcdLookup database", e);
+ Log.e(TAG, "Can't access HbpcdLookup database", e);
} finally {
if (cursor != null) {
cursor.close();
@@ -281,7 +284,7 @@
IDDS_MAPS.put(mcc, allIDDs);
- if (DBG) Rlog.d(TAG, "MCC = " + mcc + ", all IDDs = " + allIDDs);
+ if (DBG) Log.d(TAG, "MCC = " + mcc + ", all IDDs = " + allIDDs);
return allIDDs;
}
@@ -472,7 +475,7 @@
int tempCC = allCCs[i];
for (int j = 0; j < MAX_COUNTRY_CODES_LENGTH; j ++) {
if (tempCC == ccArray[j]) {
- if (DBG) Rlog.d(TAG, "Country code = " + tempCC);
+ if (DBG) Log.d(TAG, "Country code = " + tempCC);
return tempCC;
}
}
@@ -509,7 +512,7 @@
}
}
} catch (SQLException e) {
- Rlog.e(TAG, "Can't access HbpcdLookup database", e);
+ Log.e(TAG, "Can't access HbpcdLookup database", e);
} finally {
if (cursor != null) {
cursor.close();
@@ -561,10 +564,10 @@
* Filter the destination number if using VZW sim card.
*/
public static String filterDestAddr(Context context, int subId, String destAddr) {
- if (DBG) Rlog.d(TAG, "enter filterDestAddr. destAddr=\"" + Rlog.pii(TAG, destAddr) + "\"" );
+ if (DBG) Log.d(TAG, "enter filterDestAddr. destAddr=\"" + pii(TAG, destAddr) + "\"" );
if (destAddr == null || !PhoneNumberUtils.isGlobalPhoneNumber(destAddr)) {
- Rlog.w(TAG, "destAddr" + Rlog.pii(TAG, destAddr) +
+ Log.w(TAG, "destAddr" + pii(TAG, destAddr) +
" is not a global phone number! Nothing changed.");
return destAddr;
}
@@ -585,9 +588,9 @@
}
if (DBG) {
- Rlog.d(TAG, "destAddr is " + ((result != null)?"formatted.":"not formatted."));
- Rlog.d(TAG, "leave filterDestAddr, new destAddr=\"" + (result != null ? Rlog.pii(TAG,
- result) : Rlog.pii(TAG, destAddr)) + "\"");
+ Log.d(TAG, "destAddr is " + ((result != null)?"formatted.":"not formatted."));
+ Log.d(TAG, "leave filterDestAddr, new destAddr=\"" + (result != null ? pii(TAG,
+ result) : pii(TAG, destAddr)) + "\"");
}
return result != null ? result : destAddr;
}
@@ -608,7 +611,7 @@
networkType = CDMA_HOME_NETWORK;
}
} else {
- if (DBG) Rlog.w(TAG, "warning! unknown mPhoneType value=" + phoneType);
+ if (DBG) Log.w(TAG, "warning! unknown mPhoneType value=" + phoneType);
}
return networkType;
@@ -650,4 +653,44 @@
// by default this value is false
return false;
}
+
+ /**
+ * Redact personally identifiable information for production users.
+ * @param tag used to identify the source of a log message
+ * @param pii the personally identifiable information we want to apply secure hash on.
+ * @return If tag is loggable in verbose mode or pii is null, return the original input.
+ * otherwise return a secure Hash of input pii
+ */
+ private static String pii(String tag, Object pii) {
+ String val = String.valueOf(pii);
+ if (pii == null || TextUtils.isEmpty(val) || Log.isLoggable(tag, Log.VERBOSE)) {
+ return val;
+ }
+ return "[" + secureHash(val.getBytes()) + "]";
+ }
+
+ /**
+ * Returns a secure hash (using the SHA1 algorithm) of the provided input.
+ *
+ * @return "****" if the build type is user, otherwise the hash
+ * @param input the bytes for which the secure hash should be computed.
+ */
+ private static String secureHash(byte[] input) {
+ // Refrain from logging user personal information in user build.
+ if (android.os.Build.IS_USER) {
+ return "****";
+ }
+
+ MessageDigest messageDigest;
+
+ try {
+ messageDigest = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException e) {
+ return "####";
+ }
+
+ byte[] result = messageDigest.digest(input);
+ return Base64.encodeToString(
+ result, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
+ }
}
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 606fd5b..5beb06d 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -18,6 +18,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.Manifest;
+import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
@@ -26,10 +27,7 @@
import android.os.Binder;
import android.os.Build;
import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
-import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -41,7 +39,6 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import java.util.function.Supplier;
/** Utility class for Telephony permission enforcement. */
public final class TelephonyPermissions {
@@ -49,9 +46,6 @@
private static final boolean DBG = false;
- private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
- ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
-
/**
* Whether to disable the new device identifier access restrictions.
*/
@@ -95,16 +89,19 @@
* inaccesible to carrier-privileged apps).
*/
public static boolean checkCallingOrSelfReadPhoneState(
- Context context, int subId, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message) {
return checkReadPhoneState(context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
- callingPackage, message);
+ callingPackage, callingFeatureId, message);
}
/** Identical to checkCallingOrSelfReadPhoneState but never throws SecurityException */
public static boolean checkCallingOrSelfReadPhoneStateNoThrow(
- Context context, int subId, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message) {
try {
- return checkCallingOrSelfReadPhoneState(context, subId, callingPackage, message);
+ return checkCallingOrSelfReadPhoneState(context, subId, callingPackage,
+ callingFeatureId, message);
} catch (SecurityException se) {
return false;
}
@@ -132,49 +129,8 @@
* devices.
*/
public static boolean checkReadPhoneState(
- Context context, int subId, int pid, int uid, String callingPackage, String message) {
- return checkReadPhoneState(
- context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message);
- }
-
- /**
- * Check whether the calling packages has carrier privileges for the passing subscription.
- * @return {@code true} if the caller has carrier privileges, {@false} otherwise.
- */
- public static boolean checkCarrierPrivilegeForSubId(int subId) {
- if (SubscriptionManager.isValidSubscriptionId(subId)
- && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, Binder.getCallingUid())
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
- return true;
- }
- return false;
- }
-
- /**
- * Check whether the app with the given pid/uid can read phone state.
- *
- * <p>This method behaves in one of the following ways:
- * <ul>
- * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
- * READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
- * <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
- * apps which support runtime permissions, if the caller does not currently have any of
- * these permissions.
- * <li>return false: if the caller lacks all of these permissions and doesn't support runtime
- * permissions. This implies that the user revoked the ability to read phone state
- * manually (via AppOps). In this case we can't throw as it would break app compatibility,
- * so we return false to indicate that the calling function should return dummy data.
- * </ul>
- *
- * <p>Note: for simplicity, this method always returns false for callers using legacy
- * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
- * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
- * devices.
- */
- @VisibleForTesting
- public static boolean checkReadPhoneState(
- Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage, String message) {
+ Context context, int subId, int pid, int uid, String callingPackage,
+ @Nullable String callingFeatureId, String message) {
try {
context.enforcePermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -189,7 +145,7 @@
// If we don't have the runtime permission, but do have carrier privileges, that
// suffices for reading phone state.
if (SubscriptionManager.isValidSubscriptionId(subId)) {
- enforceCarrierPrivilege(telephonySupplier, subId, uid, message);
+ enforceCarrierPrivilege(context, subId, uid, message);
return true;
}
throw phoneStateException;
@@ -204,23 +160,16 @@
}
/**
- * Check whether the app with the given pid/uid can read phone state, or has carrier
- * privileges on any active subscription.
- *
- * <p>If the app does not have carrier privilege, this method will return {@code false} instead
- * of throwing a SecurityException. Therefore, the callers cannot tell the difference
- * between M+ apps which declare the runtime permission but do not have it, and pre-M apps
- * which declare the static permission but had access revoked via AppOps. Apps in the former
- * category expect SecurityExceptions; apps in the latter don't. So this method is suitable for
- * use only if the behavior in both scenarios is meant to be identical.
- *
- * @return {@code true} if the app can read phone state or has carrier privilege;
- * {@code false} otherwise.
+ * Check whether the calling packages has carrier privileges for the passing subscription.
+ * @return {@code true} if the caller has carrier privileges, {@false} otherwise.
*/
- public static boolean checkReadPhoneStateOnAnyActiveSub(
- Context context, int pid, int uid, String callingPackage, String message) {
- return checkReadPhoneStateOnAnyActiveSub(context, TELEPHONY_SUPPLIER, pid, uid,
- callingPackage, message);
+ public static boolean checkCarrierPrivilegeForSubId(Context context, int subId) {
+ if (SubscriptionManager.isValidSubscriptionId(subId)
+ && getCarrierPrivilegeStatus(context, subId, Binder.getCallingUid())
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return true;
+ }
+ return false;
}
/**
@@ -237,10 +186,8 @@
* @return {@code true} if the app can read phone state or has carrier privilege;
* {@code false} otherwise.
*/
- @VisibleForTesting
- public static boolean checkReadPhoneStateOnAnyActiveSub(
- Context context, Supplier<ITelephony> telephonySupplier, int pid, int uid,
- String callingPackage, String message) {
+ public static boolean checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid,
+ String callingPackage, @Nullable String callingFeatureId, String message) {
try {
context.enforcePermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -254,7 +201,7 @@
} catch (SecurityException phoneStateException) {
// If we don't have the runtime permission, but do have carrier privileges, that
// suffices for reading phone state.
- return checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid);
+ return checkCarrierPrivilegeForAnySubId(context, uid);
}
}
@@ -283,9 +230,10 @@
* </ul>
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkCallingOrSelfReadDeviceIdentifiers(context,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message);
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, callingFeatureId,
+ message);
}
/**
@@ -306,9 +254,9 @@
* </ul>
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
- context, subId, callingPackage, message, true);
+ context, subId, callingPackage, callingFeatureId, message, true);
}
/**
@@ -328,9 +276,9 @@
* </ul>
*/
public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
- context, subId, callingPackage, message, false);
+ context, subId, callingPackage, callingFeatureId, message, false);
}
/**
@@ -352,8 +300,8 @@
* </ul>
*/
private static boolean checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
- Context context, int subId, String callingPackage, String message,
- boolean allowCarrierPrivilegeOnAnySub) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message, boolean allowCarrierPrivilegeOnAnySub) {
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
// Allow system and root access to the device identifiers.
@@ -368,12 +316,11 @@
}
// If the calling package has carrier privileges for specified sub, then allow access.
- if (checkCarrierPrivilegeForSubId(subId)) return true;
+ if (checkCarrierPrivilegeForSubId(context, subId)) return true;
// If the calling package has carrier privileges for any subscription
// and allowCarrierPrivilegeOnAnySub is set true, then allow access.
- if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(
- context, TELEPHONY_SUPPLIER, uid)) {
+ if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(context, uid)) {
return true;
}
@@ -465,7 +412,7 @@
uid) == PackageManager.PERMISSION_GRANTED) {
return false;
}
- if (checkCarrierPrivilegeForSubId(subId)) {
+ if (checkCarrierPrivilegeForSubId(context, subId)) {
return false;
}
}
@@ -479,27 +426,14 @@
* to it, {@code false} otherwise.
*/
public static boolean checkReadCallLog(
- Context context, int subId, int pid, int uid, String callingPackage) {
- return checkReadCallLog(
- context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage);
- }
-
- /**
- * Check whether the app with the given pid/uid can read the call log.
- * @return {@code true} if the specified app has the read call log permission and AppOpp granted
- * to it, {@code false} otherwise.
- */
- @VisibleForTesting
- public static boolean checkReadCallLog(
- Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage) {
-
+ Context context, int subId, int pid, int uid, String callingPackage,
+ @Nullable String callingPackageName) {
if (context.checkPermission(Manifest.permission.READ_CALL_LOG, pid, uid)
!= PERMISSION_GRANTED) {
// If we don't have the runtime permission, but do have carrier privileges, that
// suffices for being able to see the call phone numbers.
if (SubscriptionManager.isValidSubscriptionId(subId)) {
- enforceCarrierPrivilege(telephonySupplier, subId, uid, "readCallLog");
+ enforceCarrierPrivilege(context, subId, uid, "readCallLog");
return true;
}
return false;
@@ -519,10 +453,11 @@
* default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers.
*/
public static boolean checkCallingOrSelfReadPhoneNumber(
- Context context, int subId, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message) {
return checkReadPhoneNumber(
- context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(),
- callingPackage, message);
+ context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
+ callingPackage, callingFeatureId, message);
}
/**
@@ -533,8 +468,8 @@
*/
@VisibleForTesting
public static boolean checkReadPhoneNumber(
- Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage, String message) {
+ Context context, int subId, int pid, int uid,
+ String callingPackage, @Nullable String callingFeatureId, String message) {
// Default SMS app can always read it.
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
if (appOps.noteOp(AppOpsManager.OPSTR_WRITE_SMS, uid, callingPackage) ==
@@ -548,7 +483,8 @@
// First, check if we can read the phone state.
try {
return checkReadPhoneState(
- context, telephonySupplier, subId, pid, uid, callingPackage, message);
+ context, subId, pid, uid, callingPackage, callingFeatureId,
+ message);
} catch (SecurityException readPhoneStateSecurityException) {
}
// Can be read with READ_SMS too.
@@ -588,8 +524,8 @@
return;
}
- if (DBG) Rlog.d(LOG_TAG, "No modify permission, check carrier privilege next.");
- enforceCallingOrSelfCarrierPrivilege(subId, message);
+ if (DBG) Log.d(LOG_TAG, "No modify permission, check carrier privilege next.");
+ enforceCallingOrSelfCarrierPrivilege(context, subId, message);
}
/**
@@ -606,10 +542,10 @@
}
if (DBG) {
- Rlog.d(LOG_TAG, "No READ_PHONE_STATE permission, check carrier privilege next.");
+ Log.d(LOG_TAG, "No READ_PHONE_STATE permission, check carrier privilege next.");
}
- enforceCallingOrSelfCarrierPrivilege(subId, message);
+ enforceCallingOrSelfCarrierPrivilege(context, subId, message);
}
/**
@@ -626,11 +562,38 @@
}
if (DBG) {
- Rlog.d(LOG_TAG, "No READ_PRIVILEDED_PHONE_STATE permission, "
+ Log.d(LOG_TAG, "No READ_PRIVILEGED_PHONE_STATE permission, "
+ "check carrier privilege next.");
}
- enforceCallingOrSelfCarrierPrivilege(subId, message);
+ enforceCallingOrSelfCarrierPrivilege(context, subId, message);
+ }
+
+ /**
+ * Ensure the caller (or self, if not processing an IPC) has
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
+ * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or carrier privileges.
+ *
+ * @throws SecurityException if the caller does not have the required permission/privileges
+ */
+ public static void enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ Context context, int subId, String message) {
+ if (context.checkCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ == PERMISSION_GRANTED) {
+ return;
+ }
+
+ if (context.checkCallingOrSelfPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+ == PERMISSION_GRANTED) {
+ return;
+ }
+
+ if (DBG) {
+ Log.d(LOG_TAG, "No READ_PRIVILEGED_PHONE_STATE nor READ_PRECISE_PHONE_STATE permission"
+ + ", check carrier privilege next.");
+ }
+
+ enforceCallingOrSelfCarrierPrivilege(context, subId, message);
}
/**
@@ -638,35 +601,31 @@
*
* @throws SecurityException if the caller does not have the required privileges
*/
- public static void enforceCallingOrSelfCarrierPrivilege(int subId, String message) {
+ public static void enforceCallingOrSelfCarrierPrivilege(
+ Context context, int subId, String message) {
// NOTE: It's critical that we explicitly pass the calling UID here rather than call
// TelephonyManager#hasCarrierPrivileges directly, as the latter only works when called from
// the phone process. When called from another process, it will check whether that process
// has carrier privileges instead.
- enforceCarrierPrivilege(subId, Binder.getCallingUid(), message);
- }
-
- private static void enforceCarrierPrivilege(int subId, int uid, String message) {
- enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message);
+ enforceCarrierPrivilege(context, subId, Binder.getCallingUid(), message);
}
private static void enforceCarrierPrivilege(
- Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) {
- if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid)
+ Context context, int subId, int uid, String message) {
+ if (getCarrierPrivilegeStatus(context, subId, uid)
!= TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
- if (DBG) Rlog.e(LOG_TAG, "No Carrier Privilege.");
+ if (DBG) Log.e(LOG_TAG, "No Carrier Privilege.");
throw new SecurityException(message);
}
}
/** Returns whether the provided uid has carrier privileges for any active subscription ID. */
- private static boolean checkCarrierPrivilegeForAnySubId(
- Context context, Supplier<ITelephony> telephonySupplier, int uid) {
+ private static boolean checkCarrierPrivilegeForAnySubId(Context context, int uid) {
SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
int[] activeSubIds = sm.getActiveSubscriptionIdList(/* visibleOnly */ false);
for (int activeSubId : activeSubIds) {
- if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
+ if (getCarrierPrivilegeStatus(context, activeSubId, uid)
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
return true;
}
@@ -674,18 +633,15 @@
return false;
}
- private static int getCarrierPrivilegeStatus(
- Supplier<ITelephony> telephonySupplier, int subId, int uid) {
- ITelephony telephony = telephonySupplier.get();
+ private static int getCarrierPrivilegeStatus(Context context, int subId, int uid) {
+ final long identity = Binder.clearCallingIdentity();
try {
- if (telephony != null) {
- return telephony.getCarrierPrivilegeStatusForUid(subId, uid);
- }
- } catch (RemoteException e) {
- // Fallback below.
+ TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ return telephonyManager.createForSubscriptionId(subId).getCarrierPrivilegeStatus(uid);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
- Rlog.e(LOG_TAG, "Phone process is down, cannot check carrier privileges");
- return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
}
/**
diff --git a/telephony/java/com/android/internal/telephony/util/ArrayUtils.java b/telephony/common/com/android/internal/telephony/util/ArrayUtils.java
similarity index 86%
rename from telephony/java/com/android/internal/telephony/util/ArrayUtils.java
rename to telephony/common/com/android/internal/telephony/util/ArrayUtils.java
index 2905125..28401a6 100644
--- a/telephony/java/com/android/internal/telephony/util/ArrayUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/ArrayUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -29,17 +29,30 @@
/**
* Adds value to given array if not already present, providing set-like behavior.
+ *
+ * @param kind The class of the array elements.
+ * @param array The array to append to.
+ * @param element The array element to append.
+ * @return The array containing the appended element.
*/
@SuppressWarnings("unchecked")
- public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
+ @NonNull
+ public static <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
return appendElement(kind, array, element, false);
}
/**
* Adds value to given array.
+ *
+ * @param kind The class of the array elements.
+ * @param array The array to append to.
+ * @param element The array element to append.
+ * @param allowDuplicates Whether to allow duplicated elements in array.
+ * @return The array containing the appended element.
*/
@SuppressWarnings("unchecked")
- public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element,
+ @NonNull
+ public static <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element,
boolean allowDuplicates) {
final T[] result;
final int end;
@@ -59,13 +72,14 @@
/**
* Combine multiple arrays into a single array.
*
- * @param kind The class of the array elements
+ * @param kind The class of the array elements
* @param arrays The arrays to combine
- * @param <T> The class of the array elements (inferred from kind).
+ * @param <T> The class of the array elements (inferred from kind).
* @return A single array containing all the elements of the parameter arrays.
*/
@SuppressWarnings("unchecked")
- public static @NonNull <T> T[] concatElements(Class<T> kind, @Nullable T[]... arrays) {
+ @NonNull
+ public static <T> T[] concatElements(Class<T> kind, @Nullable T[]... arrays) {
if (arrays == null || arrays.length == 0) {
return createEmptyArray(kind);
}
diff --git a/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
similarity index 100%
rename from telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
rename to telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
diff --git a/telephony/common/com/google/android/mms/ContentType.java b/telephony/common/com/google/android/mms/ContentType.java
index 12e4b7e..4a971dd 100644
--- a/telephony/common/com/google/android/mms/ContentType.java
+++ b/telephony/common/com/google/android/mms/ContentType.java
@@ -17,7 +17,7 @@
package com.google.android.mms;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.ArrayList;
diff --git a/telephony/common/com/google/android/mms/InvalidHeaderValueException.java b/telephony/common/com/google/android/mms/InvalidHeaderValueException.java
index 2836c30..55087ff 100644
--- a/telephony/common/com/google/android/mms/InvalidHeaderValueException.java
+++ b/telephony/common/com/google/android/mms/InvalidHeaderValueException.java
@@ -17,7 +17,7 @@
package com.google.android.mms;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Thrown when an invalid header value was set.
diff --git a/telephony/common/com/google/android/mms/MmsException.java b/telephony/common/com/google/android/mms/MmsException.java
index 5be33ed..24bceb3 100644
--- a/telephony/common/com/google/android/mms/MmsException.java
+++ b/telephony/common/com/google/android/mms/MmsException.java
@@ -17,7 +17,7 @@
package com.google.android.mms;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* A generic exception that is thrown by the Mms client.
diff --git a/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java b/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java
index ae447d7..8693385 100644
--- a/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java
+++ b/telephony/common/com/google/android/mms/pdu/AcknowledgeInd.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/Base64.java b/telephony/common/com/google/android/mms/pdu/Base64.java
index 483fa7f..0d6a46a 100644
--- a/telephony/common/com/google/android/mms/pdu/Base64.java
+++ b/telephony/common/com/google/android/mms/pdu/Base64.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
public class Base64 {
/**
diff --git a/telephony/common/com/google/android/mms/pdu/CharacterSets.java b/telephony/common/com/google/android/mms/pdu/CharacterSets.java
index 27da35e..5172b7b 100644
--- a/telephony/common/com/google/android/mms/pdu/CharacterSets.java
+++ b/telephony/common/com/google/android/mms/pdu/CharacterSets.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
diff --git a/telephony/common/com/google/android/mms/pdu/DeliveryInd.java b/telephony/common/com/google/android/mms/pdu/DeliveryInd.java
index 7093ac6..8fb6a75 100644
--- a/telephony/common/com/google/android/mms/pdu/DeliveryInd.java
+++ b/telephony/common/com/google/android/mms/pdu/DeliveryInd.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java b/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java
index 4166275..8c0380f 100644
--- a/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java
+++ b/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java
@@ -17,10 +17,9 @@
package com.google.android.mms.pdu;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
diff --git a/telephony/common/com/google/android/mms/pdu/GenericPdu.java b/telephony/common/com/google/android/mms/pdu/GenericPdu.java
index ebf16ac..320b13f 100644
--- a/telephony/common/com/google/android/mms/pdu/GenericPdu.java
+++ b/telephony/common/com/google/android/mms/pdu/GenericPdu.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java b/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java
index e108f76..42a89c6 100644
--- a/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java
+++ b/telephony/common/com/google/android/mms/pdu/MultimediaMessagePdu.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/NotificationInd.java b/telephony/common/com/google/android/mms/pdu/NotificationInd.java
index b561bd4..ca4615c 100644
--- a/telephony/common/com/google/android/mms/pdu/NotificationInd.java
+++ b/telephony/common/com/google/android/mms/pdu/NotificationInd.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java b/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java
index 3c70f86..ebd81af 100644
--- a/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java
+++ b/telephony/common/com/google/android/mms/pdu/NotifyRespInd.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/PduBody.java b/telephony/common/com/google/android/mms/pdu/PduBody.java
index 51914e4..f7f285f 100644
--- a/telephony/common/com/google/android/mms/pdu/PduBody.java
+++ b/telephony/common/com/google/android/mms/pdu/PduBody.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.HashMap;
import java.util.Map;
diff --git a/telephony/common/com/google/android/mms/pdu/PduComposer.java b/telephony/common/com/google/android/mms/pdu/PduComposer.java
index e24bf21..b8b212c 100644
--- a/telephony/common/com/google/android/mms/pdu/PduComposer.java
+++ b/telephony/common/com/google/android/mms/pdu/PduComposer.java
@@ -17,12 +17,11 @@
package com.google.android.mms.pdu;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.text.TextUtils;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
diff --git a/telephony/common/com/google/android/mms/pdu/PduContentTypes.java b/telephony/common/com/google/android/mms/pdu/PduContentTypes.java
index 8551b2f..57141fe 100644
--- a/telephony/common/com/google/android/mms/pdu/PduContentTypes.java
+++ b/telephony/common/com/google/android/mms/pdu/PduContentTypes.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
public class PduContentTypes {
/**
diff --git a/telephony/common/com/google/android/mms/pdu/PduHeaders.java b/telephony/common/com/google/android/mms/pdu/PduHeaders.java
index b524464..3e62184 100644
--- a/telephony/common/com/google/android/mms/pdu/PduHeaders.java
+++ b/telephony/common/com/google/android/mms/pdu/PduHeaders.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/PduParser.java b/telephony/common/com/google/android/mms/pdu/PduParser.java
index f483994..5340245 100755
--- a/telephony/common/com/google/android/mms/pdu/PduParser.java
+++ b/telephony/common/com/google/android/mms/pdu/PduParser.java
@@ -17,10 +17,9 @@
package com.google.android.mms.pdu;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import com.google.android.mms.ContentType;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/PduPart.java b/telephony/common/com/google/android/mms/pdu/PduPart.java
index 09b7751..8dd976b 100644
--- a/telephony/common/com/google/android/mms/pdu/PduPart.java
+++ b/telephony/common/com/google/android/mms/pdu/PduPart.java
@@ -17,10 +17,9 @@
package com.google.android.mms.pdu;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.util.HashMap;
import java.util.Map;
diff --git a/telephony/common/com/google/android/mms/pdu/PduPersister.java b/telephony/common/com/google/android/mms/pdu/PduPersister.java
index b237705..fcd5b8f 100755
--- a/telephony/common/com/google/android/mms/pdu/PduPersister.java
+++ b/telephony/common/com/google/android/mms/pdu/PduPersister.java
@@ -17,6 +17,7 @@
package com.google.android.mms.pdu;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -34,13 +35,12 @@
import android.provider.Telephony.MmsSms.PendingMessages;
import android.provider.Telephony.Threads;
import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import com.google.android.mms.ContentType;
import com.google.android.mms.InvalidHeaderValueException;
import com.google.android.mms.MmsException;
@@ -1448,9 +1448,9 @@
final Set<String> myPhoneNumbers = new HashSet<String>();
if (excludeMyNumber) {
// Build a list of my phone numbers from the various sims.
- for (int subid : subscriptionManager.getActiveSubscriptionIdList()) {
+ for (SubscriptionInfo subInfo : subscriptionManager.getActiveSubscriptionInfoList()) {
final String myNumber = mContext.getSystemService(TelephonyManager.class).
- createForSubscriptionId(subid).getLine1Number();
+ createForSubscriptionId(subInfo.getSubscriptionId()).getLine1Number();
if (myNumber != null) {
myPhoneNumbers.add(myNumber);
}
diff --git a/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java b/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java
index 9d6535c..4e1d7f5 100644
--- a/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java
+++ b/telephony/common/com/google/android/mms/pdu/QuotedPrintable.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.ByteArrayOutputStream;
diff --git a/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java b/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java
index e38c62d..4ba3c71 100644
--- a/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java
+++ b/telephony/common/com/google/android/mms/pdu/ReadOrigInd.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/ReadRecInd.java b/telephony/common/com/google/android/mms/pdu/ReadRecInd.java
index 9696bc2..37ccfb9 100644
--- a/telephony/common/com/google/android/mms/pdu/ReadRecInd.java
+++ b/telephony/common/com/google/android/mms/pdu/ReadRecInd.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/RetrieveConf.java b/telephony/common/com/google/android/mms/pdu/RetrieveConf.java
index 03755af..260adfc 100644
--- a/telephony/common/com/google/android/mms/pdu/RetrieveConf.java
+++ b/telephony/common/com/google/android/mms/pdu/RetrieveConf.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/SendConf.java b/telephony/common/com/google/android/mms/pdu/SendConf.java
index b859827..7799238 100644
--- a/telephony/common/com/google/android/mms/pdu/SendConf.java
+++ b/telephony/common/com/google/android/mms/pdu/SendConf.java
@@ -17,7 +17,7 @@
package com.google.android.mms.pdu;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.InvalidHeaderValueException;
diff --git a/telephony/common/com/google/android/mms/pdu/SendReq.java b/telephony/common/com/google/android/mms/pdu/SendReq.java
index c1b7f93..6e2f2da 100644
--- a/telephony/common/com/google/android/mms/pdu/SendReq.java
+++ b/telephony/common/com/google/android/mms/pdu/SendReq.java
@@ -17,10 +17,9 @@
package com.google.android.mms.pdu;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import com.google.android.mms.InvalidHeaderValueException;
public class SendReq extends MultimediaMessagePdu {
diff --git a/telephony/common/com/google/android/mms/util/AbstractCache.java b/telephony/common/com/google/android/mms/util/AbstractCache.java
index ab5d48a..25862e7 100644
--- a/telephony/common/com/google/android/mms/util/AbstractCache.java
+++ b/telephony/common/com/google/android/mms/util/AbstractCache.java
@@ -17,10 +17,9 @@
package com.google.android.mms.util;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.util.HashMap;
public abstract class AbstractCache<K, V> {
diff --git a/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java b/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java
index 118de46..0f9390d 100644
--- a/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java
+++ b/telephony/common/com/google/android/mms/util/DownloadDrmHelper.java
@@ -17,12 +17,11 @@
package com.google.android.mms.util;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.drm.DrmManagerClient;
import android.util.Log;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
public class DownloadDrmHelper {
private static final String TAG = "DownloadDrmHelper";
diff --git a/telephony/common/com/google/android/mms/util/DrmConvertSession.java b/telephony/common/com/google/android/mms/util/DrmConvertSession.java
index 0e8ec91..156c7ad 100644
--- a/telephony/common/com/google/android/mms/util/DrmConvertSession.java
+++ b/telephony/common/com/google/android/mms/util/DrmConvertSession.java
@@ -16,14 +16,13 @@
*/
package com.google.android.mms.util;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.drm.DrmConvertedStatus;
import android.drm.DrmManagerClient;
import android.provider.Downloads;
import android.util.Log;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
diff --git a/telephony/common/com/google/android/mms/util/PduCache.java b/telephony/common/com/google/android/mms/util/PduCache.java
index 94e3894..c380d6b 100644
--- a/telephony/common/com/google/android/mms/util/PduCache.java
+++ b/telephony/common/com/google/android/mms/util/PduCache.java
@@ -17,14 +17,13 @@
package com.google.android.mms.util;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentUris;
import android.content.UriMatcher;
import android.net.Uri;
import android.provider.Telephony.Mms;
import android.util.Log;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.util.HashMap;
import java.util.HashSet;
diff --git a/telephony/common/com/google/android/mms/util/PduCacheEntry.java b/telephony/common/com/google/android/mms/util/PduCacheEntry.java
index 1ecd1bf..a4a25d2 100644
--- a/telephony/common/com/google/android/mms/util/PduCacheEntry.java
+++ b/telephony/common/com/google/android/mms/util/PduCacheEntry.java
@@ -17,7 +17,7 @@
package com.google.android.mms.util;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.google.android.mms.pdu.GenericPdu;
diff --git a/telephony/common/com/google/android/mms/util/SqliteWrapper.java b/telephony/common/com/google/android/mms/util/SqliteWrapper.java
index 2dd1dc1..31fe4d7 100644
--- a/telephony/common/com/google/android/mms/util/SqliteWrapper.java
+++ b/telephony/common/com/google/android/mms/util/SqliteWrapper.java
@@ -18,6 +18,7 @@
package com.google.android.mms.util;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -27,8 +28,6 @@
import android.util.Log;
import android.widget.Toast;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
public final class SqliteWrapper {
private static final String TAG = "SqliteWrapper";
private static final String SQLITE_EXCEPTION_DETAIL_MESSAGE
diff --git a/telephony/java/android/service/carrier/CarrierIdentifier.java b/telephony/java/android/service/carrier/CarrierIdentifier.java
index af5bf74..7957c25 100644
--- a/telephony/java/android/service/carrier/CarrierIdentifier.java
+++ b/telephony/java/android/service/carrier/CarrierIdentifier.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.telephony.TelephonyManager;
import com.android.internal.telephony.uicc.IccUtils;
diff --git a/telephony/java/android/service/euicc/EuiccProfileInfo.java b/telephony/java/android/service/euicc/EuiccProfileInfo.java
index 6c357cc..8450a90 100644
--- a/telephony/java/android/service/euicc/EuiccProfileInfo.java
+++ b/telephony/java/android/service/euicc/EuiccProfileInfo.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.service.carrier.CarrierIdentifier;
diff --git a/telephony/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java b/telephony/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
index c7a9851..2382f65 100644
--- a/telephony/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
+++ b/telephony/java/android/service/euicc/GetDefaultDownloadableSubscriptionListResult.java
@@ -17,7 +17,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.euicc.DownloadableSubscription;
diff --git a/telephony/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java b/telephony/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
index abd4065..d0fb511 100644
--- a/telephony/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
+++ b/telephony/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
@@ -17,7 +17,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.euicc.DownloadableSubscription;
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index bb28df2..d325cd8 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -50,18 +50,12 @@
/**
* Transport type for Wireless Wide Area Networks (i.e. Cellular)
- * @hide
*/
- @SystemApi
- @TestApi
public static final int TRANSPORT_TYPE_WWAN = 1;
/**
* Transport type for Wireless Local Area Networks (i.e. Wifi)
- * @hide
*/
- @SystemApi
- @TestApi
public static final int TRANSPORT_TYPE_WLAN = 2;
/** @hide */
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 7482ecc..9e6dfef 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -596,4 +596,17 @@
@Retention(RetentionPolicy.SOURCE)
public @interface ImsAudioCodec {
}
+
+ /**
+ * UICC SIM Application Types
+ */
+ @IntDef(prefix = { "APPTYPE_" }, value = {
+ TelephonyManager.APPTYPE_SIM,
+ TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.APPTYPE_RUIM,
+ TelephonyManager.APPTYPE_CSIM,
+ TelephonyManager.APPTYPE_ISIM
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UiccAppType{}
}
diff --git a/telephony/java/android/telephony/AnomalyReporter.java b/telephony/java/android/telephony/AnomalyReporter.java
index 9753d8b..097041f 100644
--- a/telephony/java/android/telephony/AnomalyReporter.java
+++ b/telephony/java/android/telephony/AnomalyReporter.java
@@ -16,6 +16,8 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.content.Context;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7799442..71aaa6e 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -24,7 +24,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.os.PersistableBundle;
@@ -35,6 +35,7 @@
import android.telephony.ims.ImsReasonInfo;
import com.android.internal.telephony.ICarrierConfigLoader;
+import com.android.telephony.Rlog;
/**
* Provides access to telephony configuration values that are carrier-specific.
@@ -299,7 +300,6 @@
/**
* A string array containing numbers that shouldn't be included in the call log.
- * @hide
*/
public static final String KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY =
"unloggable_numbers_string_array";
@@ -312,12 +312,11 @@
KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
/**
- * Do only allow auto selection in Advanced Network Settings when in home network.
+ * Only allow auto selection in Advanced Network Settings when in home network.
* Manual selection is allowed when in roaming network.
- * @hide
*/
- public static final String
- KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL = "only_auto_select_in_home_network";
+ public static final String KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL =
+ "only_auto_select_in_home_network";
/**
* Control whether users receive a simplified network settings UI and improved network
@@ -581,9 +580,6 @@
* registration state to change. That is, turning on or off mobile data will not cause VT to be
* enabled or disabled.
* When {@code false}, disabling mobile data will cause VT to be de-registered.
- * <p>
- * See also {@link #KEY_VILTE_DATA_IS_METERED_BOOL}.
- * @hide
*/
public static final String KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS =
"ignore_data_enabled_changed_for_video_calls";
@@ -647,7 +643,6 @@
/**
* Default WFC_IMS_enabled: true VoWiFi by default is on
* false VoWiFi by default is off
- * @hide
*/
public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL =
"carrier_default_wfc_ims_enabled_bool";
@@ -671,6 +666,12 @@
"carrier_promote_wfc_on_call_fail_bool";
/**
+ * Flag specifying whether provisioning is required for RCS.
+ */
+ public static final String KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL =
+ "carrier_rcs_provisioning_required_bool";
+
+ /**
* Flag specifying whether provisioning is required for VoLTE, Video Telephony, and WiFi
* Calling.
*/
@@ -713,9 +714,7 @@
*
* As of now, Verizon is the only carrier enforcing this dependency in their
* WFC awareness and activation requirements.
- *
- * @hide
- * */
+ */
public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL
= "carrier_volte_override_wfc_provisioning_bool";
@@ -847,9 +846,12 @@
"carrier_force_disable_etws_cmas_test_bool";
/**
- * The default flag specifying whether "Turn on Notifications" option will be always shown in
- * Settings->More->Emergency broadcasts menu regardless developer options is turned on or not.
+ * The default flag specifying whether "Allow alerts" option will be always shown in
+ * emergency alerts settings regardless developer options is turned on or not.
+ *
+ * @deprecated The allow alerts option is always shown now. No longer need a config for that.
*/
+ @Deprecated
public static final String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL =
"always_show_emergency_alert_onoff_bool";
@@ -1073,10 +1075,6 @@
*
* When {@code false}, the old behavior is used, where the toggle in accessibility settings is
* used to set the IMS stack's RTT enabled state.
- *
- * @deprecated -- this flag no longer does anything. Remove once the new behavior is verified.
- *
- * @hide
*/
public static final String KEY_IGNORE_RTT_MODE_SETTING_BOOL =
"ignore_rtt_mode_setting_bool";
@@ -1125,7 +1123,6 @@
* Determines whether the IMS conference merge process supports and returns its participants
* data. When {@code true}, on merge complete, conference call would have a list of its
* participants returned in XML format, {@code false otherwise}.
- * @hide
*/
public static final String KEY_SUPPORT_IMS_CONFERENCE_EVENT_PACKAGE_BOOL =
"support_ims_conference_event_package_bool";
@@ -1198,20 +1195,18 @@
public static final String KEY_ENABLE_APPS_STRING_ARRAY = "enable_apps_string_array";
/**
- * Determine whether user can switch Wi-Fi preferred or Cellular preferred in calling preference.
+ * Determine whether user can switch Wi-Fi preferred or Cellular preferred
+ * in calling preference.
* Some operators support Wi-Fi Calling only, not VoLTE.
* They don't need "Cellular preferred" option.
- * In this case, set uneditalbe attribute for preferred preference.
- * @hide
+ * In this case, set uneditable attribute for preferred preference.
*/
public static final String KEY_EDITABLE_WFC_MODE_BOOL = "editable_wfc_mode_bool";
- /**
- * Flag to indicate if Wi-Fi needs to be disabled in ECBM
- * @hide
- **/
- public static final String
- KEY_CONFIG_WIFI_DISABLE_IN_ECBM = "config_wifi_disable_in_ecbm";
+ /**
+ * Flag to indicate if Wi-Fi needs to be disabled in ECBM.
+ */
+ public static final String KEY_CONFIG_WIFI_DISABLE_IN_ECBM = "config_wifi_disable_in_ecbm";
/**
* List operator-specific error codes and indices of corresponding error strings in
@@ -1275,9 +1270,8 @@
public static final String KEY_WFC_SPN_USE_ROOT_LOCALE = "wfc_spn_use_root_locale";
/**
- * The Component Name of the activity that can setup the emergency addrees for WiFi Calling
+ * The Component Name of the activity that can setup the emergency address for WiFi Calling
* as per carrier requirement.
- * @hide
*/
public static final String KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING =
"wfc_emergency_address_carrier_app_string";
@@ -1441,22 +1435,19 @@
public static final String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
/**
- * APN types that user is not allowed to modify
- * @hide
+ * APN types that user is not allowed to modify.
*/
public static final String KEY_READ_ONLY_APN_TYPES_STRING_ARRAY =
"read_only_apn_types_string_array";
/**
- * APN fields that user is not allowed to modify
- * @hide
+ * APN fields that user is not allowed to modify.
*/
public static final String KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY =
"read_only_apn_fields_string_array";
/**
* Default value of APN types field if not specified by user when adding/modifying an APN.
- * @hide
*/
public static final String KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY =
"apn_settings_default_apn_types_string_array";
@@ -1487,29 +1478,25 @@
"hide_digits_helper_text_on_stk_input_screen_bool";
/**
- * Boolean indicating if show data RAT icon on status bar even when data is disabled
- * @hide
+ * Boolean indicating if show data RAT icon on status bar even when data is disabled.
*/
public static final String KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL =
"always_show_data_rat_icon_bool";
/**
- * Boolean indicating if default data account should show LTE or 4G icon
- * @hide
+ * Boolean indicating if default data account should show LTE or 4G icon.
*/
public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL =
"show_4g_for_lte_data_icon_bool";
/**
* Boolean indicating if default data account should show 4G icon when in 3G.
- * @hide
*/
public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL =
"show_4g_for_3g_data_icon_bool";
/**
- * Boolean indicating if lte+ icon should be shown if available
- * @hide
+ * Boolean indicating if LTE+ icon should be shown if available.
*/
public static final String KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL =
"hide_lte_plus_data_icon_bool";
@@ -1524,10 +1511,8 @@
"operator_name_filter_pattern_string";
/**
- * The string is used to compare with operator name. If it matches the pattern then show
- * specific data icon.
- *
- * @hide
+ * The string is used to compare with operator name.
+ * If it matches the pattern then show specific data icon.
*/
public static final String KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING =
"show_carrier_data_icon_pattern_string";
@@ -1540,33 +1525,28 @@
"show_precise_failed_cause_bool";
/**
- * Boolean to decide whether lte is enabled.
- * @hide
+ * Boolean to decide whether LTE is enabled.
*/
public static final String KEY_LTE_ENABLED_BOOL = "lte_enabled_bool";
/**
* Boolean to decide whether TD-SCDMA is supported.
- * @hide
*/
public static final String KEY_SUPPORT_TDSCDMA_BOOL = "support_tdscdma_bool";
/**
* A list of mcc/mnc that support TD-SCDMA for device when connect to the roaming network.
- * @hide
*/
public static final String KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY =
"support_tdscdma_roaming_networks_string_array";
/**
* Boolean to decide whether world mode is enabled.
- * @hide
*/
public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
/**
* Flatten {@link android.content.ComponentName} of the carrier's settings activity.
- * @hide
*/
public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING =
"carrier_settings_activity_component_name_string";
@@ -1604,7 +1584,10 @@
public static final String KEY_MMS_UA_PROF_TAG_NAME_STRING = "uaProfTagName";
public static final String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
public static final String KEY_MMS_USER_AGENT_STRING = "userAgent";
- /** @hide */
+ /**
+ * If true, add "Connection: close" header to MMS HTTP requests so the connection
+ * is immediately closed (disabling keep-alive).
+ */
public static final String KEY_MMS_CLOSE_CONNECTION_BOOL = "mmsCloseConnection";
/**
@@ -1620,25 +1603,23 @@
/**
* Defines carrier-specific actions which act upon
* com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED, used for customization of the
- * default carrier app
+ * default carrier app.
* Format: "CARRIER_ACTION_IDX, ..."
* Where {@code CARRIER_ACTION_IDX} is an integer defined in
- * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * com.android.carrierdefaultapp.CarrierActionUtils
* Example:
- * {@link com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_DISABLE_METERED_APNS
- * disable_metered_apns}
- * @hide
+ * com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_DISABLE_METERED_APNS
+ * disables metered APNs
*/
- @UnsupportedAppUsage
+ @SuppressLint("IntentName")
public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY =
"carrier_default_actions_on_redirection_string_array";
/**
- * Defines carrier-specific actions which act upon
- * com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
+ * Defines carrier-specific actions which act upon CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
* and configured signal args:
- * {@link com.android.internal.telephony.TelephonyIntents#EXTRA_APN_TYPE_KEY apnType},
- * {@link com.android.internal.telephony.TelephonyIntents#EXTRA_ERROR_CODE_KEY errorCode}
+ * android.telephony.TelephonyManager#EXTRA_APN_TYPE,
+ * android.telephony.TelephonyManager#EXTRA_ERROR_CODE
* used for customization of the default carrier app
* Format:
* {
@@ -1646,42 +1627,41 @@
* "APN_1, ERROR_CODE_2 : CARRIER_ACTION_IDX_1 "
* }
* Where {@code APN_1} is a string defined in
- * {@link com.android.internal.telephony.PhoneConstants PhoneConstants}
+ * com.android.internal.telephony.PhoneConstants
* Example: "default"
*
- * {@code ERROR_CODE_1} is an integer defined in
- * {@link DataFailCause DcFailure}
+ * {@code ERROR_CODE_1} is an integer defined in android.telephony.DataFailCause
* Example:
- * {@link DataFailCause#MISSING_UNKNOWN_APN}
+ * android.telephony.DataFailCause#MISSING_UNKNOWN_APN
*
* {@code CARRIER_ACTION_IDX_1} is an integer defined in
- * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * com.android.carrierdefaultapp.CarrierActionUtils
* Example:
- * {@link com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_DISABLE_METERED_APNS}
- * @hide
+ * com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_DISABLE_METERED_APNS
+ * disables metered APNs
*/
+ @SuppressLint("IntentName")
public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DCFAILURE_STRING_ARRAY =
"carrier_default_actions_on_dcfailure_string_array";
/**
- * Defines carrier-specific actions which act upon
- * com.android.internal.telephony.CARRIER_SIGNAL_RESET, used for customization of the
- * default carrier app
+ * Defines carrier-specific actions which act upon CARRIER_SIGNAL_RESET,
+ * used for customization of the default carrier app.
* Format: "CARRIER_ACTION_IDX, ..."
* Where {@code CARRIER_ACTION_IDX} is an integer defined in
- * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * com.android.carrierdefaultapp.CarrierActionUtils
* Example:
- * {@link com.android.carrierdefaultapp.CarrierActionUtils
- * #CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS clear all notifications on reset}
- * @hide
+ * com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS
+ * clears all notifications on reset
*/
+ @SuppressLint("IntentName")
public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET =
"carrier_default_actions_on_reset_string_array";
/**
* Defines carrier-specific actions which act upon
* com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE,
- * used for customization of the default carrier app
+ * used for customization of the default carrier app.
* Format:
* {
* "true : CARRIER_ACTION_IDX_1",
@@ -1689,17 +1669,17 @@
* }
* Where {@code true} is a boolean indicates default network available/unavailable
* Where {@code CARRIER_ACTION_IDX} is an integer defined in
- * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils
* Example:
- * {@link com.android.carrierdefaultapp.CarrierActionUtils
- * #CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER enable the app as the default URL handler}
- * @hide
+ * com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER
+ * enables the app as the default URL handler
*/
+ @SuppressLint("IntentName")
public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE =
"carrier_default_actions_on_default_network_available_string_array";
+
/**
- * Defines a list of acceptable redirection url for default carrier app
- * @hides
+ * Defines a list of acceptable redirection url for default carrier app.
*/
public static final String KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY =
"carrier_default_redirection_url_string_array";
@@ -1827,10 +1807,10 @@
/**
* Determines whether to enable enhanced call blocking feature on the device.
- * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED
- * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_PRIVATE
- * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_PAYPHONE
- * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNKNOWN
+ * android.provider.BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED
+ * android.provider.BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_PRIVATE
+ * android.provider.BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_PAYPHONE
+ * android.provider.BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNKNOWN
*
* <p>
* 1. For Single SIM(SS) device, it can be customized in both carrier_config_mccmnc.xml
@@ -1840,7 +1820,6 @@
* function is used regardless of SIM.
* <p>
* If {@code true} enable enhanced call blocking feature on the device, {@code false} otherwise.
- * @hide
*/
public static final String KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL =
"support_enhanced_call_blocking_bool";
@@ -1943,7 +1922,6 @@
/**
* Flag indicating whether the carrier supports call deflection for an incoming IMS call.
- * @hide
*/
public static final String KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL =
"carrier_allow_deflect_ims_call_bool";
@@ -2008,8 +1986,6 @@
/**
* Whether system apps are allowed to use fallback if carrier video call is not available.
* Defaults to {@code true}.
- *
- * @hide
*/
public static final String KEY_ALLOW_VIDEO_CALLING_FALLBACK_BOOL =
"allow_video_calling_fallback_bool";
@@ -2047,9 +2023,8 @@
"enhanced_4g_lte_title_variant_bool";
/**
- * The index indicates the carrier specified title string of Enahnce 4G LTE Mode settings.
+ * The index indicates the carrier specified title string of Enhanced 4G LTE Mode settings.
* Default value is 0, which indicates the default title string.
- * @hide
*/
public static final String KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT =
"enhanced_4g_lte_title_variant_int";
@@ -2093,15 +2068,13 @@
* {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is false. If
* {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is true, this
* configuration is ignored and roaming preference cannot be changed.
- * @hide
*/
public static final String KEY_EDITABLE_WFC_ROAMING_MODE_BOOL =
"editable_wfc_roaming_mode_bool";
/**
- * Flag specifying wether to show blocking pay phone option in blocked numbers screen. Only show
- * the option if payphone call presentation represents in the carrier's region.
- * @hide
+ * Flag specifying whether to show blocking pay phone option in blocked numbers screen.
+ * Only show the option if payphone call presentation is present in the carrier's region.
*/
public static final java.lang.String KEY_SHOW_BLOCKING_PAY_PHONE_OPTION_BOOL =
"show_blocking_pay_phone_option_bool";
@@ -2111,7 +2084,6 @@
* {@code false} - roaming preference can be selected separately from the home preference.
* {@code true} - roaming preference is the same as home preference and
* {@link #KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT} is used as the default value.
- * @hide
*/
public static final String KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL =
"use_wfc_home_network_mode_in_roaming_network_bool";
@@ -2145,7 +2117,6 @@
* while the device is registered over WFC. Default value is -1, which indicates
* that this notification is not pertinent for a particular carrier. We've added a delay
* to prevent false positives.
- * @hide
*/
public static final String KEY_EMERGENCY_NOTIFICATION_DELAY_INT =
"emergency_notification_delay_int";
@@ -2196,7 +2167,6 @@
/**
* Flag specifying whether to show an alert dialog for video call charges.
* By default this value is {@code false}.
- * @hide
*/
public static final String KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL =
"show_video_call_charges_alert_dialog_bool";
@@ -2483,10 +2453,9 @@
/**
* Identifies if the key is available for WLAN or EPDG or both. The value is a bitmask.
* 0 indicates that neither EPDG or WLAN is enabled.
- * 1 indicates that key type {@link TelephonyManager#KEY_TYPE_EPDG} is enabled.
- * 2 indicates that key type {@link TelephonyManager#KEY_TYPE_WLAN} is enabled.
+ * 1 indicates that key type TelephonyManager#KEY_TYPE_EPDG is enabled.
+ * 2 indicates that key type TelephonyManager#KEY_TYPE_WLAN is enabled.
* 3 indicates that both are enabled.
- * @hide
*/
public static final String IMSI_KEY_AVAILABILITY_INT = "imsi_key_availability_int";
@@ -2505,7 +2474,6 @@
/**
* Flag specifying whether IMS registration state menu is shown in Status Info setting,
* default to false.
- * @hide
*/
public static final String KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL =
"show_ims_registration_status_bool";
@@ -2561,7 +2529,6 @@
/**
* The flag to disable the popup dialog which warns the user of data charges.
- * @hide
*/
public static final String KEY_DISABLE_CHARGE_INDICATION_BOOL =
"disable_charge_indication_bool";
@@ -2626,15 +2593,13 @@
/**
* Determines whether any carrier has been identified and its specific config has been applied,
* default to false.
- * @hide
*/
public static final String KEY_CARRIER_CONFIG_APPLIED_BOOL = "carrier_config_applied_bool";
/**
* Determines whether we should show a warning asking the user to check with their carrier
- * on pricing when the user enabled data roaming.
+ * on pricing when the user enabled data roaming,
* default to false.
- * @hide
*/
public static final String KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL =
"check_pricing_with_carrier_data_roaming_bool";
@@ -2786,10 +2751,10 @@
* Specifies a carrier-defined {@link android.telecom.CallRedirectionService} which Telecom
* will bind to for outgoing calls. An empty string indicates that no carrier-defined
* {@link android.telecom.CallRedirectionService} is specified.
- * @hide
*/
public static final String KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING =
"call_redirection_service_component_name_string";
+
/**
* Support for the original string display of CDMA MO call.
* By default, it is disabled.
@@ -2902,8 +2867,8 @@
"call_waiting_service_class_int";
/**
- * This configuration allow the system UI to display different 5G icon for different 5G
- * scenario.
+ * This configuration allows the system UI to display different 5G icons for different 5G
+ * scenarios.
*
* There are five 5G scenarios:
* 1. connected_mmwave: device currently connected to 5G cell as the secondary cell and using
@@ -2920,24 +2885,22 @@
* 5G cell as a secondary cell) but the use of 5G is restricted.
*
* The configured string contains multiple key-value pairs separated by comma. For each pair,
- * the key and value is separated by a colon. The key is corresponded to a 5G status above and
+ * the key and value are separated by a colon. The key corresponds to a 5G status above and
* the value is the icon name. Use "None" as the icon name if no icon should be shown in a
* specific 5G scenario. If the scenario is "None", config can skip this key and value.
*
* Icon name options: "5G_Plus", "5G".
*
* Here is an example:
- * UE want to display 5G_Plus icon for scenario#1, and 5G icon for scenario#2; otherwise no
+ * UE wants to display 5G_Plus icon for scenario#1, and 5G icon for scenario#2; otherwise not
* define.
* The configuration is: "connected_mmwave:5G_Plus,connected:5G"
- *
- * @hide
*/
public static final String KEY_5G_ICON_CONFIGURATION_STRING =
"5g_icon_configuration_string";
/**
- * Timeout in second for displaying 5G icon, default value is 0 which means the timer is
+ * Timeout in seconds for displaying 5G icon, default value is 0 which means the timer is
* disabled.
*
* System UI will show the 5G icon and start a timer with the timeout from this config when the
@@ -2946,8 +2909,6 @@
*
* If 5G is reacquired during this timer, the timer is canceled and restarted when 5G is next
* lost. Allows us to momentarily lose 5G without blinking the icon.
- *
- * @hide
*/
public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT =
"5g_icon_display_grace_period_sec_int";
@@ -3026,6 +2987,13 @@
"ping_test_before_data_switch_bool";
/**
+ * Controls time in milliseconds until DcTracker reevaluates 5G connection state.
+ * @hide
+ */
+ public static final String KEY_5G_WATCHDOG_TIME_MS_LONG =
+ "5g_watchdog_time_long";
+
+ /**
* Indicates zero or more emergency number prefix(es), because some carrier requires
* if users dial an emergency number address with a specific prefix, the combination of the
* prefix and the address is also a valid emergency number to dial. For example, an emergency
@@ -3058,8 +3026,6 @@
* signal bar of primary network. By default it will be false, meaning whenever data
* is going over opportunistic network, signal bar will reflect signal strength and rat
* icon of that network.
- *
- * @hide
*/
public static final String KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN =
"always_show_primary_signal_bar_in_opportunistic_network_boolean";
@@ -3153,7 +3119,6 @@
* 1 - yes. This is default.
* @hide
*/
- // TODO(b/119567985): name this key properly
public static final String KEY_SUPL_ES_STRING = KEY_PREFIX + "supl_es";
/**
@@ -3273,8 +3238,6 @@
/**
* Determines whether wifi calling location privacy policy is shown.
- *
- * @hide
*/
public static final String KEY_SHOW_WFC_LOCATION_PRIVACY_POLICY_BOOL =
"show_wfc_location_privacy_policy_bool";
@@ -3380,8 +3343,8 @@
"support_wps_over_ims_bool";
/**
- * Holds the list of carrier certificate hashes. Note that each carrier has its own certificates
- * @hide
+ * Holds the list of carrier certificate hashes.
+ * Note that each carrier has its own certificates.
*/
public static final String KEY_CARRIER_CERTIFICATE_STRING_ARRAY =
"carrier_certificate_string_array";
@@ -3439,6 +3402,7 @@
sDefaults.putInt(KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT, 2);
sDefaults.putInt(KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT, 2);
sDefaults.putBoolean(KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL, false);
+ sDefaults.putBoolean(KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL, true);
sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL, false);
@@ -3564,7 +3528,7 @@
sDefaults.putInt(KEY_IMS_DTMF_TONE_DELAY_INT, 0);
sDefaults.putInt(KEY_CDMA_DTMF_TONE_DELAY_INT, 100);
sDefaults.putBoolean(KEY_CALL_FORWARDING_MAP_NON_NUMBER_TO_VOICEMAIL_BOOL, false);
- sDefaults.putBoolean(KEY_IGNORE_RTT_MODE_SETTING_BOOL, true);
+ sDefaults.putBoolean(KEY_IGNORE_RTT_MODE_SETTING_BOOL, false);
sDefaults.putInt(KEY_CDMA_3WAYCALL_FLASH_DELAY_INT , 0);
sDefaults.putBoolean(KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_CONFERENCE_CALL_BOOL, true);
@@ -3850,6 +3814,8 @@
/* Default value is 3 seconds. */
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 3000);
sDefaults.putBoolean(KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL, true);
+ /* Default value is 1 hour. */
+ sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
sDefaults.putAll(Gps.getDefaults());
sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
new int[] {
@@ -3905,7 +3871,8 @@
+ " ICarrierConfigLoader is null");
return null;
}
- return loader.getConfigForSubId(subId, mContext.getOpPackageName());
+ return loader.getConfigForSubIdWithFeature(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
Rlog.e(TAG, "Error getting config for subId " + subId + ": "
+ ex.toString());
diff --git a/telephony/java/android/telephony/CbGeoUtils.java b/telephony/java/android/telephony/CbGeoUtils.java
index 84be4e8..719ba8d 100644
--- a/telephony/java/android/telephony/CbGeoUtils.java
+++ b/telephony/java/android/telephony/CbGeoUtils.java
@@ -16,6 +16,8 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.text.TextUtils;
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index b7dab16..399b1a4 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -16,13 +16,19 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.hardware.radio.V1_0.CellInfoType;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import com.android.telephony.Rlog;
+
import java.util.Objects;
import java.util.UUID;
@@ -181,7 +187,17 @@
* @return a CellLocation object for this CellIdentity
* @hide
*/
- public abstract CellLocation asCellLocation();
+ @SystemApi
+ public abstract @NonNull CellLocation asCellLocation();
+
+ /**
+ * Create and a return a new instance of CellIdentity with location-identifying information
+ * removed.
+ *
+ * @hide
+ */
+ @SystemApi
+ public abstract @NonNull CellIdentity sanitizeLocationInfo();
@Override
public boolean equals(Object other) {
@@ -310,4 +326,103 @@
return true;
}
+ /** @hide */
+ public static CellIdentity create(android.hardware.radio.V1_0.CellIdentity cellIdentity) {
+ if (cellIdentity == null) return null;
+ switch(cellIdentity.cellInfoType) {
+ case CellInfoType.GSM: {
+ if (cellIdentity.cellIdentityGsm.size() == 1) {
+ return new CellIdentityGsm(cellIdentity.cellIdentityGsm.get(0));
+ }
+ break;
+ }
+ case CellInfoType.WCDMA: {
+ if (cellIdentity.cellIdentityWcdma.size() == 1) {
+ return new CellIdentityWcdma(cellIdentity.cellIdentityWcdma.get(0));
+ }
+ break;
+ }
+ case CellInfoType.TD_SCDMA: {
+ if (cellIdentity.cellIdentityTdscdma.size() == 1) {
+ return new CellIdentityTdscdma(cellIdentity.cellIdentityTdscdma.get(0));
+ }
+ break;
+ }
+ case CellInfoType.LTE: {
+ if (cellIdentity.cellIdentityLte.size() == 1) {
+ return new CellIdentityLte(cellIdentity.cellIdentityLte.get(0));
+ }
+ break;
+ }
+ case CellInfoType.CDMA: {
+ if (cellIdentity.cellIdentityCdma.size() == 1) {
+ return new CellIdentityCdma(cellIdentity.cellIdentityCdma.get(0));
+ }
+ break;
+ }
+ case CellInfoType.NONE: break;
+ default: break;
+ }
+ return null;
+ }
+
+ /** @hide */
+ public static CellIdentity create(android.hardware.radio.V1_2.CellIdentity cellIdentity) {
+ if (cellIdentity == null) return null;
+ switch(cellIdentity.cellInfoType) {
+ case CellInfoType.GSM: {
+ if (cellIdentity.cellIdentityGsm.size() == 1) {
+ return new CellIdentityGsm(cellIdentity.cellIdentityGsm.get(0));
+ }
+ break;
+ }
+ case CellInfoType.WCDMA: {
+ if (cellIdentity.cellIdentityWcdma.size() == 1) {
+ return new CellIdentityWcdma(cellIdentity.cellIdentityWcdma.get(0));
+ }
+ break;
+ }
+ case CellInfoType.TD_SCDMA: {
+ if (cellIdentity.cellIdentityTdscdma.size() == 1) {
+ return new CellIdentityTdscdma(cellIdentity.cellIdentityTdscdma.get(0));
+ }
+ break;
+ }
+ case CellInfoType.LTE: {
+ if (cellIdentity.cellIdentityLte.size() == 1) {
+ return new CellIdentityLte(cellIdentity.cellIdentityLte.get(0));
+ }
+ break;
+ }
+ case CellInfoType.CDMA: {
+ if (cellIdentity.cellIdentityCdma.size() == 1) {
+ return new CellIdentityCdma(cellIdentity.cellIdentityCdma.get(0));
+ }
+ break;
+ }
+ case CellInfoType.NONE: break;
+ default: break;
+ }
+ return null;
+ }
+
+ /** @hide */
+ public static CellIdentity create(android.hardware.radio.V1_5.CellIdentity ci) {
+ if (ci == null) return null;
+ switch (ci.getDiscriminator()) {
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.gsm:
+ return new CellIdentityGsm(ci.gsm());
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.cdma:
+ return new CellIdentityCdma(ci.cdma());
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.lte:
+ return new CellIdentityLte(ci.lte());
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.wcdma:
+ return new CellIdentityWcdma(ci.wcdma());
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.tdscdma:
+ return new CellIdentityTdscdma(ci.tdscdma());
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.nr:
+ return new CellIdentityNr(ci.nr());
+ default: return null;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 880d3db..1a6bf33 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.telephony.cdma.CdmaCellLocation;
@@ -127,7 +128,8 @@
}
/** @hide */
- public CellIdentityCdma sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityCdma sanitizeLocationInfo() {
return new CellIdentityCdma(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
mAlphaLong, mAlphaShort);
@@ -198,6 +200,7 @@
}
/** @hide */
+ @NonNull
@Override
public CdmaCellLocation asCellLocation() {
CdmaCellLocation cl = new CdmaCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 25c6577..49f425a 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -16,8 +16,9 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
@@ -103,7 +104,8 @@
}
/** @hide */
- public CellIdentityGsm sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityGsm sanitizeLocationInfo() {
return new CellIdentityGsm(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
CellInfo.UNAVAILABLE, mMccStr, mMncStr, mAlphaLong, mAlphaShort);
}
@@ -200,6 +202,7 @@
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 997b19f..bc46550 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -16,8 +16,9 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.telephony.gsm.GsmCellLocation;
@@ -120,7 +121,8 @@
}
/** @hide */
- public CellIdentityLte sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityLte sanitizeLocationInfo() {
return new CellIdentityLte(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
mMccStr, mMncStr, mAlphaLong, mAlphaShort);
@@ -232,6 +234,7 @@
*
* @hide
*/
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index edc838c..f08a580 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -17,6 +17,7 @@
package android.telephony;
import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.telephony.gsm.GsmCellLocation;
@@ -68,7 +69,8 @@
}
/** @hide */
- public CellIdentityNr sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityNr sanitizeLocationInfo() {
return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort);
}
@@ -77,6 +79,7 @@
* @return a CellLocation object for this CellIdentity.
* @hide
*/
+ @NonNull
@Override
public CellLocation asCellLocation() {
return new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 558e346..4bb3a95 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -97,7 +97,8 @@
}
/** @hide */
- public CellIdentityTdscdma sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityTdscdma sanitizeLocationInfo() {
return new CellIdentityTdscdma(mMccStr, mMncStr, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort);
}
@@ -171,6 +172,7 @@
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 031fed1..4ecd134 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -16,8 +16,9 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
@@ -97,7 +98,8 @@
}
/** @hide */
- public CellIdentityWcdma sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityWcdma sanitizeLocationInfo() {
return new CellIdentityWcdma(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mMccStr, mMncStr,
mAlphaLong, mAlphaShort);
@@ -196,6 +198,7 @@
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index ae45307..ec86c14 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -18,7 +18,8 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.SuppressLint;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.radio.V1_4.CellInfo.Info;
import android.os.Parcel;
import android.os.Parcelable;
@@ -179,6 +180,18 @@
*
* @return a time stamp in nanos since boot.
*/
+ @SuppressLint("MethodNameUnits")
+ public long getTimestampNanos() {
+ return mTimeStamp;
+ }
+
+ /**
+ * Approximate time this cell information was received from the modem.
+ *
+ * @return a time stamp in nanos since boot.
+ * @deprecated Use {@link #getTimestampNanos} instead.
+ */
+ @Deprecated
public long getTimeStamp() {
return mTimeStamp;
}
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index 30b131f..acb21f4 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -16,12 +16,13 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
/**
* A {@link CellInfo} representing a CDMA cell that provides identity and measurement info.
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index 137f97e..79a9d44 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -16,11 +16,12 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
/**
* A {@link CellInfo} representing a GSM cell that provides identity and measurement info.
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index da7b7ab..fed3ebf 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -16,8 +16,10 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
index f1305f5..58ff8c9 100644
--- a/telephony/java/android/telephony/CellInfoTdscdma.java
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -16,6 +16,8 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java
index ee5fec8..33f6a55 100644
--- a/telephony/java/android/telephony/CellInfoWcdma.java
+++ b/telephony/java/android/telephony/CellInfoWcdma.java
@@ -18,7 +18,7 @@
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import java.util.Objects;
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index 0133153..64776e3 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -16,13 +16,13 @@
package android.telephony;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
-
-import android.annotation.UnsupportedAppUsage;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
+
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index 1998439..cab3b0c 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -20,7 +20,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import java.util.Objects;
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index fb16d54..28052aa 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -16,13 +16,14 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
-import android.telephony.Rlog;
import java.util.Objects;
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 8df9d23..2ef2a52 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -16,8 +16,10 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index f31fafe..4d67bcf 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -16,6 +16,8 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.os.Parcel;
@@ -155,7 +157,17 @@
* @param ss signal strength from modem.
*/
public CellSignalStrengthNr(android.hardware.radio.V1_4.NrSignalStrength ss) {
- this(ss.csiRsrp, ss.csiRsrq, ss.csiSinr, ss.ssRsrp, ss.ssRsrq, ss.ssSinr);
+ this(flip(ss.csiRsrp), flip(ss.csiRsrq), ss.csiSinr, flip(ss.ssRsrp), flip(ss.ssRsrq),
+ ss.ssSinr);
+ }
+
+ /**
+ * Flip sign cell strength value when taking in the value from hal
+ * @param val cell strength value
+ * @return flipped value
+ */
+ private static int flip(int val) {
+ return val != CellInfo.UNAVAILABLE ? -val : val;
}
/**
diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
index f4a3dbb..3bd9d58 100644
--- a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
@@ -16,6 +16,8 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.os.Parcel;
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index 4dc54f0..535e952 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -16,13 +16,14 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.IntRange;
import android.annotation.StringDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.lang.annotation.Retention;
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 04ec4b6..aff1391 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Describes the cause of a disconnected call. Those disconnect causes can be converted into a more
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index 39af34c..9b4292f 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -17,6 +17,8 @@
package android.telephony.ims;
import android.annotation.NonNull;
+import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
@@ -35,7 +37,63 @@
private Context mContext;
- /** @hide */
+ /**
+ * <p>Broadcast Action: Indicates that an IMS operation was rejected by the network due to it
+ * not being authorized on the network.
+ * May include the {@link SubscriptionManager#EXTRA_SUBSCRIPTION_INDEX} extra to also specify
+ * which subscription the operation was rejected for.
+ * <p class="note">
+ * Carrier applications may listen to this broadcast to be notified of possible IMS provisioning
+ * issues.
+ */
+ // Moved from TelephonyIntents, need to keep backwards compatibility with OEM apps that have
+ // this value hard-coded in BroadcastReceiver.
+ @SuppressLint("ActionValue")
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION =
+ "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
+
+ /**
+ * An intent action indicating that IMS registration for WiFi calling has resulted in an error.
+ * Contains error information that should be displayed to the user.
+ * <p>
+ * This intent will contain the following extra key/value pairs:
+ * {@link #EXTRA_WFC_REGISTRATION_FAILURE_TITLE}
+ * and {@link #EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE}, which contain carrier specific
+ * error information that should be displayed to the user.
+ * <p>
+ * Usage: This intent is sent as an ordered broadcast. If the settings application is going
+ * to show the error information specified to the user, it should respond to
+ * {@link android.content.BroadcastReceiver#setResultCode(int)} with
+ * {@link android.app.Activity#RESULT_CANCELED}, which will signal to the framework that the
+ * event was handled. If the framework does not receive a response to the ordered broadcast,
+ * it will then show a notification to the user indicating that there was a registration
+ * failure.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_WFC_IMS_REGISTRATION_ERROR =
+ "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
+
+ /**
+ * An extra key corresponding to a String value which contains the carrier specific title to be
+ * displayed as part of the message shown to the user when there is an error registering for
+ * WiFi calling.
+ */
+ public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE =
+ "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
+
+ /**
+ * An extra key corresponding to a String value which contains the carrier specific message to
+ * be displayed as part of the message shown to the user when there is an error registering for
+ * WiFi calling.
+ */
+ public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE =
+ "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
+
+ /**
+ * Use {@link Context#getSystemService(String)} to get an instance of this class.
+ * @hide
+ */
public ImsManager(@NonNull Context context) {
mContext = context;
}
diff --git a/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
index 92a674c..1c31368 100644
--- a/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
+++ b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
@@ -16,7 +16,7 @@
package android.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.Editable;
/*
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index 023ed30..5f46799 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -24,7 +24,7 @@
import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index fc717e7..32ffb75 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -36,23 +36,24 @@
/**
* Description of a mobile network registration info
- * @hide
*/
-@SystemApi
-@TestApi
public final class NetworkRegistrationInfo implements Parcelable {
/**
* Network domain
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "DOMAIN_", value = {DOMAIN_CS, DOMAIN_PS})
+ @IntDef(prefix = "DOMAIN_", value = {DOMAIN_UNKNOWN, DOMAIN_CS, DOMAIN_PS, DOMAIN_CS_PS})
public @interface Domain {}
- /** Circuit switching domain */
- public static final int DOMAIN_CS = 1;
- /** Packet switching domain */
- public static final int DOMAIN_PS = 2;
+ /** Unknown / Unspecified domain */
+ public static final int DOMAIN_UNKNOWN = 0;
+ /** Circuit switched domain */
+ public static final int DOMAIN_CS = android.hardware.radio.V1_5.Domain.CS;
+ /** Packet switched domain */
+ public static final int DOMAIN_PS = android.hardware.radio.V1_5.Domain.PS;
+ /** Applicable to both CS and PS Domain */
+ public static final int DOMAIN_CS_PS = DOMAIN_CS | DOMAIN_PS;
/**
* Network registration state
@@ -65,17 +66,41 @@
REGISTRATION_STATE_UNKNOWN, REGISTRATION_STATE_ROAMING})
public @interface RegistrationState {}
- /** Not registered. The device is not currently searching a new operator to register. */
+ /**
+ * Not registered. The device is not currently searching a new operator to register.
+ * @hide
+ */
+ @SystemApi @TestApi
public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0;
- /** Registered on home network. */
+ /**
+ * Registered on home network.
+ * @hide
+ */
+ @SystemApi @TestApi
public static final int REGISTRATION_STATE_HOME = 1;
- /** Not registered. The device is currently searching a new operator to register. */
+ /**
+ * Not registered. The device is currently searching a new operator to register.
+ * @hide
+ */
+ @SystemApi @TestApi
public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2;
- /** Registration denied. */
+ /**
+ * Registration denied.
+ * @hide
+ */
+ @SystemApi @TestApi
public static final int REGISTRATION_STATE_DENIED = 3;
- /** Registration state is unknown. */
+ /**
+ * Registration state is unknown.
+ * @hide
+ */
+ @SystemApi @TestApi
public static final int REGISTRATION_STATE_UNKNOWN = 4;
- /** Registered on roaming network. */
+ /**
+ * Registered on roaming network.
+ * @hide
+ */
+ @SystemApi @TestApi
public static final int REGISTRATION_STATE_ROAMING = 5;
/** @hide */
@@ -88,7 +113,6 @@
/**
* The device isn't camped on an LTE cell or the LTE cell doesn't support E-UTRA-NR
* Dual Connectivity(EN-DC).
- * @hide
*/
public static final int NR_STATE_NONE = 0;
@@ -96,7 +120,6 @@
* The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) but
* either the use of dual connectivity with NR(DCNR) is restricted or NR is not supported by
* the selected PLMN.
- * @hide
*/
public static final int NR_STATE_RESTRICTED = 1;
@@ -104,14 +127,12 @@
* The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) and both
* the use of dual connectivity with NR(DCNR) is not restricted and NR is supported by the
* selected PLMN.
- * @hide
*/
public static final int NR_STATE_NOT_RESTRICTED = 2;
/**
* The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) and
* also connected to at least one 5G cell as a secondary serving cell.
- * @hide
*/
public static final int NR_STATE_CONNECTED = 3;
@@ -125,22 +146,34 @@
SERVICE_TYPE_VIDEO, SERVICE_TYPE_EMERGENCY})
public @interface ServiceType {}
- /** Unkown service */
+ /**
+ * Unknown service
+ */
public static final int SERVICE_TYPE_UNKNOWN = 0;
- /** Voice service */
+ /**
+ * Voice service
+ */
public static final int SERVICE_TYPE_VOICE = 1;
- /** Data service */
+ /**
+ * Data service
+ */
public static final int SERVICE_TYPE_DATA = 2;
- /** SMS service */
+ /**
+ * SMS service
+ */
public static final int SERVICE_TYPE_SMS = 3;
- /** Video service */
+ /**
+ * Video service
+ */
public static final int SERVICE_TYPE_VIDEO = 4;
- /** Emergency service */
+ /**
+ * Emergency service
+ */
public static final int SERVICE_TYPE_EMERGENCY = 5;
@Domain
@@ -326,9 +359,7 @@
* Get the 5G NR connection state.
*
* @return the 5G NR connection state.
- * @hide
*/
- @SystemApi
public @NRState int getNrState() {
return mNrState;
}
@@ -340,7 +371,10 @@
/**
* @return The registration state.
+ *
+ * @hide
*/
+ @SystemApi @TestApi
public @RegistrationState int getRegistrationState() {
return mRegistrationState;
}
@@ -348,6 +382,21 @@
/**
* @return {@code true} if registered on roaming network, {@code false} otherwise.
*/
+ public boolean isRegistered() {
+ return mRegistrationState == REGISTRATION_STATE_HOME
+ || mRegistrationState == REGISTRATION_STATE_ROAMING;
+ }
+
+ /**
+ * @return {@code true} if registered on roaming network, {@code false} otherwise.
+ */
+ public boolean isSearching() {
+ return mRegistrationState == REGISTRATION_STATE_NOT_REGISTERED_SEARCHING;
+ }
+
+ /**
+ * @return {@code true} if registered on roaming network, {@code false} otherwise.
+ */
public boolean isRoaming() {
return mRoamingType != ServiceState.ROAMING_TYPE_NOT_ROAMING;
}
@@ -372,15 +421,18 @@
/**
* @return the current network roaming type.
+ * @hide
*/
-
+ @SystemApi @TestApi
public @ServiceState.RoamingType int getRoamingType() {
return mRoamingType;
}
/**
* @return Whether emergency is enabled.
+ * @hide
*/
+ @SystemApi @TestApi
public boolean isEmergencyEnabled() { return mEmergencyOnly; }
/**
@@ -418,7 +470,9 @@
* @return Reason for denial if the registration state is {@link #REGISTRATION_STATE_DENIED}.
* Depending on {@code accessNetworkTechnology}, the values are defined in 3GPP TS 24.008
* 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2 A.S0001 6.2.2.44 for CDMA
+ * @hide
*/
+ @SystemApi @TestApi
public int getRejectCause() {
return mRejectCause;
}
@@ -441,8 +495,10 @@
/**
* @return Data registration related info
+ * @hide
*/
@Nullable
+ @SystemApi @TestApi
public DataSpecificRegistrationInfo getDataSpecificInfo() {
return mDataSpecificInfo;
}
@@ -504,11 +560,21 @@
}
}
+ /** @hide */
+ static @NonNull String domainToString(@Domain int domain) {
+ switch (domain) {
+ case DOMAIN_CS: return "CS";
+ case DOMAIN_PS: return "PS";
+ case DOMAIN_CS_PS: return "CS_PS";
+ default: return "UNKNOWN";
+ }
+ }
+
@NonNull
@Override
public String toString() {
return new StringBuilder("NetworkRegistrationInfo{")
- .append(" domain=").append((mDomain == DOMAIN_CS) ? "CS" : "PS")
+ .append(" domain=").append(domainToString(mDomain))
.append(" transportType=").append(
AccessNetworkConstants.transportTypeToString(mTransportType))
.append(" registrationState=").append(registrationStateToString(mRegistrationState))
@@ -557,7 +623,11 @@
&& mNrState == other.mNrState;
}
+ /**
+ * @hide
+ */
@Override
+ @SystemApi @TestApi
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mDomain);
dest.writeInt(mTransportType);
@@ -645,8 +715,10 @@
* .setRegistrationState(REGISTRATION_STATE_HOME)
* .build();
* </code></pre>
+ * @hide
*/
- public static final class Builder{
+ @SystemApi @TestApi
+ public static final class Builder {
@Domain
private int mDomain;
@@ -745,7 +817,9 @@
* @param emergencyOnly True if this network registration is for emergency use only.
*
* @return The same instance of the builder.
+ * @hide
*/
+ @SystemApi @TestApi
public @NonNull Builder setEmergencyOnly(boolean emergencyOnly) {
mEmergencyOnly = emergencyOnly;
return this;
@@ -757,7 +831,9 @@
* @param availableServices Available services.
*
* @return The same instance of the builder.
+ * @hide
*/
+ @SystemApi @TestApi
public @NonNull Builder setAvailableServices(
@NonNull @ServiceType List<Integer> availableServices) {
mAvailableServices = availableServices;
@@ -770,7 +846,9 @@
* @param cellIdentity The cell identity.
*
* @return The same instance of the builder.
+ * @hide
*/
+ @SystemApi @TestApi
public @NonNull Builder setCellIdentity(@Nullable CellIdentity cellIdentity) {
mCellIdentity = cellIdentity;
return this;
@@ -778,9 +856,10 @@
/**
* Build the NetworkRegistrationInfo.
- *
* @return the NetworkRegistrationInfo object.
+ * @hide
*/
+ @SystemApi @TestApi
public @NonNull NetworkRegistrationInfo build() {
return new NetworkRegistrationInfo(mDomain, mTransportType, mRegistrationState,
mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
index 202da68..c249ece 100644
--- a/telephony/java/android/telephony/NetworkScan.java
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -16,6 +16,8 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.IntDef;
import android.content.Context;
import android.os.RemoteException;
diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java
index 8c5e107..844289c 100644
--- a/telephony/java/android/telephony/NetworkService.java
+++ b/telephony/java/android/telephony/NetworkService.java
@@ -16,6 +16,8 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
diff --git a/telephony/java/android/telephony/NetworkServiceCallback.java b/telephony/java/android/telephony/NetworkServiceCallback.java
index 89b9665..214ab41 100644
--- a/telephony/java/android/telephony/NetworkServiceCallback.java
+++ b/telephony/java/android/telephony/NetworkServiceCallback.java
@@ -16,6 +16,8 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index ac6bcaa..d4ed860 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -16,15 +16,14 @@
package android.telephony;
-import com.android.i18n.phonenumbers.AsYouTypeFormatter;
-import com.android.i18n.phonenumbers.PhoneNumberUtil;
-
-import android.annotation.UnsupportedAppUsage;
-import android.telephony.PhoneNumberUtils;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.Editable;
import android.text.Selection;
import android.text.TextWatcher;
+import com.android.i18n.phonenumbers.AsYouTypeFormatter;
+import com.android.i18n.phonenumbers.PhoneNumberUtil;
+
import java.util.Locale;
/**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 67afa7d..0074772 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -16,17 +16,18 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
-import android.location.CountryDetector;
import android.net.Uri;
import android.os.PersistableBundle;
import android.provider.Contacts;
@@ -2030,6 +2031,7 @@
private static boolean isEmergencyNumberInternal(int subId, String number,
String defaultCountryIso,
boolean useExactMatch) {
+ // TODO: clean up all the callers that pass in a defaultCountryIso, since it's ignored now.
try {
if (useExactMatch) {
return TelephonyManager.getDefault().isEmergencyNumber(number);
@@ -2191,18 +2193,7 @@
private static boolean isLocalEmergencyNumberInternal(int subId, String number,
Context context,
boolean useExactMatch) {
- String countryIso;
- CountryDetector detector = (CountryDetector) context.getSystemService(
- Context.COUNTRY_DETECTOR);
- if (detector != null && detector.detectCountry() != null) {
- countryIso = detector.detectCountry().getCountryIso();
- } else {
- Locale locale = context.getResources().getConfiguration().locale;
- countryIso = locale.getCountry();
- Rlog.w(LOG_TAG, "No CountryDetector; falling back to countryIso based on locale: "
- + countryIso);
- }
- return isEmergencyNumberInternal(subId, number, countryIso, useExactMatch);
+ return isEmergencyNumberInternal(subId, number, null /* unused */, useExactMatch);
}
/**
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
index bfa6326..98eeacf 100644
--- a/telephony/java/android/telephony/PreciseCallState.java
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -19,14 +19,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.PreciseCallStates;
import android.telephony.Annotation.PreciseDisconnectCauses;
-import android.telephony.DisconnectCause;
-import android.telephony.PreciseDisconnectCause;
import java.util.Objects;
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 78ad5c5..31434c1 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.LinkProperties;
import android.os.Build;
import android.os.Parcel;
@@ -81,18 +81,20 @@
/**
- * Constructor
+ * Constructor of PreciseDataConnectionState
*
* @param state the state of the data connection
* @param networkType the access network that is/would carry this data connection
* @param apnTypes the APN types that this data connection carries
- * @param apnSetting if there is a valid APN for this Data Connection, then the APN Settings;
- * if there is no valid APN setting for the specific type, then this will be null
+ * @param apn the APN of this data connection
* @param linkProperties if the data connection is connected, the properties of the connection
* @param failCause in case a procedure related to this data connection fails, a non-zero error
* code indicating the cause of the failure.
+ * @param apnSetting if there is a valid APN for this Data Connection, then the APN Settings;
+ * if there is no valid APN setting for the specific type, then this will be null
* @hide
*/
+ @SystemApi
public PreciseDataConnectionState(@DataState int state,
@NetworkType int networkType,
@ApnType int apnTypes, @NonNull String apn,
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index 28f6515..bc84738 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -16,9 +16,7 @@
package android.telephony;
-import android.annotation.UnsupportedAppUsage;
-import android.hardware.radio.V1_0.RadioTechnology;
-import android.hardware.radio.V1_4.CellInfo.Info;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 1014571..ed003ed 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
@@ -34,6 +34,8 @@
import android.telephony.NetworkRegistrationInfo.NRState;
import android.text.TextUtils;
+import com.android.telephony.Rlog;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -64,6 +66,13 @@
static final boolean DBG = false;
static final boolean VDBG = false; // STOPSHIP if true
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "STATE_",
+ value = {STATE_IN_SERVICE, STATE_OUT_OF_SERVICE, STATE_EMERGENCY_ONLY,
+ STATE_POWER_OFF})
+ public @interface RegState {}
+
/**
* Normal operation condition, the phone is registered
* with an operator either in home network or in roaming.
@@ -82,6 +91,7 @@
/**
* The phone is registered and locked. Only emergency numbers are allowed. {@more}
*/
+ //TODO: This state is not used anymore. It should be deprecated in a future release.
public static final int STATE_EMERGENCY_ONLY =
TelephonyProtoEnums.SERVICE_STATE_EMERGENCY_ONLY; // 2
@@ -371,15 +381,15 @@
/**
* Create a new ServiceState from a intent notifier Bundle
*
- * This method is used by PhoneStateIntentReceiver, CellBroadcastReceiver, and maybe by
- * external applications.
+ * This method is used to get ServiceState object from extras upon receiving
+ * {@link Intent#ACTION_SERVICE_STATE}.
*
* @param m Bundle from intent notifier
* @return newly created ServiceState
* @hide
*/
+ @SystemApi
@NonNull
- @UnsupportedAppUsage
public static ServiceState newFromBundle(@NonNull Bundle m) {
ServiceState ret;
ret = new ServiceState();
@@ -530,13 +540,15 @@
}
/**
- * Get current data service state
+ * Get current data registration state.
*
* @see #STATE_IN_SERVICE
* @see #STATE_OUT_OF_SERVICE
* @see #STATE_EMERGENCY_ONLY
* @see #STATE_POWER_OFF
*
+ * @return current data registration state
+ *
* @hide
*/
@UnsupportedAppUsage
@@ -545,6 +557,23 @@
}
/**
+ * Get current data registration state.
+ *
+ * @see #STATE_IN_SERVICE
+ * @see #STATE_OUT_OF_SERVICE
+ * @see #STATE_EMERGENCY_ONLY
+ * @see #STATE_POWER_OFF
+ *
+ * @return current data registration state
+ *
+ * @hide
+ */
+ @SystemApi
+ public @RegState int getDataRegistrationState() {
+ return getDataRegState();
+ }
+
+ /**
* Get the current duplex mode
*
* @see #DUPLEX_MODE_UNKNOWN
@@ -555,8 +584,8 @@
*/
@DuplexMode
public int getDuplexMode() {
- // only support LTE duplex mode
- if (!isLte(getRilDataRadioTechnology())) {
+ // support LTE/NR duplex mode
+ if (!isPsOnlyTech(getRilDataRadioTechnology())) {
return DUPLEX_MODE_UNKNOWN;
}
@@ -1254,11 +1283,15 @@
/**
* Set intent notifier Bundle based on service state.
*
+ * Put ServiceState object and its fields into bundle which is used by TelephonyRegistry
+ * to broadcast {@link Intent#ACTION_SERVICE_STATE}.
+ *
* @param m intent notifier Bundle
* @hide
+ *
*/
- @UnsupportedAppUsage
- public void fillInNotifierBundle(Bundle m) {
+ @SystemApi
+ public void fillInNotifierBundle(@NonNull Bundle m) {
m.putParcelable(Intent.EXTRA_SERVICE_STATE, this);
// serviceState already consists of below entries.
// for backward compatibility, we continue fill in below entries.
@@ -1437,7 +1470,15 @@
return getRilDataRadioTechnology();
}
- /** @hide */
+ /**
+ * Transform RIL radio technology {@link RilRadioTechnology} value to Network
+ * type {@link NetworkType}.
+ *
+ * @param rat The RIL radio technology {@link RilRadioTechnology}.
+ * @return The network type {@link NetworkType}.
+ *
+ * @hide
+ */
public static int rilRadioTechnologyToNetworkType(@RilRadioTechnology int rat) {
switch(rat) {
case RIL_RADIO_TECHNOLOGY_GPRS:
@@ -1519,7 +1560,15 @@
}
}
- /** @hide */
+ /**
+ * Transform network type {@link NetworkType} value to RIL radio technology
+ * {@link RilRadioTechnology}.
+ *
+ * @param networkType The network type {@link NetworkType}.
+ * @return The RIL radio technology {@link RilRadioTechnology}.
+ *
+ * @hide
+ */
public static int networkTypeToRilRadioTechnology(int networkType) {
switch(networkType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
@@ -1575,7 +1624,8 @@
* @return Current data network type
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @SystemApi
+ @TestApi
public @NetworkType int getDataNetworkType() {
final NetworkRegistrationInfo iwlanRegInfo = getNetworkRegistrationInfo(
NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
@@ -1668,9 +1718,10 @@
}
/** @hide */
- public static boolean isLte(int radioTechnology) {
- return radioTechnology == RIL_RADIO_TECHNOLOGY_LTE ||
- radioTechnology == RIL_RADIO_TECHNOLOGY_LTE_CA;
+ public static boolean isPsOnlyTech(int radioTechnology) {
+ return radioTechnology == RIL_RADIO_TECHNOLOGY_LTE
+ || radioTechnology == RIL_RADIO_TECHNOLOGY_LTE_CA
+ || radioTechnology == RIL_RADIO_TECHNOLOGY_NR;
}
/** @hide */
@@ -1720,7 +1771,14 @@
return bearerBitmask;
}
- /** @hide */
+ /**
+ * Convert network type bitmask to bearer bitmask.
+ *
+ * @param networkTypeBitmask The network type bitmask value
+ * @return The bearer bitmask value.
+ *
+ * @hide
+ */
public static int convertNetworkTypeBitmaskToBearerBitmask(int networkTypeBitmask) {
if (networkTypeBitmask == 0) {
return 0;
@@ -1734,7 +1792,14 @@
return bearerBitmask;
}
- /** @hide */
+ /**
+ * Convert bearer bitmask to network type bitmask.
+ *
+ * @param bearerBitmask The bearer bitmask value.
+ * @return The network type bitmask value.
+ *
+ * @hide
+ */
public static int convertBearerBitmaskToNetworkTypeBitmask(int bearerBitmask) {
if (bearerBitmask == 0) {
return 0;
@@ -1772,10 +1837,8 @@
* Get all of the available network registration info.
*
* @return List of {@link NetworkRegistrationInfo}
- * @hide
*/
@NonNull
- @SystemApi
public List<NetworkRegistrationInfo> getNetworkRegistrationInfoList() {
synchronized (mNetworkRegistrationInfos) {
List<NetworkRegistrationInfo> newList = new ArrayList<>();
@@ -1825,7 +1888,7 @@
synchronized (mNetworkRegistrationInfos) {
for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) {
- if (networkRegistrationInfo.getDomain() == domain) {
+ if ((networkRegistrationInfo.getDomain() & domain) != 0) {
list.add(new NetworkRegistrationInfo(networkRegistrationInfo));
}
}
@@ -1841,7 +1904,6 @@
* @param transportType The transport type
* @return The matching {@link NetworkRegistrationInfo}
* @hide
- *
*/
@Nullable
@SystemApi
@@ -1850,7 +1912,7 @@
synchronized (mNetworkRegistrationInfos) {
for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) {
if (networkRegistrationInfo.getTransportType() == transportType
- && networkRegistrationInfo.getDomain() == domain) {
+ && (networkRegistrationInfo.getDomain() & domain) != 0) {
return new NetworkRegistrationInfo(networkRegistrationInfo);
}
}
@@ -1893,9 +1955,18 @@
* Returns a copy of self with location-identifying information removed.
* Always clears the NetworkRegistrationInfo's CellIdentity fields, but if removeCoarseLocation
* is true, clears other info as well.
+ *
+ * @param removeCoarseLocation Whether to also remove coarse location information.
+ * if false, it only clears fine location information such as
+ * NetworkRegistrationInfo's CellIdentity fields; If true, it will
+ * also remove other location information such as operator's MCC
+ * and MNC.
+ * @return the copied ServiceState with location info sanitized.
* @hide
*/
- public ServiceState sanitizeLocationInfo(boolean removeCoarseLocation) {
+ @SystemApi
+ @NonNull
+ public ServiceState createLocationInfoSanitizedCopy(boolean removeCoarseLocation) {
ServiceState state = new ServiceState(this);
synchronized (state.mNetworkRegistrationInfos) {
List<NetworkRegistrationInfo> networkRegistrationInfos =
@@ -1975,4 +2046,27 @@
public boolean isIwlanPreferred() {
return mIsIwlanPreferred;
}
+ /**
+ * @return {@code true}Returns True whenever the modem is searching for service.
+ * To check both CS and PS domain
+ */
+
+ public boolean isSearching() {
+ NetworkRegistrationInfo psRegState = getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+
+ if (psRegState != null && psRegState.getRegistrationState()
+ == NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING) {
+ return true;
+ }
+
+ NetworkRegistrationInfo csRegState = getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+
+ if (csRegState != null && csRegState.getRegistrationState()
+ == NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 9aafc1b..483ccc4 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -17,12 +17,17 @@
package android.telephony;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
+import android.os.SystemClock;
+
+import com.android.telephony.Rlog;
import java.util.ArrayList;
import java.util.List;
@@ -74,6 +79,9 @@
/* The type of signal measurement */
private static final String MEASUREMENT_TYPE_RSCP = "rscp";
+ // timeStamp of signalStrength in nanoseconds since boot
+ private long mTimestamp = Long.MAX_VALUE;
+
CellSignalStrengthCdma mCdma;
CellSignalStrengthGsm mGsm;
CellSignalStrengthWcdma mWcdma;
@@ -132,6 +140,7 @@
mTdscdma = tdscdma;
mLte = lte;
mNr = nr;
+ mTimestamp = SystemClock.elapsedRealtimeNanos();
}
/**
@@ -266,6 +275,7 @@
mTdscdma.updateLevel(cc, ss);
mLte.updateLevel(cc, ss);
mNr.updateLevel(cc, ss);
+ mTimestamp = SystemClock.elapsedRealtimeNanos();
}
/**
@@ -275,8 +285,8 @@
*
* @hide
*/
- @UnsupportedAppUsage
- public SignalStrength(SignalStrength s) {
+ @SystemApi
+ public SignalStrength(@NonNull SignalStrength s) {
copyFrom(s);
}
@@ -291,6 +301,7 @@
mTdscdma = new CellSignalStrengthTdscdma(s.mTdscdma);
mLte = new CellSignalStrengthLte(s.mLte);
mNr = new CellSignalStrengthNr(s.mNr);
+ mTimestamp = s.getTimestampNanos();
}
/**
@@ -308,6 +319,7 @@
mTdscdma = in.readParcelable(CellSignalStrengthTdscdma.class.getClassLoader());
mLte = in.readParcelable(CellSignalStrengthLte.class.getClassLoader());
mNr = in.readParcelable(CellSignalStrengthLte.class.getClassLoader());
+ mTimestamp = in.readLong();
}
/**
@@ -320,9 +332,18 @@
out.writeParcelable(mTdscdma, flags);
out.writeParcelable(mLte, flags);
out.writeParcelable(mNr, flags);
+ out.writeLong(mTimestamp);
}
/**
+ * @return mTimestamp in nanoseconds
+ */
+ @SuppressLint("MethodNameUnits")
+ public long getTimestampNanos() {
+ return mTimestamp;
+ }
+
+ /**
* {@link Parcelable#describeContents}
*/
public int describeContents() {
@@ -332,17 +353,16 @@
/**
* {@link Parcelable.Creator}
*
- * @hide
*/
- @UnsupportedAppUsage
- public static final @android.annotation.NonNull Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
- public SignalStrength createFromParcel(Parcel in) {
- return new SignalStrength(in);
- }
+ public static final @android.annotation.NonNull Parcelable.Creator<SignalStrength> CREATOR =
+ new Parcelable.Creator<SignalStrength>() {
+ public SignalStrength createFromParcel(Parcel in) {
+ return new SignalStrength(in);
+ }
- public SignalStrength[] newArray(int size) {
- return new SignalStrength[size];
- }
+ public SignalStrength[] newArray(int size) {
+ return new SignalStrength[size];
+ }
};
/**
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 6c2dd85..0ba36b1 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -24,15 +25,13 @@
import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.CursorWindow;
import android.net.Uri;
-import android.os.Binder;
-import android.os.BaseBundle;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
@@ -1578,7 +1577,7 @@
}
/**
- * Copy a raw SMS PDU to the ICC.
+ * Copies a raw SMS PDU to the ICC.
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
@@ -1592,21 +1591,26 @@
* operation is performed on the correct subscription.
* </p>
*
- * @param smsc the SMSC for this message, or NULL for the default SMSC
- * @param pdu the raw PDU to store
- * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
- * STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
- * @return true for success
+ * @param smsc the SMSC for this messag or null for the default SMSC.
+ * @param pdu the raw PDU to store.
+ * @param status message status. One of these status:
+ * <code>STATUS_ON_ICC_READ</code>
+ * <code>STATUS_ON_ICC_UNREAD</code>
+ * <code>STATUS_ON_ICC_SENT</code>
+ * <code>STATUS_ON_ICC_UNSENT</code>
+ * @return true for success. Otherwise false.
*
- * @throws IllegalArgumentException if pdu is NULL
- * {@hide}
+ * @throws IllegalArgumentException if pdu is null.
+ * @hide
*/
- @UnsupportedAppUsage
- public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
+ public boolean copyMessageToIcc(
+ @Nullable byte[] smsc, @NonNull byte[] pdu, @StatusOnIcc int status) {
boolean success = false;
- if (null == pdu) {
- throw new IllegalArgumentException("pdu is NULL");
+ if (pdu == null) {
+ throw new IllegalArgumentException("pdu is null");
}
try {
ISms iSms = getISmsService();
@@ -1623,7 +1627,7 @@
}
/**
- * Delete the specified message from the ICC.
+ * Deletes the specified message from the ICC.
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
@@ -1637,14 +1641,16 @@
* operation is performed on the correct subscription.
* </p>
*
- * @param messageIndex is the record index of the message on ICC
- * @return true for success
+ * @param messageIndex This is the same index used to access a message
+ * from {@link #getMessagesFromIcc()}.
+ * @return true for success, false if the operation fails. Failure can be due to IPC failure,
+ * RIL/modem error which results in SMS failed to be deleted on SIM
*
* {@hide}
*/
- @UnsupportedAppUsage
- public boolean
- deleteMessageFromIcc(int messageIndex) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
+ public boolean deleteMessageFromIcc(int messageIndex) {
boolean success = false;
try {
@@ -1686,6 +1692,7 @@
* {@hide}
*/
@UnsupportedAppUsage
+ @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
boolean success = false;
@@ -1704,7 +1711,7 @@
}
/**
- * Retrieves all messages currently stored on ICC.
+ * Retrieves all messages currently stored on the ICC.
* ICC (Integrated Circuit Card) is the card of the device.
* For example, this can be the SIM or USIM for GSM.
*
@@ -1718,8 +1725,22 @@
* operation is performed on the correct subscription.
* </p>
*
+ * @return <code>List</code> of <code>SmsMessage</code> objects
+ *
+ * {@hide}
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
+ public @NonNull List<SmsMessage> getMessagesFromIcc() {
+ return getAllMessagesFromIcc();
+ }
+
+ /**
* @return <code>ArrayList</code> of <code>SmsMessage</code> objects
*
+ * This is similar to {@link #getMessagesFromIcc} except that it will return ArrayList.
+ * Suggested to use {@link #getMessagesFromIcc} instead.
+ *
* {@hide}
*/
@UnsupportedAppUsage
@@ -1856,8 +1877,7 @@
}
/**
- * Create a list of <code>SmsMessage</code>s from a list of RawSmsData
- * records returned by <code>getAllMessagesFromIcc()</code>
+ * Creates a list of <code>SmsMessage</code>s from a list of SmsRawData records.
*
* <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
* applications or the Telephony framework and will never trigger an SMS disambiguation
@@ -1869,8 +1889,7 @@
* operation is performed on the correct subscription.
* </p>
*
- * @param records SMS EF records, returned by
- * <code>getAllMessagesFromIcc</code>
+ * @param records SMS EF records.
* @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
*/
private ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) {
@@ -1881,7 +1900,7 @@
SmsRawData data = records.get(i);
// List contains all records, including "free" records (null)
if (data != null) {
- SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes(),
+ SmsMessage sms = SmsMessage.createFromEfRecord(i + 1, data.getBytes(),
getSubscriptionId());
if (sms != null) {
messages.add(sms);
@@ -2021,6 +2040,17 @@
return ret;
}
+ /** @hide */
+ @IntDef(prefix = { "STATUS_ON_ICC_" }, value = {
+ STATUS_ON_ICC_FREE,
+ STATUS_ON_ICC_READ,
+ STATUS_ON_ICC_UNREAD,
+ STATUS_ON_ICC_SENT,
+ STATUS_ON_ICC_UNSENT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StatusOnIcc {}
+
// see SmsMessage.getStatusOnIcc
/** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
@@ -2409,33 +2439,32 @@
/** Intent extra name for HTTP status code for MMS HTTP failure in integer type */
public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS";
- /** Represents the received SMS message for importing {@hide} */
- public static final int SMS_TYPE_INCOMING = 0;
- /** Represents the sent SMS message for importing {@hide} */
- public static final int SMS_TYPE_OUTGOING = 1;
-
- /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */
- public static final String MESSAGE_STATUS_SEEN = "seen";
- /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */
- public static final String MESSAGE_STATUS_READ = "read";
-
/**
- * Get carrier-dependent configuration values.
+ * Get carrier-dependent MMS configuration values.
*
* <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
- * applications or the Telephony framework and will never trigger an SMS disambiguation
- * dialog. If this method is called on a device that has multiple active subscriptions, this
- * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
- * default subscription is defined, the subscription ID associated with this message will be
- * INVALID, which will result in the operation being completed on the subscription associated
- * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
- * operation is performed on the correct subscription.
+ * applications or the Telephony framework and will never trigger an SMS disambiguation dialog.
+ * If this method is called on a device that has multiple active subscriptions, this {@link
+ * SmsManager} instance has been created with {@link #getDefault()}, and no user-defined default
+ * subscription is defined, the subscription ID associated with this message will be INVALID,
+ * which will result in the operation being completed on the subscription associated with
+ * logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation is
+ * performed on the correct subscription.
* </p>
*
- * @return bundle key/values pairs of configuration values
+ * @return the bundle key/values pairs that contains MMS configuration values
*/
+ @Nullable
public Bundle getCarrierConfigValues() {
- return MmsManager.getInstance().getCarrierConfigValues(getSubscriptionId());
+ try {
+ ISms iSms = getISmsService();
+ if (iSms != null) {
+ return iSms.getCarrierConfigValuesForSubscriber(getSubscriptionId());
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+ return null;
}
/**
@@ -2677,7 +2706,7 @@
ISms iccISms = getISmsServiceOrThrow();
if (iccISms != null) {
return iccISms.checkSmsShortCodeDestination(getSubscriptionId(),
- ActivityThread.currentPackageName(), destAddress, countryIso);
+ ActivityThread.currentPackageName(), null, destAddress, countryIso);
}
} catch (RemoteException e) {
Log.e(TAG, "checkSmsShortCodeDestination() RemoteException", e);
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 392d3eb..8d9b1dd 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -16,11 +16,18 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
+import android.Manifest;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.StringDef;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.SystemApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.os.Binder;
import android.text.TextUtils;
@@ -29,8 +36,10 @@
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.Sms7BitEncodingTranslator;
import com.android.internal.telephony.SmsConstants;
+import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.SmsMessageBase.SubmitPduBase;
+import com.android.internal.telephony.cdma.sms.UserData;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -54,6 +63,16 @@
UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3;
}
+ /** @hide */
+ @IntDef(prefix = { "ENCODING_" }, value = {
+ ENCODING_UNKNOWN,
+ ENCODING_7BIT,
+ ENCODING_8BIT,
+ ENCODING_16BIT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EncodingSize {}
+
/** User data text encoding code unit size */
public static final int ENCODING_UNKNOWN = 0;
public static final int ENCODING_7BIT = 1;
@@ -259,41 +278,24 @@
}
/**
- * Create an SmsMessage from an SMS EF record.
+ * Creates an SmsMessage from an SMS EF record.
*
- * @param index Index of SMS record. This should be index in ArrayList
- * returned by SmsManager.getAllMessagesFromSim + 1.
+ * @param index Index of SMS EF record.
* @param data Record data.
* @return An SmsMessage representing the record.
*
* @hide
*/
public static SmsMessage createFromEfRecord(int index, byte[] data) {
- SmsMessageBase wrappedMessage;
-
- if (isCdmaVoice()) {
- wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord(
- index, data);
- } else {
- wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromEfRecord(
- index, data);
- }
-
- if (wrappedMessage != null) {
- return new SmsMessage(wrappedMessage);
- } else {
- Rlog.e(LOG_TAG, "createFromEfRecord(): wrappedMessage is null");
- return null;
- }
+ return createFromEfRecord(index, data, SmsManager.getDefaultSmsSubscriptionId());
}
/**
- * Create an SmsMessage from an SMS EF record.
+ * Creates an SmsMessage from an SMS EF record.
*
- * @param index Index of SMS record. This should be index in ArrayList
- * returned by SmsManager.getAllMessagesFromSim + 1.
+ * @param index Index of SMS EF record.
* @param data Record data.
- * @param subId Subscription Id of the SMS
+ * @param subId Subscription Id associated with the record.
* @return An SmsMessage representing the record.
*
* @hide
@@ -313,6 +315,34 @@
}
/**
+ * Create an SmsMessage from a native SMS-Submit PDU, specified by Bluetooth Message Access
+ * Profile Specification v1.4.2 5.8.
+ * This is used by Bluetooth MAP profile to decode message when sending non UTF-8 SMS messages.
+ *
+ * @param data Message data.
+ * @param isCdma Indicates weather the type of the SMS is CDMA.
+ * @return An SmsMessage representing the message.
+ *
+ * @hide
+ */
+ @SystemApi
+ @Nullable
+ public static SmsMessage createFromNativeSmsSubmitPdu(@NonNull byte[] data, boolean isCdma) {
+ SmsMessageBase wrappedMessage;
+
+ if (isCdma) {
+ wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord(
+ 0, data);
+ } else {
+ // Bluetooth uses its own method to decode GSM PDU so this part is not called.
+ wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromEfRecord(
+ 0, data);
+ }
+
+ return wrappedMessage != null ? new SmsMessage(wrappedMessage) : null;
+ }
+
+ /**
* Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the
* length in bytes (not hex chars) less the SMSC header
*
@@ -555,13 +585,15 @@
*/
/**
- * Get an SMS-SUBMIT PDU for a destination address and a message.
+ * Gets an SMS-SUBMIT PDU for a destination address and a message.
* This method will not attempt to use any GSM national language 7 bit encodings.
*
- * @param scAddress Service Centre address. Null means use default.
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param scAddress Service Centre address. Null means use default.
+ * @param destinationAddress the address of the destination for the message.
+ * @param message string representation of the message payload.
+ * @param statusReportRequested indicates whether a report is requested for this message.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
*/
public static SubmitPdu getSubmitPdu(String scAddress,
String destinationAddress, String message, boolean statusReportRequested) {
@@ -574,17 +606,16 @@
}
/**
- * Get an SMS-SUBMIT PDU for a destination address and a message.
+ * Gets an SMS-SUBMIT PDU for a destination address and a message.
* This method will not attempt to use any GSM national language 7 bit encodings.
*
- * @param scAddress Service Centre address. Null means use default.
+ * @param scAddress Service Centre address. Null means use default.
* @param destinationAddress the address of the destination for the message.
- * @param message String representation of the message payload.
- * @param statusReportRequested Indicates whether a report is requested for this message.
- * @param subId Subscription of the message
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param message string representation of the message payload.
+ * @param statusReportRequested indicates whether a report is requested for this message.
+ * @param subId subscription of the message.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
* @hide
*/
public static SubmitPdu getSubmitPdu(String scAddress,
@@ -602,17 +633,16 @@
}
/**
- * Get an SMS-SUBMIT PDU for a data message to a destination address & port.
+ * Gets an SMS-SUBMIT PDU for a data message to a destination address & port.
* This method will not attempt to use any GSM national language 7 bit encodings.
*
- * @param scAddress Service Centre address. null == use default
- * @param destinationAddress the address of the destination for the message
- * @param destinationPort the port to deliver the message to at the
- * destination
- * @param data the data for the message
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param scAddress Service Centre address. Null means use default.
+ * @param destinationAddress the address of the destination for the message.
+ * @param destinationPort the port to deliver the message to at the destination.
+ * @param data the data for the message.
+ * @param statusReportRequested indicates whether a report is requested for this message.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
*/
public static SubmitPdu getSubmitPdu(String scAddress,
String destinationAddress, short destinationPort, byte[] data,
@@ -630,6 +660,132 @@
return new SubmitPdu(spb);
}
+ // TODO: SubmitPdu class is used for SMS-DELIVER also now. Refactor for SubmitPdu and new
+ // DeliverPdu accordingly.
+
+ /**
+ * Gets an SMS PDU to store in the ICC.
+ *
+ * @param subId subscription of the message.
+ * @param status message status. One of these status:
+ * <code>SmsManager.STATUS_ON_ICC_READ</code>
+ * <code>SmsManager.STATUS_ON_ICC_UNREAD</code>
+ * <code>SmsManager.STATUS_ON_ICC_SENT</code>
+ * <code>SmsManager.STATUS_ON_ICC_UNSENT</code>
+ * @param scAddress Service Centre address. Null means use default.
+ * @param address destination or originating address.
+ * @param message string representation of the message payload.
+ * @param date the time stamp the message was received.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
+ * @hide
+ */
+ @SystemApi
+ @Nullable
+ public static SubmitPdu getSmsPdu(int subId, @SmsManager.StatusOnIcc int status,
+ @Nullable String scAddress, @NonNull String address, @NonNull String message,
+ long date) {
+ SubmitPduBase spb;
+ if (isCdmaVoice(subId)) { // 3GPP2 format
+ if (status == SmsManager.STATUS_ON_ICC_READ
+ || status == SmsManager.STATUS_ON_ICC_UNREAD) { // Deliver PDU
+ spb = com.android.internal.telephony.cdma.SmsMessage.getDeliverPdu(address,
+ message, date);
+ } else { // Submit PDU
+ spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+ address, message, false /* statusReportRequested */, null /* smsHeader */);
+ }
+ } else { // 3GPP format
+ if (status == SmsManager.STATUS_ON_ICC_READ
+ || status == SmsManager.STATUS_ON_ICC_UNREAD) { // Deliver PDU
+ spb = com.android.internal.telephony.gsm.SmsMessage.getDeliverPdu(scAddress,
+ address, message, date);
+ } else { // Submit PDU
+ spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+ address, message, false /* statusReportRequested */, null /* header */);
+ }
+ }
+
+ return spb != null ? new SubmitPdu(spb) : null;
+ }
+
+ /**
+ * Get an SMS-SUBMIT PDU's encoded message.
+ * This is used by Bluetooth MAP profile to handle long non UTF-8 SMS messages.
+ *
+ * @param isTypeGsm true when message's type is GSM, false when type is CDMA
+ * @param destinationAddress the address of the destination for the message
+ * @param message message content
+ * @param encoding User data text encoding code unit size
+ * @param languageTable GSM national language table to use, specified by 3GPP
+ * 23.040 9.2.3.24.16
+ * @param languageShiftTable GSM national language shift table to use, specified by 3GPP
+ * 23.040 9.2.3.24.15
+ * @param refNumber parameter to create SmsHeader
+ * @param seqNumber parameter to create SmsHeader
+ * @param msgCount parameter to create SmsHeader
+ * @return a byte[] containing the encoded message
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @SystemApi
+ @NonNull
+ public static byte[] getSubmitPduEncodedMessage(boolean isTypeGsm,
+ @NonNull String destinationAddress,
+ @NonNull String message,
+ @EncodingSize int encoding, int languageTable,
+ int languageShiftTable, int refNumber,
+ int seqNumber, int msgCount) {
+ byte[] data;
+ SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+ concatRef.refNumber = refNumber;
+ concatRef.seqNumber = seqNumber; // 1-based sequence
+ concatRef.msgCount = msgCount;
+ // We currently set this to true since our messaging app will never
+ // send more than 255 parts (it converts the message to MMS well before that).
+ // However, we should support 3rd party messaging apps that might need 16-bit
+ // references
+ // Note: It's not sufficient to just flip this bit to true; it will have
+ // ripple effects (several calculations assume 8-bit ref).
+ concatRef.isEightBits = true;
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.concatRef = concatRef;
+
+ /* Depending on the type, call either GSM or CDMA getSubmitPdu(). The encoding
+ * will be determined(again) by getSubmitPdu().
+ * All packets need to be encoded using the same encoding, as the bMessage
+ * only have one filed to describe the encoding for all messages in a concatenated
+ * SMS... */
+ if (encoding == ENCODING_7BIT) {
+ smsHeader.languageTable = languageTable;
+ smsHeader.languageShiftTable = languageShiftTable;
+ }
+
+ if (isTypeGsm) {
+ data = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(null,
+ destinationAddress, message, false,
+ SmsHeader.toByteArray(smsHeader), encoding, languageTable,
+ languageShiftTable).encodedMessage;
+ } else { // SMS_TYPE_CDMA
+ UserData uData = new UserData();
+ uData.payloadStr = message;
+ uData.userDataHeader = smsHeader;
+ if (encoding == ENCODING_7BIT) {
+ uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
+ } else { // assume UTF-16
+ uData.msgEncoding = UserData.ENCODING_UNICODE_16;
+ }
+ uData.msgEncodingSet = true;
+ data = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
+ destinationAddress, uData, false).encodedMessage;
+ }
+ if (data == null) {
+ return new byte[0];
+ }
+ return data;
+ }
+
/**
* Returns the address of the SMS service center that relayed this message
* or null if there is none.
@@ -1038,10 +1194,10 @@
}
/**
- * {@hide}
* Returns the recipient address(receiver) of this SMS message in String form or null if
* unavailable.
*/
+ @Nullable
public String getRecipientAddress() {
return mWrappedSmsMessage.getRecipientAddress();
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index bbde1f4..2d8e237 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -16,9 +16,11 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 376a5e0..d4ab04cc 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -16,6 +16,8 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
@@ -32,9 +34,9 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -48,7 +50,6 @@
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.ParcelUuid;
import android.os.Process;
@@ -64,6 +65,7 @@
import com.android.internal.telephony.ISetOpportunisticDataCallback;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.util.HandlerExecutor;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
@@ -1040,6 +1042,23 @@
*/
public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
if (listener == null) return;
+ addOnSubscriptionsChangedListener(listener.mExecutor, listener);
+ }
+
+ /**
+ * Register for changes to the list of active {@link SubscriptionInfo} records or to the
+ * individual records themselves. When a change occurs the onSubscriptionsChanged method of
+ * the listener will be invoked immediately if there has been a notification. The
+ * onSubscriptionChanged method will also be triggered once initially when calling this
+ * function.
+ *
+ * @param listener an instance of {@link OnSubscriptionsChangedListener} with
+ * onSubscriptionsChanged overridden.
+ * @param executor the executor that will execute callbacks.
+ */
+ public void addOnSubscriptionsChangedListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnSubscriptionsChangedListener listener) {
String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
if (DBG) {
logd("register OnSubscriptionsChangedListener pkgName=" + pkgName
@@ -1051,7 +1070,7 @@
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (telephonyRegistryManager != null) {
telephonyRegistryManager.addOnSubscriptionsChangedListener(listener,
- listener.mExecutor);
+ executor);
}
}
@@ -1186,7 +1205,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName());
+ subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1197,12 +1217,17 @@
}
/**
- * Get the active SubscriptionInfo associated with the iccId
+ * Gets an active SubscriptionInfo {@link SubscriptionInfo} associated with the Sim IccId.
+ *
* @param iccId the IccId of SIM card
* @return SubscriptionInfo, maybe null if its not active
+ *
* @hide
*/
- public SubscriptionInfo getActiveSubscriptionInfoForIccIndex(String iccId) {
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @Nullable
+ @SystemApi
+ public SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String iccId) {
if (VDBG) logd("[getActiveSubscriptionInfoForIccIndex]+ iccId=" + iccId);
if (iccId == null) {
logd("[getActiveSubscriptionInfoForIccIndex]- null iccid");
@@ -1214,7 +1239,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName());
+ result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1248,7 +1274,7 @@
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
- mContext.getOpPackageName());
+ mContext.getOpPackageName(), null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1271,7 +1297,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getAllSubInfoList(mContext.getOpPackageName());
+ result = iSub.getAllSubInfoList(mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1346,7 +1373,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName());
+ activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1396,7 +1424,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName());
+ result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1513,7 +1542,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getAllSubInfoCount(mContext.getOpPackageName());
+ result = iSub.getAllSubInfoCount(mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1541,7 +1571,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getActiveSubInfoCount(mContext.getOpPackageName());
+ result = iSub.getActiveSubInfoCount(mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -2278,7 +2309,7 @@
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
resultValue = iSub.getSubscriptionProperty(subId, propKey,
- context.getOpPackageName());
+ context.getOpPackageName(), null);
}
} catch (RemoteException ex) {
// ignore it
@@ -2419,7 +2450,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- return iSub.isActiveSubId(subId, mContext.getOpPackageName());
+ return iSub.isActiveSubId(subId, mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
}
@@ -2472,6 +2504,8 @@
* may not be displayed or used by decision making logic.
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
+ * @throws IllegalArgumentException if plans don't meet the requirements
+ * defined in {@link SubscriptionPlan}.
*/
public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
try {
@@ -2645,8 +2679,7 @@
/**
* Checks whether the app with the given context is authorized to manage the given subscription
- * according to its metadata. Only supported for embedded subscriptions (if
- * {@code SubscriptionInfo#isEmbedded} returns true).
+ * according to its metadata.
*
* @param info The subscription to check.
* @return whether the app is authorized to manage this subscription per its metadata.
@@ -2659,16 +2692,16 @@
* Checks whether the given app is authorized to manage the given subscription. An app can only
* be authorized if it is included in the {@link android.telephony.UiccAccessRule} of the
* {@link android.telephony.SubscriptionInfo} with the access status.
- * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded}
- * returns true).
*
* @param info The subscription to check.
* @param packageName Package name of the app to check.
* @return whether the app is authorized to manage this subscription per its access rules.
* @hide
*/
- public boolean canManageSubscription(SubscriptionInfo info, String packageName) {
- if (info == null || info.getAllAccessRules() == null) {
+ @SystemApi
+ public boolean canManageSubscription(@Nullable SubscriptionInfo info,
+ @Nullable String packageName) {
+ if (info == null || info.getAllAccessRules() == null || packageName == null) {
return false;
}
PackageManager packageManager = mContext.getPackageManager();
@@ -2787,13 +2820,14 @@
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public @NonNull List<SubscriptionInfo> getOpportunisticSubscriptions() {
- String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextFeature = null;
List<SubscriptionInfo> subInfoList = null;
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subInfoList = iSub.getOpportunisticSubscriptions(pkgForDebug);
+ subInfoList = iSub.getOpportunisticSubscriptions(contextPkg, contextFeature);
}
} catch (RemoteException ex) {
// ignore it
@@ -3031,7 +3065,8 @@
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
public @NonNull List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid) {
Preconditions.checkNotNull(groupUuid, "groupUuid can't be null");
- String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextFeature = null;
if (VDBG) {
logd("[getSubscriptionsInGroup]+ groupUuid:" + groupUuid);
}
@@ -3040,7 +3075,7 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getSubscriptionsInGroup(groupUuid, pkgForDebug);
+ result = iSub.getSubscriptionsInGroup(groupUuid, contextPkg, contextFeature);
} else {
if (!isSystemProcess()) {
throw new IllegalStateException("telephony service is null.");
@@ -3163,6 +3198,34 @@
}
/**
+ * Set uicc applications being enabled or disabled.
+ * The value will be remembered on the subscription and will be applied whenever it's present.
+ * If the subscription in currently present, it will also apply the setting to modem
+ * immediately.
+ *
+ * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+ *
+ * @param enabled whether uicc applications are enabled or disabled.
+ * @param subscriptionId which subscription to operate on.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public void setUiccApplicationsEnabled(boolean enabled, int subscriptionId) {
+ if (VDBG) {
+ logd("setUiccApplicationsEnabled subId= " + subscriptionId + " enable " + enabled);
+ }
+ try {
+ ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+ if (iSub != null) {
+ iSub.setUiccApplicationsEnabled(enabled, subscriptionId);
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+ }
+
+ /**
* Whether it's supported to disable / re-enable a subscription on a physical (non-euicc) SIM.
*
* Physical SIM refers non-euicc, or aka non-programmable SIM.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 85f2581..ef631b8 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -17,6 +17,8 @@
package android.telephony;
import static android.content.Context.TELECOM_SERVICE;
+import static android.provider.Telephony.Carriers.DPC_URI;
+import static android.provider.Telephony.Carriers.INVALID_APN_ID;
import static com.android.internal.util.Preconditions.checkNotNull;
@@ -34,16 +36,17 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
import android.app.ActivityThread;
import android.app.PendingIntent;
import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkStats;
import android.net.Uri;
@@ -70,11 +73,13 @@
import android.telecom.TelecomManager;
import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.CallState;
-import android.telephony.Annotation.DataState;
import android.telephony.Annotation.NetworkType;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
+import android.telephony.Annotation.UiccAppType;
import android.telephony.VisualVoicemailService.VisualVoicemailTask;
+import android.telephony.data.ApnSetting;
+import android.telephony.data.ApnSetting.MvnoType;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
import android.telephony.ims.ImsMmTelManager;
@@ -102,6 +107,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.SmsApplication;
+import com.android.telephony.Rlog;
import dalvik.system.VMRuntime;
@@ -190,11 +196,8 @@
NETWORK_SELECTION_MODE_MANUAL})
public @interface NetworkSelectionMode {}
- /** @hide */
public static final int NETWORK_SELECTION_MODE_UNKNOWN = 0;
- /** @hide */
public static final int NETWORK_SELECTION_MODE_AUTO = 1;
- /** @hide */
public static final int NETWORK_SELECTION_MODE_MANUAL = 2;
/** The otaspMode passed to PhoneStateListener#onOtaspChanged */
@@ -375,6 +378,10 @@
return ActivityThread.currentOpPackageName();
}
+ private String getFeatureId() {
+ return null;
+ }
+
private boolean isSystemProcess() {
return Process.myUid() == Process.SYSTEM_UID;
}
@@ -765,30 +772,6 @@
public static final String EXTRA_PRECISE_DISCONNECT_CAUSE = "precise_disconnect_cause";
/**
- * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
- * for an String containing the data APN type.
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getStringExtra(String name)}.
- *
- * @hide
- */
- public static final String EXTRA_DATA_APN_TYPE = PhoneConstants.DATA_APN_TYPE_KEY;
-
- /**
- * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
- * for an String containing the data APN.
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getStringExtra(String name)}.
- *
- * @hide
- */
- public static final String EXTRA_DATA_APN = PhoneConstants.DATA_APN_KEY;
-
- /**
* Broadcast intent action for letting the default dialer to know to show voicemail
* notification.
*
@@ -1450,25 +1433,6 @@
public static final String EXTRA_SIM_COMBINATION_NAMES =
"android.telephony.extra.SIM_COMBINATION_NAMES";
- /**
- * Broadcast Action: The time was set by the carrier (typically by the NITZ string).
- * This is a sticky broadcast.
- * The intent will have the following extra values:</p>
- * <ul>
- * <li><em>time</em> - The time as a long in UTC milliseconds.</li>
- * </ul>
- *
- * <p class="note">
- * Requires the READ_PHONE_STATE permission.
- *
- * <p class="note">This is a protected intent that can only be sent
- * by the system.
- *
- * @hide
- */
- @SystemApi
- public static final String ACTION_NETWORK_SET_TIME = "android.telephony.action.NETWORK_SET_TIME";
-
//
//
// Device Info
@@ -1507,7 +1471,8 @@
if (telephony == null) return null;
try {
- return telephony.getDeviceSoftwareVersionForSlot(slotIndex, getOpPackageName());
+ return telephony.getDeviceSoftwareVersionForSlot(slotIndex, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1548,7 +1513,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getDeviceId(mContext.getOpPackageName());
+ return telephony.getDeviceIdWithFeature(mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1592,7 +1558,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName());
+ return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1650,7 +1617,7 @@
if (telephony == null) return null;
try {
- return telephony.getImeiForSlot(slotIndex, getOpPackageName());
+ return telephony.getImeiForSlot(slotIndex, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1744,7 +1711,7 @@
if (telephony == null) return null;
try {
- String meid = telephony.getMeidForSlot(slotIndex, getOpPackageName());
+ String meid = telephony.getMeidForSlot(slotIndex, getOpPackageName(), getFeatureId());
if (TextUtils.isEmpty(meid)) {
Log.d(TAG, "getMeid: return null because MEID is not available");
return null;
@@ -1845,7 +1812,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- String nai = info.getNaiForSubscriber(subId, mContext.getOpPackageName());
+ String nai = info.getNaiForSubscriber(subId, mContext.getOpPackageName(),
+ null);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Rlog.v(TAG, "Nai = " + nai);
}
@@ -1878,13 +1846,9 @@
return null;
}
- Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName());
- if (bundle == null || bundle.isEmpty()) {
- Rlog.d(TAG, "getCellLocation returning null because CellLocation is unavailable");
- return null;
- }
-
- CellLocation cl = CellLocation.newFromBundle(bundle);
+ CellIdentity cellIdentity = telephony.getCellLocation(mContext.getOpPackageName(),
+ null);
+ CellLocation cl = cellIdentity.asCellLocation();
if (cl == null || cl.isEmpty()) {
Rlog.d(TAG, "getCellLocation returning null because CellLocation is empty or"
+ " phone type doesn't match CellLocation type");
@@ -1966,7 +1930,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getNeighboringCellInfo(mContext.getOpPackageName());
+ return telephony.getNeighboringCellInfo(mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1982,6 +1947,16 @@
public static final int PHONE_TYPE_CDMA = PhoneConstants.PHONE_TYPE_CDMA;
/** Phone is via SIP. */
public static final int PHONE_TYPE_SIP = PhoneConstants.PHONE_TYPE_SIP;
+ /** Phone is via IMS. */
+ public static final int PHONE_TYPE_IMS = PhoneConstants.PHONE_TYPE_IMS;
+
+ /**
+ * Phone is via Third Party.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int PHONE_TYPE_THIRD_PARTY = PhoneConstants.PHONE_TYPE_THIRD_PARTY;
/**
* Returns the current phone type.
@@ -2394,7 +2369,7 @@
ITelephony telephony = getITelephony();
if (telephony == null) return "";
return telephony.getNetworkCountryIsoForPhone(getPhoneId(),
- null /* no permission check */);
+ null /* no permission check */, null);
} catch (RemoteException ex) {
return "";
}
@@ -2434,7 +2409,8 @@
ITelephony telephony = getITelephony();
if (telephony == null) return "";
- return telephony.getNetworkCountryIsoForPhone(slotIndex, getOpPackageName());
+ return telephony.getNetworkCountryIsoForPhone(slotIndex, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return "";
}
@@ -2566,7 +2542,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName());
+ return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -2630,7 +2607,8 @@
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getDataNetworkTypeForSubscriber(subId, getOpPackageName());
+ return telephony.getDataNetworkTypeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -2666,7 +2644,8 @@
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getVoiceNetworkTypeForSubscriber(subId, getOpPackageName());
+ return telephony.getVoiceNetworkTypeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -2806,6 +2785,55 @@
}
}
+ /**
+ * Returns the bitmask for a given technology (network type)
+ * @param networkType for which bitmask is returned
+ * @return the network type bitmask
+ * {@hide}
+ */
+ public static @NetworkTypeBitMask long getBitMaskForNetworkType(@NetworkType int networkType) {
+ switch(networkType) {
+ case NETWORK_TYPE_GSM:
+ return NETWORK_TYPE_BITMASK_GSM;
+ case NETWORK_TYPE_GPRS:
+ return NETWORK_TYPE_BITMASK_GPRS;
+ case NETWORK_TYPE_EDGE:
+ return NETWORK_TYPE_BITMASK_EDGE;
+ case NETWORK_TYPE_CDMA:
+ return NETWORK_TYPE_BITMASK_CDMA;
+ case NETWORK_TYPE_1xRTT:
+ return NETWORK_TYPE_BITMASK_1xRTT;
+ case NETWORK_TYPE_EVDO_0:
+ return NETWORK_TYPE_BITMASK_EVDO_0;
+ case NETWORK_TYPE_EVDO_A:
+ return NETWORK_TYPE_BITMASK_EVDO_A;
+ case NETWORK_TYPE_EVDO_B:
+ return NETWORK_TYPE_BITMASK_EVDO_B;
+ case NETWORK_TYPE_EHRPD:
+ return NETWORK_TYPE_BITMASK_EHRPD;
+ case NETWORK_TYPE_HSUPA:
+ return NETWORK_TYPE_BITMASK_HSUPA;
+ case NETWORK_TYPE_HSDPA:
+ return NETWORK_TYPE_BITMASK_HSDPA;
+ case NETWORK_TYPE_HSPA:
+ return NETWORK_TYPE_BITMASK_HSPA;
+ case NETWORK_TYPE_HSPAP:
+ return NETWORK_TYPE_BITMASK_HSPAP;
+ case NETWORK_TYPE_UMTS:
+ return NETWORK_TYPE_BITMASK_UMTS;
+ case NETWORK_TYPE_TD_SCDMA:
+ return NETWORK_TYPE_BITMASK_TD_SCDMA;
+ case NETWORK_TYPE_LTE:
+ return NETWORK_TYPE_BITMASK_LTE;
+ case NETWORK_TYPE_LTE_CA:
+ return NETWORK_TYPE_BITMASK_LTE_CA;
+ case NETWORK_TYPE_NR:
+ return NETWORK_TYPE_BITMASK_NR;
+ default:
+ return NETWORK_TYPE_BITMASK_UNKNOWN;
+ }
+ }
+
//
//
// SIM Card
@@ -3460,7 +3488,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName());
+ return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3504,7 +3533,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
- return telephony.getLteOnCdmaModeForSubscriber(subId, getOpPackageName());
+ return telephony.getLteOnCdmaModeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// Assume no ICC card if remote exception which shouldn't happen
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
@@ -3732,7 +3762,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName());
+ return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3899,7 +3930,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getGroupIdLevel1ForSubscriber(getSubId(), mContext.getOpPackageName());
+ return info.getGroupIdLevel1ForSubscriber(getSubId(), mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3922,7 +3954,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName());
+ return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3972,7 +4005,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- number = telephony.getLine1NumberForDisplay(subId, mContext.getOpPackageName());
+ number = telephony.getLine1NumberForDisplay(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -3983,7 +4017,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName());
+ return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4062,7 +4097,7 @@
ITelephony telephony = getITelephony();
if (telephony != null)
alphaTag = telephony.getLine1AlphaTagForDisplay(subId,
- getOpPackageName());
+ getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4073,7 +4108,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getLine1AlphaTagForSubscriber(subId, getOpPackageName());
+ return info.getLine1AlphaTagForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4102,7 +4138,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.getMergedSubscriberIds(getSubId(), getOpPackageName());
+ return telephony.getMergedSubscriberIds(getSubId(), getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4157,7 +4194,7 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getMsisdnForSubscriber(subId, getOpPackageName());
+ return info.getMsisdnForSubscriber(subId, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4191,7 +4228,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getVoiceMailNumberForSubscriber(subId, getOpPackageName());
+ return info.getVoiceMailNumberForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4315,8 +4353,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony
- .getVisualVoicemailPackageName(mContext.getOpPackageName(), getSubId());
+ return telephony.getVisualVoicemailPackageName(mContext.getOpPackageName(),
+ getFeatureId(), getSubId());
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -4752,7 +4790,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return 0;
- return telephony.getVoiceMessageCountForSubscriber(subId, getOpPackageName());
+ return telephony.getVoiceMessageCountForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return 0;
} catch (NullPointerException ex) {
@@ -4788,7 +4827,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getVoiceMailAlphaTagForSubscriber(subId, getOpPackageName());
+ return info.getVoiceMailAlphaTagForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4878,7 +4918,9 @@
* not present or not loaded
* @hide
*/
- @UnsupportedAppUsage
+ @Nullable
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String[] getIsimImpu() {
try {
IPhoneSubInfo info = getSubscriberInfo();
@@ -5184,7 +5226,7 @@
} else if (listener.mSubId != null) {
subId = listener.mSubId;
}
- registry.listenForSubscriber(subId, getOpPackageName(),
+ registry.listenForSubscriber(subId, getOpPackageName(), getFeatureId(),
listener.callback, events, notifyNow);
} else {
Rlog.w(TAG, "telephony registry not ready.");
@@ -5214,7 +5256,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return -1;
- return telephony.getCdmaEriIconIndexForSubscriber(subId, getOpPackageName());
+ return telephony.getCdmaEriIconIndexForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -5249,7 +5292,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return -1;
- return telephony.getCdmaEriIconModeForSubscriber(subId, getOpPackageName());
+ return telephony.getCdmaEriIconModeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -5280,7 +5324,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getCdmaEriTextForSubscriber(subId, getOpPackageName());
+ return telephony.getCdmaEriTextForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// the phone process is restarting.
return null;
@@ -5372,8 +5417,7 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getAllCellInfo(
- getOpPackageName());
+ return telephony.getAllCellInfo(getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -5473,7 +5517,7 @@
Binder.restoreCallingIdentity(identity);
}
}
- }, getOpPackageName());
+ }, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
}
}
@@ -5524,7 +5568,7 @@
Binder.restoreCallingIdentity(identity);
}
}
- }, getOpPackageName(), workSource);
+ }, getOpPackageName(), getFeatureId(), workSource);
} catch (RemoteException ex) {
}
}
@@ -5681,7 +5725,10 @@
* @param AID Application id. See ETSI 102.221 and 101.220.
* @param p2 P2 parameter (described in ISO 7816-4).
* @return an IccOpenLogicalChannelResponse object.
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID, int p2) {
return iccOpenLogicalChannel(getSubId(), AID, p2);
}
@@ -5712,7 +5759,10 @@
* @param p2 P2 parameter (described in ISO 7816-4).
* @return an IccOpenLogicalChannelResponse object.
* @hide
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID, int p2) {
try {
ITelephony telephony = getITelephony();
@@ -5740,7 +5790,10 @@
* iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
* @hide
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
public boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel) {
@@ -5767,7 +5820,10 @@
* @param channel is the channel id to be closed as returned by a successful
* iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public boolean iccCloseLogicalChannel(int channel) {
return iccCloseLogicalChannel(getSubId(), channel);
}
@@ -5786,7 +5842,10 @@
* iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
* @hide
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public boolean iccCloseLogicalChannel(int subId, int channel) {
try {
ITelephony telephony = getITelephony();
@@ -5822,7 +5881,10 @@
* @return The APDU response from the ICC card with the status appended at the end, or null if
* there is an issue connecting to the Telephony service.
* @hide
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
@Nullable
@@ -5860,7 +5922,10 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at
* the end.
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public String iccTransmitApduLogicalChannel(int channel, int cla,
int instruction, int p1, int p2, int p3, String data) {
return iccTransmitApduLogicalChannel(getSubId(), channel, cla,
@@ -5889,7 +5954,10 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
* @hide
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
int instruction, int p1, int p2, int p3, String data) {
try {
@@ -5925,7 +5993,10 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
* @hide
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
@NonNull
@@ -5961,7 +6032,10 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at
* the end.
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public String iccTransmitApduBasicChannel(int cla,
int instruction, int p1, int p2, int p3, String data) {
return iccTransmitApduBasicChannel(getSubId(), cla,
@@ -5988,7 +6062,10 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
* @hide
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public String iccTransmitApduBasicChannel(int subId, int cla,
int instruction, int p1, int p2, int p3, String data) {
try {
@@ -6016,7 +6093,10 @@
* @param p3 P3 value of the APDU command.
* @param filePath
* @return The APDU response.
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
String filePath) {
return iccExchangeSimIO(getSubId(), fileID, command, p1, p2, p3, filePath);
@@ -6038,7 +6118,10 @@
* @param filePath
* @return The APDU response.
* @hide
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2,
int p3, String filePath) {
try {
@@ -6064,7 +6147,10 @@
* @return The APDU response from the ICC card in hexadecimal format
* with the last 4 bytes being the status word. If the command fails,
* returns an empty string.
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public String sendEnvelopeWithStatus(String content) {
return sendEnvelopeWithStatus(getSubId(), content);
}
@@ -6084,7 +6170,10 @@
* with the last 4 bytes being the status word. If the command fails,
* returns an empty string.
* @hide
+ * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
*/
+ // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
+ @Deprecated
public String sendEnvelopeWithStatus(int subId, String content) {
try {
ITelephony telephony = getITelephony();
@@ -6617,19 +6706,6 @@
}
}
- /**
- * UICC SIM Application Types
- * @hide
- */
- @IntDef(prefix = { "APPTYPE_" }, value = {
- APPTYPE_SIM,
- APPTYPE_USIM,
- APPTYPE_RUIM,
- APPTYPE_CSIM,
- APPTYPE_ISIM
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface UiccAppType{}
/** UICC application type is SIM */
public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
/** UICC application type is USIM */
@@ -6740,7 +6816,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getForbiddenPlmns(subId, appType, mContext.getOpPackageName());
+ return telephony.getForbiddenPlmns(subId, appType, mContext.getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -6774,7 +6851,7 @@
ITelephony telephony = getITelephony();
if (telephony == null) return -1;
return telephony.setForbiddenPlmns(
- getSubId(), APPTYPE_USIM, fplmns, getOpPackageName());
+ getSubId(), APPTYPE_USIM, fplmns, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
Rlog.e(TAG, "setForbiddenPlmns RemoteException: " + ex.getMessage());
} catch (NullPointerException ex) {
@@ -6795,7 +6872,7 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return new String[0];
- return telephony.getPcscfAddress(apnType, getOpPackageName());
+ return telephony.getPcscfAddress(apnType, getOpPackageName(), getFeatureId());
} catch (RemoteException e) {
return new String[0];
}
@@ -7306,7 +7383,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getCellNetworkScanResults(getSubId(), getOpPackageName());
+ return telephony.getCellNetworkScanResults(getSubId(), getOpPackageName(),
+ getFeatureId());
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getAvailableNetworks RemoteException", ex);
@@ -7361,7 +7439,7 @@
}
}
return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback,
- getOpPackageName());
+ getOpPackageName(), getFeatureId());
}
/**
@@ -7443,14 +7521,18 @@
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
* given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
-
- * @return the network selection mode.
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+ * READ_PRECISE_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
- * @hide
+ * @return the network selection mode.
*/
- @NetworkSelectionMode
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public int getNetworkSelectionMode() {
+ @SuppressAutoDoc // No support for carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE
+ })
+ public @NetworkSelectionMode int getNetworkSelectionMode() {
int mode = NETWORK_SELECTION_MODE_UNKNOWN;
try {
ITelephony telephony = getITelephony();
@@ -7573,12 +7655,12 @@
/**
* Check whether DUN APN is required for tethering.
* <p>
- * Requires Permission: READ_PRIVILEGED_PHONE_STATE.
+ * Requires Permission: MODIFY_PHONE_STATE.
*
* @return {@code true} if DUN APN is required for tethering.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
public boolean isTetheringApnRequired() {
return isTetheringApnRequired(getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
@@ -8033,7 +8115,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.isRadioOn(getOpPackageName());
+ return telephony.isRadioOnWithFeature(getOpPackageName(), getFeatureId());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isRadioOn", e);
}
@@ -8047,9 +8129,9 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.supplyPin(pin);
+ return telephony.supplyPinForSubscriber(getSubId(), pin);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#supplyPin", e);
+ Log.e(TAG, "Error calling ITelephony#supplyPinForSubscriber", e);
}
return false;
}
@@ -8061,9 +8143,9 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.supplyPuk(puk, pin);
+ return telephony.supplyPukForSubscriber(getSubId(), puk, pin);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#supplyPuk", e);
+ Log.e(TAG, "Error calling ITelephony#supplyPukForSubscriber", e);
}
return false;
}
@@ -8075,9 +8157,9 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.supplyPinReportResult(pin);
+ return telephony.supplyPinReportResultForSubscriber(getSubId(), pin);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#supplyPinReportResult", e);
+ Log.e(TAG, "Error calling ITelephony#supplyPinReportResultForSubscriber", e);
}
return new int[0];
}
@@ -8089,7 +8171,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.supplyPukReportResult(puk, pin);
+ return telephony.supplyPukReportResultForSubscriber(getSubId(), puk, pin);
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#]", e);
}
@@ -8346,7 +8428,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getRadioPowerState(getSlotIndex(), mContext.getOpPackageName());
+ return telephony.getRadioPowerState(getSlotIndex(), mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -8704,7 +8787,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.isVideoCallingEnabled(getOpPackageName());
+ return telephony.isVideoCallingEnabled(getOpPackageName(), getFeatureId());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isVideoCallingEnabled", e);
}
@@ -8720,7 +8803,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.canChangeDtmfToneLength(mSubId, getOpPackageName());
+ return telephony.canChangeDtmfToneLength(mSubId, getOpPackageName(),
+ getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#canChangeDtmfToneLength", e);
@@ -8739,7 +8823,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.isWorldPhone(mSubId, getOpPackageName());
+ return telephony.isWorldPhone(mSubId, getOpPackageName(), getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isWorldPhone", e);
@@ -9020,15 +9104,20 @@
}
/**
- * Requested state of SIM
- *
- * CARD_POWER_DOWN
* Powers down the SIM. SIM must be up prior.
- *
- * CARD_POWER_UP
+ * @hide
+ */
+ @SystemApi
+ public static final int CARD_POWER_DOWN = 0;
+
+ /**
* Powers up the SIM normally. SIM must be down prior.
- *
- * CARD_POWER_UP_PASS_THROUGH
+ * @hide
+ */
+ @SystemApi
+ public static final int CARD_POWER_UP = 1;
+
+ /**
* Powers up the SIM in PASS_THROUGH mode. SIM must be down prior.
* When SIM is powered up in PASS_THOUGH mode, the modem does not send
* any command to it (for example SELECT of MF, or TERMINAL CAPABILITY),
@@ -9041,12 +9130,9 @@
* is activated, and normal behavior occurs at the next SIM initialization,
* unless PASS_THROUGH mode is requested again. Hence, the last power-up mode
* is NOT persistent across boots. On reboot, SIM will power up normally.
+ * @hide
*/
- /** @hide */
- public static final int CARD_POWER_DOWN = 0;
- /** @hide */
- public static final int CARD_POWER_UP = 1;
- /** @hide */
+ @SystemApi
public static final int CARD_POWER_UP_PASS_THROUGH = 2;
/**
@@ -9465,7 +9551,7 @@
ITelephony service = getITelephony();
if (service != null) {
retval = service.getSubIdForPhoneAccountHandle(
- phoneAccountHandle, mContext.getOpPackageName());
+ phoneAccountHandle, mContext.getOpPackageName(), null);
}
} catch (RemoteException ex) {
Log.e(TAG, "getSubscriptionId RemoteException", ex);
@@ -9603,7 +9689,8 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getServiceStateForSubscriber(subId, getOpPackageName());
+ return service.getServiceStateForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getServiceStateForSubscriber", e);
@@ -10198,6 +10285,7 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
*
* @param enabled control enable or disable carrier data.
+ * @see #resetAllCarrierActions()
* @hide
*/
@SystemApi
@@ -10224,6 +10312,7 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
*
* @param enabled control enable or disable radio.
+ * @see #resetAllCarrierActions()
* @hide
*/
@SystemApi
@@ -10250,6 +10339,7 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
*
* @param report control start/stop reporting network status.
+ * @see #resetAllCarrierActions()
* @hide
*/
@SystemApi
@@ -10343,7 +10433,7 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getClientRequestStats(getOpPackageName(), subId);
+ return service.getClientRequestStats(getOpPackageName(), getFeatureId(), subId);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getClientRequestStats", e);
@@ -10396,7 +10486,8 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isManualNetworkSelectionAllowed() {
try {
ITelephony telephony = getITelephony();
@@ -10631,7 +10722,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getNumberOfModemsWithSimultaneousDataConnections(
- getSubId(), getOpPackageName());
+ getSubId(), getOpPackageName(), getFeatureId());
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -10987,7 +11078,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getEmergencyNumberList(mContext.getOpPackageName());
+ return telephony.getEmergencyNumberList(mContext.getOpPackageName(),
+ null);
} else {
throw new IllegalStateException("telephony service is null.");
}
@@ -11042,7 +11134,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
emergencyNumberList = telephony.getEmergencyNumberList(
- mContext.getOpPackageName());
+ mContext.getOpPackageName(), null);
if (emergencyNumberList != null) {
for (Integer subscriptionId : emergencyNumberList.keySet()) {
List<EmergencyNumber> numberList = emergencyNumberList.get(subscriptionId);
@@ -11348,12 +11440,14 @@
android.Manifest.permission.READ_PHONE_STATE
})
public int getPreferredOpportunisticDataSubscription() {
- String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String packageName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String featureId = null;
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
try {
IOns iOpportunisticNetworkService = getIOns();
if (iOpportunisticNetworkService != null) {
- subId = iOpportunisticNetworkService.getPreferredDataSubscriptionId(pkgForDebug);
+ subId = iOpportunisticNetworkService.getPreferredDataSubscriptionId(
+ packageName, featureId);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getPreferredDataSubscriptionId RemoteException", ex);
@@ -11480,7 +11574,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.isModemEnabledForSlot(slotIndex, mContext.getOpPackageName());
+ return telephony.isModemEnabledForSlot(slotIndex, mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
Log.e(TAG, "enableModem RemoteException", ex);
@@ -11585,7 +11680,7 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.isMultiSimSupported(getOpPackageName());
+ return service.isMultiSimSupported(getOpPackageName(), getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "isMultiSimSupported RemoteException", e);
@@ -11637,7 +11732,7 @@
ITelephony service = getITelephony();
if (service != null) {
return service.doesSwitchMultiSimConfigTriggerReboot(getSubId(),
- getOpPackageName());
+ getOpPackageName(), getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "doesSwitchMultiSimConfigTriggerReboot RemoteException", e);
@@ -11671,6 +11766,114 @@
}
/**
+ * Get the calling application status about carrier privileges for the subscription created
+ * in TelephonyManager. Used by Telephony Module for permission checking.
+ *
+ * @param uid Uid to check.
+ * @return any value of {@link #CARRIER_PRIVILEGE_STATUS_HAS_ACCESS},
+ * {@link #CARRIER_PRIVILEGE_STATUS_NO_ACCESS},
+ * {@link #CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED}, or
+ * {@link #CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES}
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public int getCarrierPrivilegeStatus(int uid) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getCarrierPrivilegeStatusForUid(getSubId(), uid);
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "getCarrierPrivilegeStatus RemoteException", ex);
+ }
+ return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
+ }
+
+ /**
+ * Returns a list of APNs set as overrides by the device policy manager via
+ * {@link #addDevicePolicyOverrideApn}.
+ * This method must only be called from the system or phone processes.
+ *
+ * @param context Context to use.
+ * @return {@link List} of APNs that have been set as overrides.
+ * @throws {@link SecurityException} if the caller is not the system or phone process.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ // TODO: add new permission tag indicating that this is system-only.
+ public @NonNull List<ApnSetting> getDevicePolicyOverrideApns(@NonNull Context context) {
+ try (Cursor cursor = context.getContentResolver().query(DPC_URI, null, null, null, null)) {
+ if (cursor == null) {
+ return Collections.emptyList();
+ }
+ List<ApnSetting> apnList = new ArrayList<ApnSetting>();
+ cursor.moveToPosition(-1);
+ while (cursor.moveToNext()) {
+ ApnSetting apn = ApnSetting.makeApnSetting(cursor);
+ apnList.add(apn);
+ }
+ return apnList;
+ }
+ }
+
+ /**
+ * Used by the device policy manager to add a new override APN.
+ * This method must only be called from the system or phone processes.
+ *
+ * @param context Context to use.
+ * @param apnSetting The {@link ApnSetting} describing the new APN.
+ * @return An integer, corresponding to a primary key in a database, that allows the caller to
+ * modify the APN in the future via {@link #modifyDevicePolicyOverrideApn}, or
+ * {@link android.provider.Telephony.Carriers.INVALID_APN_ID} if the override operation
+ * failed.
+ * @throws {@link SecurityException} if the caller is not the system or phone process.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ // TODO: add new permission tag indicating that this is system-only.
+ public int addDevicePolicyOverrideApn(@NonNull Context context,
+ @NonNull ApnSetting apnSetting) {
+ Uri resultUri = context.getContentResolver().insert(DPC_URI, apnSetting.toContentValues());
+
+ int resultId = INVALID_APN_ID;
+ if (resultUri != null) {
+ try {
+ resultId = Integer.parseInt(resultUri.getLastPathSegment());
+ } catch (NumberFormatException e) {
+ Rlog.e(TAG, "Failed to parse inserted override APN id: "
+ + resultUri.getLastPathSegment());
+ }
+ }
+ return resultId;
+ }
+
+ /**
+ * Used by the device policy manager to modify an override APN.
+ * This method must only be called from the system or phone processes.
+ *
+ * @param context Context to use.
+ * @param apnId The integer key of the APN to modify, as returned by
+ * {@link #addDevicePolicyOverrideApn}
+ * @param apnSetting The {@link ApnSetting} describing the updated APN.
+ * @return {@code true} if successful, {@code false} otherwise.
+ * @throws {@link SecurityException} if the caller is not the system or phone process.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ // TODO: add new permission tag indicating that this is system-only.
+ public boolean modifyDevicePolicyOverrideApn(@NonNull Context context, int apnId,
+ @NonNull ApnSetting apnSetting) {
+ return context.getContentResolver().update(
+ Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
+ apnSetting.toContentValues(), null, null) > 0;
+ }
+
+ /**
* Return whether data is enabled for certain APN type. This will tell if framework will accept
* corresponding network requests on a subId.
*
@@ -11728,6 +11931,37 @@
}
/**
+ * Verifies whether the input MCC/MNC and MVNO correspond to the current carrier.
+ *
+ * @param mccmnc the carrier's mccmnc that you want to match
+ * @param mvnoType the mvnoType that defined in {@link ApnSetting}
+ * @param mvnoMatchData the MVNO match data
+ * @return {@code true} if input mccmnc and mvno matches with data from sim operator.
+ * {@code false} otherwise.
+ *
+ * {@hide}
+ */
+ @SystemApi
+ public boolean isCurrentSimOperator(@NonNull String mccmnc, @MvnoType int mvnoType,
+ @Nullable String mvnoMatchData) {
+ try {
+ if (!mccmnc.equals(getSimOperator())) {
+ Log.d(TAG, "The mccmnc does not match");
+ return false;
+ }
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.isMvnoMatched(getSubId(), mvnoType, mvnoMatchData);
+ }
+ } catch (RemoteException ex) {
+ if (!isSystemProcess()) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+ return false;
+ }
+
+ /**
* Set allowing mobile data during voice call.
*
* @param allow {@code true} if allowing using data during voice call, {@code false} if
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 9ff8515..1651c81 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -16,6 +16,8 @@
package android.telephony;
+import com.android.telephony.Rlog;
+
import static com.android.internal.util.Preconditions.checkNotNull;
import android.content.Context;
@@ -200,13 +202,14 @@
*/
public NetworkScan requestNetworkScan(int subId,
NetworkScanRequest request, Executor executor, NetworkScanCallback callback,
- String callingPackage) {
+ String callingPackage, String callingFeatureId) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
synchronized (mScanInfo) {
int scanId = telephony.requestNetworkScan(
- subId, request, mMessenger, new Binder(), callingPackage);
+ subId, request, mMessenger, new Binder(), callingPackage,
+ callingFeatureId);
if (scanId == INVALID_SCAN_ID) {
Rlog.e(TAG, "Failed to initiate network scan");
return null;
diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java
index 93ccba1..81a09c6 100644
--- a/telephony/java/android/telephony/UiccAccessRule.java
+++ b/telephony/java/android/telephony/UiccAccessRule.java
@@ -15,6 +15,8 @@
*/
package android.telephony;
+import com.android.telephony.Rlog;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
diff --git a/telephony/java/android/telephony/VoLteServiceState.java b/telephony/java/android/telephony/VoLteServiceState.java
index f65c7b0..6b15443 100644
--- a/telephony/java/android/telephony/VoLteServiceState.java
+++ b/telephony/java/android/telephony/VoLteServiceState.java
@@ -16,12 +16,12 @@
package android.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+import com.android.telephony.Rlog;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
/**
* Contains LTE network state related information.
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
index 45b1e47..9bc39a0 100644
--- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -16,7 +16,7 @@
package android.telephony.cdma;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.telephony.CellLocation;
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 034fc22..fab1bf2 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -28,7 +28,7 @@
import android.provider.Telephony.Carriers;
import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.NetworkType;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -1056,6 +1056,11 @@
}
/** @hide */
+ public boolean isEmergencyApn() {
+ return hasApnType(TYPE_EMERGENCY);
+ }
+
+ /** @hide */
public boolean canHandleType(@ApnType int type) {
if (!mCarrierEnabled) {
return false;
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 372bdf1..bff12b6 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -31,7 +31,7 @@
import android.os.Message;
import android.os.RemoteException;
import android.telephony.AccessNetworkConstants;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index 11dc78a..d33d3f9 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -22,7 +22,7 @@
import android.annotation.SystemApi;
import android.net.LinkProperties;
import android.os.RemoteException;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.telephony.data.DataService.DataServiceProvider;
import java.lang.annotation.Retention;
diff --git a/telephony/java/android/telephony/data/QualifiedNetworksService.java b/telephony/java/android/telephony/data/QualifiedNetworksService.java
index e793979..8220b16 100644
--- a/telephony/java/android/telephony/data/QualifiedNetworksService.java
+++ b/telephony/java/android/telephony/data/QualifiedNetworksService.java
@@ -28,7 +28,7 @@
import android.os.RemoteException;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.Annotation.ApnType;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index 1666265..cd3fc95 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -25,7 +25,7 @@
import android.os.Parcelable;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
index cb27f64..23d46ba 100644
--- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java
+++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
@@ -17,17 +17,18 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.UiccAccessRule;
+
+import com.android.internal.util.Preconditions;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import com.android.internal.util.Preconditions;
-
/**
* Information about a subscription which is downloadable to an eUICC using
* {@link EuiccManager#downloadSubscription(DownloadableSubscription, boolean, PendingIntent).
diff --git a/telephony/java/android/telephony/euicc/EuiccInfo.java b/telephony/java/android/telephony/euicc/EuiccInfo.java
index 91ebb6c..467d268 100644
--- a/telephony/java/android/telephony/euicc/EuiccInfo.java
+++ b/telephony/java/android/telephony/euicc/EuiccInfo.java
@@ -16,7 +16,7 @@
package android.telephony.euicc;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java
index d6780ce..30cea0e 100644
--- a/telephony/java/android/telephony/gsm/GsmCellLocation.java
+++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java
@@ -16,7 +16,7 @@
package android.telephony.gsm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.telephony.CellLocation;
diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index 9f09d7a..d53a2e6 100644
--- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 87e5391..a7d553b 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -18,9 +18,10 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -40,10 +41,11 @@
import java.util.List;
/**
- * Parcelable object to handle IMS call profile.
- * It is created from GSMA IR.92/IR.94, 3GPP TS 24.229/TS 26.114/TS26.111.
- * It provides the service and call type, the additional information related to the call.
- *
+ * A Parcelable object to handle the IMS call profile, which provides the service, call type, and
+ * additional information related to the call.
+ * <p>
+ * See the following specifications for more information about this class: GSMA IR.92/IR.94,
+ * 3GPP TS 24.229/TS 26.114/TS26.111.
* @hide
*/
@SystemApi
@@ -151,12 +153,13 @@
*/
public static final String EXTRA_CONFERENCE_AVAIL = "conference_avail";
- // Extra string for internal use only. OEMs should not use
- // this for packing extras.
/**
+ * Extra key used to store a Bundle containing proprietary extras to send to the ImsService.
+ * Use {@link #getProprietaryCallExtras()} instead.
* @hide
*/
- public static final String EXTRA_OEM_EXTRAS = "OemCallExtras";
+ @TestApi
+ public static final String EXTRA_OEM_EXTRAS = "android.telephony.ims.extra.OEM_EXTRAS";
/**
* Rule for originating identity (number) presentation, MO/MT.
@@ -291,15 +294,30 @@
* updateImsCallRatFromExtras(Bundle)} to determine whether to set the
* {@link android.telecom.TelecomManager#EXTRA_CALL_NETWORK_TYPE} extra value and
* {@link android.telecom.Connection#PROPERTY_WIFI} property on a connection.
+ * @deprecated the constants associated with this extra are hidden, instead use
+ * {@link #EXTRA_CALL_NETWORK_TYPE}.
*/
+ @Deprecated
public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
/**
+ * Extra key with an {@code int} value which can be set in {@link #setCallExtraInt(String, int)}
+ * to indicate the network type used for a call.
+ * <p>
+ * Valid values are defined by {@code TelephonyManager.NETWORK_TYPE_*} constants. An example may
+ * be {@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE}.
+ */
+ public static final String EXTRA_CALL_NETWORK_TYPE =
+ "android.telephony.ims.extra.CALL_NETWORK_TYPE";
+
+ /**
* Similar to {@link #EXTRA_CALL_RAT_TYPE}, except with a lowercase 'c'. Used to ensure
* compatibility with modems that are non-compliant with the {@link #EXTRA_CALL_RAT_TYPE}
* extra key. Should be removed when the non-compliant modems are fixed.
* @hide
+ * @deprecated Use {@link #EXTRA_CALL_NETWORK_TYPE} instead.
*/
+ @Deprecated
public static final String EXTRA_CALL_RAT_TYPE_ALT = "callRadioTech";
/** @hide */
@@ -679,6 +697,18 @@
return mCallExtras;
}
+ /**
+ * Get the proprietary extras set for this ImsCallProfile.
+ * @return A {@link Bundle} containing proprietary call extras that were not set by the
+ * platform.
+ */
+ public @Nullable Bundle getProprietaryCallExtras() {
+ if (mCallExtras == null) {
+ return null;
+ }
+ return mCallExtras.getBundle(EXTRA_OEM_EXTRAS);
+ }
+
public ImsStreamMediaProfile getMediaProfile() {
return mMediaProfile;
}
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index 5adc99e..1b583fd 100644
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -25,8 +25,6 @@
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsVideoCallProvider;
-import java.util.Objects;
-
/**
* Provides the call initiation/termination, and media exchange between two IMS endpoints.
* It directly communicates with IMS service which implements the IMS protocol behavior.
@@ -346,7 +344,7 @@
}
/**
- * Called when an {@link ImsCallSession} may handover from one radio technology to another.
+ * Called when an {@link ImsCallSession} may handover from one network type to another.
* For example, the session may handover from WIFI to LTE if conditions are right.
* <p>
* If handover is attempted,
@@ -355,24 +353,24 @@
* called to indicate the success or failure of the handover.
*
* @param session IMS session object
- * @param srcAccessTech original access technology
- * @param targetAccessTech new access technology
+ * @param srcNetworkType original network type
+ * @param targetNetworkType new network type
*/
- public void callSessionMayHandover(ImsCallSession session, int srcAccessTech,
- int targetAccessTech) {
+ public void callSessionMayHandover(ImsCallSession session, int srcNetworkType,
+ int targetNetworkType) {
// no-op
}
/**
- * Called when session access technology changes
+ * Called when session network type changes
*
* @param session IMS session object
- * @param srcAccessTech original access technology
- * @param targetAccessTech new access technology
+ * @param srcNetworkType original network type
+ * @param targetNetworkType new network type
* @param reasonInfo
*/
public void callSessionHandover(ImsCallSession session,
- int srcAccessTech, int targetAccessTech,
+ int srcNetworkType, int targetNetworkType,
ImsReasonInfo reasonInfo) {
// no-op
}
@@ -381,12 +379,12 @@
* Called when session access technology change fails
*
* @param session IMS session object
- * @param srcAccessTech original access technology
- * @param targetAccessTech new access technology
+ * @param srcNetworkType original access technology
+ * @param targetNetworkType new access technology
* @param reasonInfo handover failure reason
*/
public void callSessionHandoverFailed(ImsCallSession session,
- int srcAccessTech, int targetAccessTech,
+ int srcNetworkType, int targetNetworkType,
ImsReasonInfo reasonInfo) {
// no-op
}
@@ -1303,20 +1301,19 @@
/**
* Notifies of a case where a {@link ImsCallSession} may
* potentially handover from one radio technology to another.
- * @param srcAccessTech The source radio access technology; one of the access technology
- * constants defined in {@link android.telephony.ServiceState}. For
- * example
- * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
- * @param targetAccessTech The target radio access technology; one of the access technology
- * constants defined in {@link android.telephony.ServiceState}. For
- * example
- * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
+ * @param srcNetworkType The source network type; one of the network type constants defined
+ * in {@link android.telephony.TelephonyManager}. For example
+ * {@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE}.
+ * @param targetNetworkType The target radio access technology; one of the network type
+ * constants defined in {@link android.telephony.TelephonyManager}.
+ * For example
+ * {@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE}.
*/
@Override
- public void callSessionMayHandover(int srcAccessTech, int targetAccessTech) {
+ public void callSessionMayHandover(int srcNetworkType, int targetNetworkType) {
if (mListener != null) {
- mListener.callSessionMayHandover(ImsCallSession.this, srcAccessTech,
- targetAccessTech);
+ mListener.callSessionMayHandover(ImsCallSession.this, srcNetworkType,
+ targetNetworkType);
}
}
@@ -1324,11 +1321,11 @@
* Notifies of handover information for this call
*/
@Override
- public void callSessionHandover(int srcAccessTech, int targetAccessTech,
+ public void callSessionHandover(int srcNetworkType, int targetNetworkType,
ImsReasonInfo reasonInfo) {
if (mListener != null) {
- mListener.callSessionHandover(ImsCallSession.this, srcAccessTech,
- targetAccessTech, reasonInfo);
+ mListener.callSessionHandover(ImsCallSession.this, srcNetworkType,
+ targetNetworkType, reasonInfo);
}
}
@@ -1336,11 +1333,11 @@
* Notifies of handover failure info for this call
*/
@Override
- public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
+ public void callSessionHandoverFailed(int srcNetworkType, int targetNetworkType,
ImsReasonInfo reasonInfo) {
if (mListener != null) {
- mListener.callSessionHandoverFailed(ImsCallSession.this, srcAccessTech,
- targetAccessTech, reasonInfo);
+ mListener.callSessionHandoverFailed(ImsCallSession.this, srcNetworkType,
+ targetNetworkType, reasonInfo);
}
}
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
index e11886f..025721c 100644
--- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -17,10 +17,13 @@
package android.telephony.ims;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.os.RemoteException;
+import android.telephony.Annotation;
import android.telephony.CallQuality;
+import android.telephony.ServiceState;
import android.telephony.ims.aidl.IImsCallSessionListener;
import android.telephony.ims.stub.ImsCallSessionImplBase;
@@ -476,11 +479,27 @@
* @param targetAccessTech The target radio access technology; one of the access technology
* constants defined in {@link android.telephony.ServiceState}. For example
* {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE}.
+ * @deprecated Uses hidden constants for radio access technology, use
+ * {@link #onMayHandover(int, int)} instead.
*/
- public void callSessionMayHandover(int srcAccessTech, int targetAccessTech)
- {
+ @Deprecated
+ public void callSessionMayHandover(int srcAccessTech, int targetAccessTech) {
+ // Use new API internally.
+ onMayHandover(ServiceState.rilRadioTechnologyToNetworkType(srcAccessTech),
+ ServiceState.rilRadioTechnologyToNetworkType(targetAccessTech));
+ }
+
+ /**
+ * Notify the framework that the associated {@link ImsCallSession} may handover from one network
+ * type to another.
+ *
+ * @param srcNetworkType The source network type.
+ * @param targetNetworkType The target network type.
+ */
+ public void onMayHandover(@Annotation.NetworkType int srcNetworkType,
+ @Annotation.NetworkType int targetNetworkType) {
try {
- mListener.callSessionMayHandover(srcAccessTech, targetAccessTech);
+ mListener.callSessionMayHandover(srcNetworkType, targetNetworkType);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -494,11 +513,29 @@
* @param targetAccessTech new access technology, defined in
* {@link android.telephony.ServiceState}.
* @param reasonInfo The {@link ImsReasonInfo} associated with this handover.
+ * @deprecated Uses hidden radio access technology constants, use
+ * {@link #onHandover(int, int, ImsReasonInfo)} instead.
*/
+ @Deprecated
public void callSessionHandover(int srcAccessTech, int targetAccessTech,
ImsReasonInfo reasonInfo) {
+ // Use new API internally.
+ onHandover(ServiceState.rilRadioTechnologyToNetworkType(srcAccessTech),
+ ServiceState.rilRadioTechnologyToNetworkType(targetAccessTech), reasonInfo);
+ }
+
+ /**
+ * Notify the framework that the associated {@link ImsCallSession} has handed over from one
+ * network type to another.
+ *
+ * @param srcNetworkType original network type.
+ * @param targetNetworkType target network type after handover..
+ * @param reasonInfo An optional {@link ImsReasonInfo} associated with this handover.
+ */
+ public void onHandover(@Annotation.NetworkType int srcNetworkType,
+ @Annotation.NetworkType int targetNetworkType, @Nullable ImsReasonInfo reasonInfo) {
try {
- mListener.callSessionHandover(srcAccessTech, targetAccessTech, reasonInfo);
+ mListener.callSessionHandover(srcNetworkType, targetNetworkType, reasonInfo);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -510,11 +547,28 @@
* @param srcAccessTech original access technology
* @param targetAccessTech new access technology
* @param reasonInfo An {@link ImsReasonInfo} detailing the reason for the failure.
+ * @deprecated Uses hidden radio access technology constants, use
+ * {@link #onHandoverFailed(int, int, ImsReasonInfo)} instead
*/
+ @Deprecated
public void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
ImsReasonInfo reasonInfo) {
+ // Use new API internally.
+ onHandoverFailed(ServiceState.rilRadioTechnologyToNetworkType(srcAccessTech),
+ ServiceState.rilRadioTechnologyToNetworkType(targetAccessTech), reasonInfo);
+ }
+
+ /**
+ * The IMS call session's access technology change has failed..
+ *
+ * @param srcNetworkType original network type.
+ * @param targetNetworkType target network type that the handover failed for.
+ * @param reasonInfo An {@link ImsReasonInfo} detailing the reason for the failure.
+ */
+ public void onHandoverFailed(@Annotation.NetworkType int srcNetworkType,
+ @Annotation.NetworkType int targetNetworkType, @NonNull ImsReasonInfo reasonInfo) {
try {
- mListener.callSessionHandoverFailed(srcAccessTech, targetAccessTech, reasonInfo);
+ mListener.callSessionHandoverFailed(srcNetworkType, targetNetworkType, reasonInfo);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
diff --git a/telephony/java/android/telephony/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java
index 8d2049b..abfee61 100644
--- a/telephony/java/android/telephony/ims/ImsConferenceState.java
+++ b/telephony/java/android/telephony/ims/ImsConferenceState.java
@@ -24,7 +24,7 @@
import android.os.Parcelable;
import android.telecom.Call;
import android.telecom.Connection;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.util.Log;
import java.util.HashMap;
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
index 39af2e7..cb3f0f9 100644
--- a/telephony/java/android/telephony/ims/ImsException.java
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -30,10 +30,7 @@
/**
* This class defines an IMS-related exception that has been thrown while interacting with a
* device or carrier provided ImsService implementation.
- * @hide
*/
-@SystemApi
-@TestApi
public final class ImsException extends Exception {
/**
@@ -83,7 +80,10 @@
/**
* A new {@link ImsException} with an unspecified {@link ImsErrorCode} code.
* @param message an optional message to detail the error condition more specifically.
+ * @hide
*/
+ @SystemApi
+ @TestApi
public ImsException(@Nullable String message) {
super(getMessage(message, CODE_ERROR_UNSPECIFIED));
}
@@ -91,7 +91,10 @@
/**
* A new {@link ImsException} that includes an {@link ImsErrorCode} error code.
* @param message an optional message to detail the error condition more specifically.
+ * @hide
*/
+ @SystemApi
+ @TestApi
public ImsException(@Nullable String message, @ImsErrorCode int code) {
super(getMessage(message, code));
mCode = code;
@@ -102,7 +105,10 @@
* {@link Throwable} that contains the original error that was thrown to lead to this Exception.
* @param message an optional message to detail the error condition more specifically.
* @param cause the {@link Throwable} that caused this {@link ImsException} to be created.
+ * @hide
*/
+ @SystemApi
+ @TestApi
public ImsException(@Nullable String message, @ImsErrorCode int code,
@Nullable Throwable cause) {
super(getMessage(message, code), cause);
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index dcb9c9d..136a83e 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -24,7 +24,7 @@
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 5fd0af5..c66672f 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -23,6 +23,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressAutoDoc;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.Context;
@@ -56,10 +58,7 @@
* associated subscription.
*
* @see #createForSubscriptionId(int)
- * @hide
*/
-@SystemApi
-@TestApi
public class ImsMmTelManager implements RegistrationManager {
/**
@@ -94,9 +93,11 @@
* @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback)
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
* @deprecated Use {@link RegistrationManager.RegistrationCallback} instead.
+ * @hide
*/
// Do not add to this class, add to RegistrationManager.RegistrationCallback instead.
@Deprecated
+ @SystemApi @TestApi
public static class RegistrationCallback extends RegistrationManager.RegistrationCallback {
/**
@@ -141,7 +142,7 @@
/**
* Receives IMS capability status updates from the ImsService. This information is also
- * available via the {@link #isAvailable(int, int)} method below.
+ * available via the {@see #isAvailable(int, int)} method below.
*
* @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback)
* @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
@@ -190,7 +191,7 @@
* If unavailable, the feature is not able to support the unavailable capability at this
* time.
*
- * This information can also be queried using the {@link #isAvailable(int, int)} API.
+ * This information can also be queried using the {@see #isAvailable(int, int)} API.
*
* @param capabilities The new availability of the capabilities.
*/
@@ -218,8 +219,20 @@
*
* @param subId The ID of the subscription that this ImsMmTelManager will use.
* @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+ * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges
+ * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
+ *
* @throws IllegalArgumentException if the subscription is invalid.
+ *
*/
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE
+ })
+ @SuppressLint("ManagerLookup")
public static @NonNull ImsMmTelManager createForSubscriptionId(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid subscription ID");
@@ -258,8 +271,10 @@
* reason.
* @deprecated Use {@link RegistrationManager#registerImsRegistrationCallback(Executor,
* RegistrationManager.RegistrationCallback)} instead.
+ * @hide
*/
@Deprecated
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull RegistrationCallback c) throws ImsException {
@@ -284,9 +299,20 @@
}
}
- /**{@inheritDoc}*/
+ /**
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+ * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges
+ * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
+ *
+ * {@inheritDoc}
+ *
+ */
@Override
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull RegistrationManager.RegistrationCallback c) throws ImsException {
if (c == null) {
@@ -317,8 +343,10 @@
* @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
* @deprecated Use {@link #unregisterImsRegistrationCallback(
* RegistrationManager.RegistrationCallback)}.
+ * @hide
*/
@Deprecated
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) {
if (c == null) {
@@ -331,9 +359,20 @@
}
}
- /**{@inheritDoc}*/
+ /**
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+ * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges
+ * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
+ * Access by profile owners is deprecated and will be removed in a future release.
+ *
+ *{@inheritDoc}
+ */
@Override
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public void unregisterImsRegistrationCallback(
@NonNull RegistrationManager.RegistrationCallback c) {
if (c == null) {
@@ -346,9 +385,13 @@
}
}
- /**{@inheritDoc}*/
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
@Override
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SystemApi @TestApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
@NonNull @ImsRegistrationState Consumer<Integer> stateCallback) {
if (stateCallback == null) {
@@ -369,9 +412,19 @@
}
}
- /**{@inheritDoc}*/
+ /**
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+ * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges
+ * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
+ * Access by profile owners is deprecated and will be removed in a future release.
+ *
+ *{@inheritDoc}
+ */
@Override
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor,
@NonNull @AccessNetworkConstants.TransportType
Consumer<Integer> transportTypeCallback) {
@@ -397,12 +450,25 @@
/**
* Registers a {@link CapabilityCallback} with the system, which will provide MmTel service
* availability updates for the subscription specified in
- * {@link #createForSubscriptionId(int)}. The method {@link #isAvailable(int, int)}
+ * {@link #createForSubscriptionId(int)}. The method {@see #isAvailable(int, int)}
* can also be used to query this information at any time.
*
* Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
* subscription changed events and call
* {@link #unregisterMmTelCapabilityCallback(CapabilityCallback)} to clean up.
+ * <p>This API requires one of the following:
+ * <ul>
+ * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li>
+ * <li>If the caller is the device or profile owner, the caller holds the
+ * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li>
+ * <li>The caller has carrier privileges (see
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any
+ * active subscription.</li>
+ * <li>The caller is the default SMS app for the device.</li>
+ * </ul>
+ * <p>The profile owner is an app that owns a managed profile on the device; for more details
+ * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Access by profile owners is deprecated and will be removed in a future release.
*
* When the callback is registered, it will initiate the callback c to be called with the
* current capabilities.
@@ -418,7 +484,10 @@
* the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
* reason.
*/
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull CapabilityCallback c) throws ImsException {
if (c == null) {
@@ -450,10 +519,27 @@
* When the subscription associated with this callback is removed (SIM removed, ESIM swap,
* etc...), this callback will automatically be removed. If this method is called for an
* inactive subscription, it will result in a no-op.
+ * <p>This API requires one of the following:
+ * <ul>
+ * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li>
+ * <li>If the caller is the device or profile owner, the caller holds the
+ * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li>
+ * <li>The caller has carrier privileges (see
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any
+ * active subscription.</li>
+ * <li>The caller is the default SMS app for the device.</li>
+ * </ul>
+ * <p>The profile owner is an app that owns a managed profile on the device; for more details
+ * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Access by profile owners is deprecated and will be removed in a future release.
+ *
* @param c The MmTel {@link CapabilityCallback} to be removed.
* @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback)
*/
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
@@ -475,6 +561,19 @@
* <p>
* Note: If the carrier configuration for advanced calling is not editable or hidden, this
* method will always return the default value.
+ * <p>This API requires one of the following:
+ * <ul>
+ * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li>
+ * <li>If the caller is the device or profile owner, the caller holds the
+ * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li>
+ * <li>The caller has carrier privileges (see
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any
+ * active subscription.</li>
+ * <li>The caller is the default SMS app for the device.</li>
+ * </ul>
+ * <p>The profile owner is an app that owns a managed profile on the device; for more details
+ * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Access by profile owners is deprecated and will be removed in a future release.
*
* @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
* @see android.telephony.CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL
@@ -486,7 +585,10 @@
* active (SIM is not inserted, ESIM inactive) or invalid.
* @return true if the user's setting for advanced calling is enabled, false otherwise.
*/
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public boolean isAdvancedCallingSettingEnabled() {
try {
return getITelephony().isAdvancedCallingSettingEnabled(mSubId);
@@ -524,8 +626,10 @@
* @see #isAdvancedCallingSettingEnabled()
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
+ * @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ @SystemApi @TestApi
public void setAdvancedCallingSettingEnabled(boolean isEnabled) {
try {
getITelephony().setAdvancedCallingSettingEnabled(mSubId, isEnabled);
@@ -556,13 +660,15 @@
* {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}
* @param capability The IMS MmTel capability to query, can be one of the following:
* {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
- * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO,
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
* {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT},
* {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS}
* @return {@code true} if the MmTel IMS capability is capable for this subscription, false
* otherwise.
+ * @hide
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SystemApi @TestApi
public boolean isCapable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
try {
@@ -583,12 +689,14 @@
* {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}
* @param capability The IMS MmTel capability to query, can be one of the following:
* {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
- * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO,
+ * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
* {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT},
* {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS}
* @return {@code true} if the MmTel IMS capability is available for this subscription, false
* otherwise.
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isAvailable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
@@ -613,7 +721,9 @@
* capability is supported on this carrier network for the transport specified.
* @throws ImsException if the subscription is no longer valid or the IMS service is not
* available.
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@AccessNetworkConstants.TransportType int transportType,
@@ -642,12 +752,32 @@
/**
* The user's setting for whether or not they have enabled the "Video Calling" setting.
*
+ * <p>
+ * Note: If the carrier configuration for advanced calling is not editable or hidden, this
+ * method will always return the default value.
+ * <p>This API requires one of the following:
+ * <ul>
+ * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li>
+ * <li>If the caller is the device or profile owner, the caller holds the
+ * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li>
+ * <li>The caller has carrier privileges (see
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any
+ * active subscription.</li>
+ * <li>The caller is the default SMS app for the device.</li>
+ * </ul>
+ * <p>The profile owner is an app that owns a managed profile on the device; for more details
+ * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Access by profile owners is deprecated and will be removed in a future release.
+ *
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @return true if the user’s “Video Calling” setting is currently enabled.
* @see #setVtSettingEnabled(boolean)
*/
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
public boolean isVtSettingEnabled() {
try {
return getITelephony().isVtSettingEnabled(mSubId);
@@ -669,7 +799,9 @@
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @see #isVtSettingEnabled()
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVtSettingEnabled(boolean isEnabled) {
try {
@@ -689,11 +821,28 @@
/**
* @return true if the user's setting for Voice over WiFi is enabled and false if it is not.
*
+ * <p>This API requires one of the following:
+ * <ul>
+ * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li>
+ * <li>If the caller is the device or profile owner, the caller holds the
+ * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li>
+ * <li>The caller has carrier privileges (see
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any
+ * active subscription.</li>
+ * <li>The caller is the default SMS app for the device.</li>
+ * </ul>
+ * <p>The profile owner is an app that owns a managed profile on the device; for more details
+ * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Access by profile owners is deprecated and will be removed in a future release.
+ *
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @see #setVoWiFiSettingEnabled(boolean)
*/
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public boolean isVoWiFiSettingEnabled() {
try {
return getITelephony().isVoWiFiSettingEnabled(mSubId);
@@ -716,7 +865,9 @@
* active (SIM is not inserted, ESIM inactive) or invalid.
* @param isEnabled true if the user's setting for Voice over WiFi is enabled, false otherwise=
* @see #isVoWiFiSettingEnabled()
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiSettingEnabled(boolean isEnabled) {
try {
@@ -736,13 +887,30 @@
/**
* Returns the user's voice over WiFi roaming setting associated with the current subscription.
*
+ * <p>This API requires one of the following:
+ * <ul>
+ * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li>
+ * <li>If the caller is the device or profile owner, the caller holds the
+ * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li>
+ * <li>The caller has carrier privileges (see
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any
+ * active subscription.</li>
+ * <li>The caller is the default SMS app for the device.</li>
+ * </ul>
+ * <p>The profile owner is an app that owns a managed profile on the device; for more details
+ * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Access by profile owners is deprecated and will be removed in a future release.
+ *
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @return true if the user's setting for Voice over WiFi while roaming is enabled, false
* if disabled.
* @see #setVoWiFiRoamingSettingEnabled(boolean)
*/
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public boolean isVoWiFiRoamingSettingEnabled() {
try {
return getITelephony().isVoWiFiRoamingSettingEnabled(mSubId);
@@ -766,7 +934,9 @@
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @see #isVoWiFiRoamingSettingEnabled()
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) {
try {
@@ -796,7 +966,9 @@
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @see #setVoWiFiSettingEnabled(boolean)
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiNonPersistent(boolean isCapable, int mode) {
try {
@@ -816,6 +988,20 @@
/**
* Returns the user's voice over WiFi Roaming mode setting associated with the device.
*
+ * <p>This API requires one of the following:
+ * <ul>
+ * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li>
+ * <li>If the caller is the device or profile owner, the caller holds the
+ * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li>
+ * <li>The caller has carrier privileges (see
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any
+ * active subscription.</li>
+ * <li>The caller is the default SMS app for the device.</li>
+ * </ul>
+ * <p>The profile owner is an app that owns a managed profile on the device; for more details
+ * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Access by profile owners is deprecated and will be removed in a future release.
+ *
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @return The Voice over WiFi Mode preference set by the user, which can be one of the
@@ -825,7 +1011,10 @@
* - {@link #WIFI_MODE_WIFI_PREFERRED}
* @see #setVoWiFiSettingEnabled(boolean)
*/
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public @WiFiCallingMode int getVoWiFiModeSetting() {
try {
return getITelephony().getVoWiFiModeSetting(mSubId);
@@ -851,7 +1040,9 @@
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @see #getVoWiFiModeSetting()
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiModeSetting(@WiFiCallingMode int mode) {
try {
@@ -880,7 +1071,9 @@
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @see #setVoWiFiRoamingSettingEnabled(boolean)
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @WiFiCallingMode int getVoWiFiRoamingModeSetting() {
try {
@@ -909,7 +1102,9 @@
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @see #getVoWiFiRoamingModeSetting()
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiRoamingModeSetting(@WiFiCallingMode int mode) {
try {
@@ -936,7 +1131,9 @@
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @param isEnabled if true RTT should be enabled during calls made on this subscription.
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setRttCapabilitySetting(boolean isEnabled) {
try {
@@ -956,12 +1153,29 @@
/**
* @return true if TTY over VoLTE is supported
*
+ * <p>This API requires one of the following:
+ * <ul>
+ * <li>The caller holds the READ_PRECISE_PHONE_STATE permission.</li>
+ * <li>If the caller is the device or profile owner, the caller holds the
+ * {@link Manifest.permission#READ_PRECISE_PHONE_STATE} permission.</li>
+ * <li>The caller has carrier privileges (see
+ * {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on any
+ * active subscription.</li>
+ * <li>The caller is the default SMS app for the device.</li>
+ * </ul>
+ * <p>The profile owner is an app that owns a managed profile on the device; for more details
+ * see <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
+ * Access by profile owners is deprecated and will be removed in a future release.
+ *
* @throws IllegalArgumentException if the subscription associated with this operation is not
* active (SIM is not inserted, ESIM inactive) or invalid.
* @see android.telecom.TelecomManager#getCurrentTtyMode
* @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL
*/
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public boolean isTtyOverVolteEnabled() {
try {
return getITelephony().isTtyOverVolteEnabled(mSubId);
@@ -988,7 +1202,9 @@
* specified when the service state has been retrieved from the IMS service.
* @throws ImsException if the IMS service associated with this subscription is not available or
* the IMS service is not available.
+ * @hide
*/
+ @SystemApi @TestApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void getFeatureState(@NonNull @CallbackExecutor Executor executor,
@NonNull @ImsFeature.ImsState Consumer<Integer> callback) throws ImsException {
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 0c8dba6..5aa37bb 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -28,6 +28,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.AccessNetworkConstants;
+import android.telephony.SubscriptionManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRcsController;
import android.telephony.ims.feature.ImsFeature;
@@ -35,6 +36,8 @@
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;
+import com.android.internal.telephony.IIntegerConsumer;
+
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -154,9 +157,20 @@
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
+
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "Register registration callback: IImsRcsController is null");
+ throw new ImsException("Cannot find remote IMS service",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
c.setExecutor(executor);
- throw new UnsupportedOperationException("registerImsRegistrationCallback is not"
- + "supported.");
+ try {
+ imsRcsController.registerImsRegistrationCallback(mSubId, c.getBinder());
+ } catch (RemoteException | IllegalStateException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
}
/**{@inheritDoc}*/
@@ -167,8 +181,18 @@
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
}
- throw new UnsupportedOperationException("unregisterImsRegistrationCallback is not"
- + "supported.");
+
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "Unregister registration callback: IImsRcsController is null");
+ throw new IllegalStateException("Cannot find remote IMS service");
+ }
+
+ try {
+ imsRcsController.unregisterImsRegistrationCallback(mSubId, c.getBinder());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
}
/**{@inheritDoc}*/
@@ -182,8 +206,23 @@
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
- throw new UnsupportedOperationException("getRegistrationState is not"
- + "supported.");
+
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "Get registration state error: IImsRcsController is null");
+ throw new IllegalStateException("Cannot find remote IMS service");
+ }
+
+ try {
+ imsRcsController.getImsRcsRegistrationState(mSubId, new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> stateCallback.accept(result));
+ }
+ });
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
}
/**{@inheritDoc}*/
@@ -198,10 +237,25 @@
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
- throw new UnsupportedOperationException("getRegistrationTransportType is not"
- + "supported.");
- }
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "Get registration transport type error: IImsRcsController is null");
+ throw new IllegalStateException("Cannot find remote IMS service");
+ }
+
+ try {
+ imsRcsController.getImsRcsRegistrationTransportType(mSubId,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> transportTypeCallback.accept(result));
+ }
+ });
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
/**
* Registers an {@link AvailabilityCallback} with the system, which will provide RCS
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index f4b2cef..0d6b31d 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
index 6b72859..2d2e638 100644
--- a/telephony/java/android/telephony/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -22,7 +22,7 @@
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index 77bd984..9cce95f 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index b7ab0a0..b70fd64 100644
--- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
index 270e693..569c6d5 100644
--- a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
+++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
@@ -18,7 +18,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index e16085e..aa4f77d 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -26,15 +26,15 @@
import android.annotation.TestApi;
import android.annotation.WorkerThread;
import android.content.Context;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.ims.aidl.IImsConfigCallback;
import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.stub.ImsConfigImplBase;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -85,6 +85,11 @@
"STRING_QUERY_RESULT_ERROR_NOT_READY";
/**
+ * There is no existing configuration for the queried provisioning key.
+ */
+ public static final int PROVISIONING_RESULT_UNKNOWN = -1;
+
+ /**
* The integer result of provisioning for the queried key is disabled.
*/
public static final int PROVISIONING_VALUE_DISABLED = 0;
@@ -95,6 +100,313 @@
public static final int PROVISIONING_VALUE_ENABLED = 1;
+ // Inheriting values from ImsConfig for backwards compatibility.
+ /**
+ * AMR CODEC Mode Value set, 0-7 in comma separated sequence.
+ * <p>
+ * This corresponds to the {@code mode-set} parameter for the AMR codec.
+ * See 3GPP TS 26.101 Table 1A for more information.
+ * <p>
+ * <UL>
+ * <LI>0 - AMR 4.75 kbit/s</LI>
+ * <LI>1 - AMR 5.15 kbit/s</LI>
+ * <LI>2 - AMR 5.90 kbit/s</LI>
+ * <LI>3 - AMR 6.70 kbit/s (PDC-EFR)</LI>
+ * <LI>4 - AMR 7.40 kbit/s (TDMA-EFR)</LI>
+ * <LI>5 - AMR 7.95 kbit/s</LI>
+ * <LI>6 - AMR 10.2 kbit/s</LI>
+ * <LI>7 - AMR 12.2 kbit/s (GSM-EFR)</LI>
+ * </UL>
+ * <p>
+ * Value is in String format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_AMR_CODEC_MODE_SET_VALUES = 0;
+
+ /**
+ * Wide Band AMR CODEC Mode Value set,0-7 in comma separated sequence.
+ * <p>
+ * This corresponds to the {@code mode-set} parameter for the AMR wideband codec.
+ * See 3GPP TS 26.101 Table 1A for more information.
+ * <p>
+ * <UL>
+ * <LI>0 - AMR 4.75 kbit/s</LI>
+ * <LI>1 - AMR 5.15 kbit/s</LI>
+ * <LI>2 - AMR 5.90 kbit/s</LI>
+ * <LI>3 - AMR 6.70 kbit/s (PDC-EFR)</LI>
+ * <LI>4 - AMR 7.40 kbit/s (TDMA-EFR)</LI>
+ * <LI>5 - AMR 7.95 kbit/s</LI>
+ * <LI>6 - AMR 10.2 kbit/s</LI>
+ * <LI>7 - AMR 12.2 kbit/s (GSM-EFR)</LI>
+ * </UL>
+ * <p>
+ * Value is in String format.
+ * @see #setProvisioningStringValue(int, String)
+ * @see #getProvisioningStringValue(int)
+ */
+ public static final int KEY_AMR_WB_CODEC_MODE_SET_VALUES = 1;
+
+ /**
+ * SIP Session Timer value (seconds).
+ * <p>
+ * See RFC4028 for more information.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_SESSION_TIMER_SEC = 2;
+
+ /**
+ * Minimum SIP Session Expiration Timer in (seconds).
+ * <p>
+ * See RFC4028 for more information.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC = 3;
+
+ /**
+ * SIP_INVITE cancellation time out value (in milliseconds). Integer format.
+ * <p>
+ * See RFC4028 for more information.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_INVITE_CANCELLATION_TIMER_MS = 4;
+
+ /**
+ * Delay time when an iRAT transitions from eHRPD/HRPD/1xRTT to LTE.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_TRANSITION_TO_LTE_DELAY_MS = 5;
+
+ /**
+ * Silent redial status of Enabled (True), or Disabled (False).
+ * Value is in boolean format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_ENABLE_SILENT_REDIAL = 6;
+
+ /**
+ * An integer key representing the SIP T1 timer value in milliseconds for the associated
+ * subscription.
+ * <p>
+ * The SIP T1 timer is an estimate of the round-trip time and will retransmit
+ * INVITE transactions that are longer than T1 milliseconds over unreliable transports, doubling
+ * the time before retransmission every time there is no response. See RFC3261, section 17.1.1.1
+ * for more details.
+ * <p>
+ * The value is an integer.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_T1_TIMER_VALUE_MS = 7;
+
+ /**
+ * SIP T2 timer value in milliseconds. See RFC 3261 for information.
+ * <p>
+ * The T2 timer is the maximum retransmit interval for non-INVITE requests and INVITE responses.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_T2_TIMER_VALUE_MS = 8;
+
+ /**
+ * SIP TF timer value in milliseconds. See RFC 3261 for information.
+ * <p>
+ * The TF timer is the non-INVITE transaction timeout timer.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_TF_TIMER_VALUE_MS = 9;
+
+ /**
+ * An integer key representing the voice over LTE (VoLTE) provisioning status for the
+ * associated subscription. Determines whether the user can register for voice services over
+ * LTE.
+ * <p>
+ * Use {@link #PROVISIONING_VALUE_ENABLED} to enable VoLTE provisioning and
+ * {@link #PROVISIONING_VALUE_DISABLED} to disable VoLTE provisioning.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_VOLTE_PROVISIONING_STATUS = 10;
+
+ /**
+ * An integer key representing the video telephony (VT) provisioning status for the
+ * associated subscription. Determines whether the user can register for video services over
+ * LTE.
+ * <p>
+ * Use {@link #PROVISIONING_VALUE_ENABLED} to enable VT provisioning and
+ * {@link #PROVISIONING_VALUE_DISABLED} to disable VT provisioning.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_VT_PROVISIONING_STATUS = 11;
+
+ /**
+ * Domain Name for the device to populate the request URI for REGISTRATION.
+ * Value is in String format.
+ * @see #setProvisioningStringValue(int, String)
+ * @see #getProvisioningStringValue(int)
+ */
+ public static final int KEY_REGISTRATION_DOMAIN_NAME = 12;
+
+ /**
+ * Device Outgoing SMS based on either 3GPP or 3GPP2 standards.
+ * Value is in Integer format.
+ * Valid values are {@link #SMS_FORMAT_3GPP} and {@link #SMS_FORMAT_3GPP2}.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SMS_FORMAT = 13;
+
+ /**
+ * Value used with {@link #KEY_SMS_FORMAT} to indicate 3GPP2 SMS format is used.
+ * See {@link android.telephony.SmsMessage#FORMAT_3GPP2} for more information.
+ */
+ public static final int SMS_FORMAT_3GPP2 = 0;
+
+ /**
+ * Value used with {@link #KEY_SMS_FORMAT} to indicate 3GPP SMS format is used.
+ * See {@link android.telephony.SmsMessage#FORMAT_3GPP} for more information.
+ */
+ public static final int SMS_FORMAT_3GPP = 1;
+
+ /**
+ * Turns SMS over IMS ON/OFF on the device.
+ * Value is in Integer format. ON (1), OFF(0).
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SMS_OVER_IP_ENABLED = 14;
+
+ /**
+ * An integer key associated with the carrier configured SIP PUBLISH timer, which dictates the
+ * expiration time in seconds for published online availability in RCS presence.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RCS_PUBLISH_TIMER_SEC = 15;
+
+ /**
+ * An integer key associated with the carrier configured expiration time in seconds for
+ * RCS presence published offline availability in RCS presence.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16;
+
+ /**
+ * An integer key associated with whether or not capability discovery is provisioned for this
+ * subscription. Any capability requests will be ignored by the RCS service.
+ * <p>
+ * The value is an integer, either {@link #PROVISIONING_VALUE_DISABLED} if capability
+ * discovery is disabled or {@link #PROVISIONING_VALUE_ENABLED} if capability discovery is
+ * enabled.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RCS_CAPABILITY_DISCOVERY_ENABLED = 17;
+
+ /**
+ * An integer key associated with the period of time the capability information of each contact
+ * is cached on the device.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC = 18;
+
+ /**
+ * An integer key associated with the period of time in seconds that the availability
+ * information of a contact is cached on the device.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC = 19;
+
+ /**
+ * An integer key associated with the carrier configured interval in seconds expected between
+ * successive capability polling attempts.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RCS_CAPABILITIES_POLL_INTERVAL_SEC = 20;
+
+ /**
+ * An integer key representing the minimum time allowed between two consecutive presence publish
+ * messages from the device.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS = 21;
+
+ /**
+ * An integer key associated with the maximum number of MDNs contained in one SIP Request
+ * Contained List (RCS) used to retrieve the RCS capabilities of the contacts book.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RCS_MAX_NUM_ENTRIES_IN_RCL = 22;
+
+ /**
+ * An integer associated with the expiration timer used during the SIP subscription of a
+ * Request Contained List (RCL), which is used to retrieve the RCS capabilities of the contact
+ * book.
+ * <p>
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC = 23;
+
+ /**
+ * Applies compression to LIST Subscription.
+ * Value is in Integer format. Enable (1), Disable(0).
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION = 24;
+
+ /**
+ * An integer key representing the RCS enhanced address book (EAB) provisioning status for the
+ * associated subscription. Determines whether or not SIP OPTIONS or presence will be used to
+ * retrieve RCS capabilities for the user's contacts.
+ * <p>
+ * Use {@link #PROVISIONING_VALUE_ENABLED} to enable EAB provisioning and
+ * {@link #PROVISIONING_VALUE_DISABLED} to disable EAB provisioning.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_EAB_PROVISIONING_STATUS = 25;
+
/**
* Override the user-defined WiFi Roaming enabled setting for this subscription, defined in
* {@link SubscriptionManager#WFC_ROAMING_ENABLED_CONTENT_URI}, for the purposes of provisioning
@@ -121,6 +433,349 @@
public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27;
/**
+ * Enable voice over wifi. Enabled (1), or Disabled (0).
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE = 28;
+
+ /**
+ * Mobile data enabled.
+ * Value is in Integer format. On (1), OFF(0).
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_MOBILE_DATA_ENABLED = 29;
+
+ /**
+ * VoLTE user opted in status.
+ * Value is in Integer format. Opted-in (1) Opted-out (0).
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_VOLTE_USER_OPT_IN_STATUS = 30;
+
+ /**
+ * Proxy for Call Session Control Function(P-CSCF) address for Local-BreakOut(LBO).
+ * Value is in String format.
+ */
+ public static final int KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS = 31;
+
+ /**
+ * Keep Alive Enabled for SIP.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_KEEP_ALIVE_ENABLED = 32;
+
+ /**
+ * Registration retry Base Time value in seconds.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33;
+
+ /**
+ * Registration retry Max Time value in seconds.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_REGISTRATION_RETRY_MAX_TIME_SEC = 34;
+
+ /**
+ * Smallest RTP port for speech codec.
+ * Value is in integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+
+ public static final int KEY_RTP_SPEECH_START_PORT = 35;
+
+ /**
+ * Largest RTP port for speech code.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RTP_SPEECH_END_PORT = 36;
+
+ /**
+ * SIP Timer A's value in milliseconds. Timer A is the INVITE request retransmit interval (in
+ * milliseconds), for UDP only.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS = 37;
+
+ /**
+ * SIP Timer B's value in milliseconds. Timer B is the wait time for INVITE message to be,
+ * in milliseconds.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_INVITE_ACK_WAIT_TIME_MS = 38;
+
+ /**
+ * SIP Timer D's value in milliseconds. Timer D is the wait time for response retransmits of
+ * the invite client transactions, in milliseconds.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS = 39;
+
+ /**
+ * SIP Timer E's value in milliseconds. Timer E is the value Non-INVITE request retransmit
+ * interval (in milliseconds), for UDP only.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMIT_INTERVAL_MS = 40;
+
+ /**
+ * SIP Timer F's value in milliseconds. Timer F is the Non-INVITE transaction timeout timer,
+ * in milliseconds.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS = 41;
+
+ /**
+ * SIP Timer G's value in milliseconds. Timer G is the value of INVITE response
+ * retransmit interval.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS = 42;
+
+ /**
+ * SIP Timer H's value in milliseconds. Timer H is the value of wait time for
+ * ACK receipt.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS = 43;
+
+ /**
+ * SIP Timer I's value in milliseconds. Timer I is the value of wait time for
+ * ACK retransmits.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS = 44;
+
+ /**
+ * SIP Timer J's value in milliseconds. Timer J is the value of wait time for
+ * non-invite request retransmission.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS = 45;
+
+ /**
+ * SIP Timer K's value in milliseconds. Timer K is the value of wait time for
+ * non-invite response retransmits.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS = 46;
+
+ /**
+ * AMR WB octet aligned dynamic payload type.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE = 47;
+
+ /**
+ * AMR WB bandwidth efficient payload type.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 48;
+
+ /**
+ * AMR octet aligned dynamic payload type.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE = 49;
+
+ /**
+ * AMR bandwidth efficient payload type.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE = 50;
+
+ /**
+ * DTMF WB payload type.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_DTMF_WB_PAYLOAD_TYPE = 51;
+
+ /**
+ * DTMF NB payload type.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_DTMF_NB_PAYLOAD_TYPE = 52;
+
+ /**
+ * AMR Default encoding mode.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_AMR_DEFAULT_ENCODING_MODE = 53;
+
+ /**
+ * SMS Public Service Identity.
+ * Value is in String format.
+ */
+ public static final int KEY_SMS_PUBLIC_SERVICE_IDENTITY = 54;
+
+ /**
+ * Video Quality - VideoQualityFeatureValuesConstants.
+ * Valid values are: {@link #VIDEO_QUALITY_HIGH} and {@link #VIDEO_QUALITY_LOW}.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_VIDEO_QUALITY = 55;
+
+ /**
+ * Used with {@link #KEY_VIDEO_QUALITY} to indicate low video quality.
+ */
+ public static final int VIDEO_QUALITY_LOW = 0;
+
+ /**
+ * Used with {@link #KEY_VIDEO_QUALITY} to indicate high video quality.
+ */
+ public static final int VIDEO_QUALITY_HIGH = 1;
+
+ /**
+ * LTE to WIFI handover threshold.
+ * Handover from LTE to WiFi if LTE < THLTE1 and WiFi >= {@link #KEY_WIFI_THRESHOLD_A}.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_LTE_THRESHOLD_1 = 56;
+
+ /**
+ * WIFI to LTE handover threshold.
+ * Handover from WiFi to LTE if LTE >= {@link #KEY_LTE_THRESHOLD_3} or (WiFi < {@link
+ * #KEY_WIFI_THRESHOLD_B} and LTE >= {@link #KEY_LTE_THRESHOLD_2}).
+ * Value is in Integer format.
+ *
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_LTE_THRESHOLD_2 = 57;
+
+ /**
+ * LTE to WIFI handover threshold.
+ * Handover from WiFi to LTE if LTE >= {@link #KEY_LTE_THRESHOLD_3} or (WiFi < {@link
+ * #KEY_WIFI_THRESHOLD_B} and LTE >= {@link #KEY_LTE_THRESHOLD_2}).
+ * Value is in Integer format.
+ *
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_LTE_THRESHOLD_3 = 58;
+
+ /**
+ * 1x to WIFI handover threshold.
+ * Handover from 1x to WiFi if 1x < {@link #KEY_1X_THRESHOLD}.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_1X_THRESHOLD = 59;
+
+ /**
+ * LTE to WIFI threshold A.
+ * Handover from LTE to WiFi if LTE < {@link #KEY_LTE_THRESHOLD_1} and WiFi >= {@link
+ * #KEY_WIFI_THRESHOLD_A}.
+ * Value is in Integer format.
+ *
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_WIFI_THRESHOLD_A = 60;
+
+ /**
+ * WiFi to LTRE handover threshold B.
+ * Handover from WiFi to LTE if LTE >= {@link #KEY_LTE_THRESHOLD_3} or (WiFi <
+ * {@link #KEY_WIFI_THRESHOLD_B} and LTE >= {@link #KEY_LTE_THRESHOLD_2}).
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_WIFI_THRESHOLD_B = 61;
+
+ /**
+ * LTE ePDG timer (in seconds).
+ * Device shall not handover back to LTE until the T_ePDG_LTE timer expires.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_LTE_EPDG_TIMER_SEC = 62;
+
+ /**
+ * WiFi ePDG timer (in seconds).
+ * Device shall not handover back to WiFi until the T_ePDG_WiFi timer expires.
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_WIFI_EPDG_TIMER_SEC = 63;
+
+ /**
+ * 1x ePDG timer (in seconds).
+ * Device shall not re-register on 1x until the T_ePDG_1x timer expires.
+ */
+ public static final int KEY_1X_EPDG_TIMER_SEC = 64;
+
+ /**
+ * MultiEndpoint status: Enabled (1), or Disabled (0).
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_MULTIENDPOINT_ENABLED = 65;
+
+ /**
+ * RTT status: Enabled (1), or Disabled (0).
+ * Value is in Integer format.
+ * @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ */
+ public static final int KEY_RTT_ENABLED = 66;
+
+ /**
* Callback for IMS provisioning changes.
*/
public static class Callback {
@@ -225,13 +880,11 @@
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerProvisioningChangedCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull Callback callback) throws ImsException {
- if (!isImsAvailableOnDevice()) {
- throw new ImsException("IMS not available on device.",
- ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
- }
callback.setExecutor(executor);
try {
getITelephony().registerImsProvisioningChangedCallback(mSubId, callback.getBinder());
+ } catch (ServiceSpecificException e) {
+ throw new ImsException(e.getMessage(), e.errorCode);
} catch (RemoteException | IllegalStateException e) {
throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
@@ -263,7 +916,7 @@
*
* @param key An integer that represents the provisioning key, which is defined by the OEM.
* @return an integer value for the provided key, or
- * {@link ImsConfigImplBase#CONFIG_RESULT_UNKNOWN} if the key doesn't exist.
+ * {@link #PROVISIONING_RESULT_UNKNOWN} if the key doesn't exist.
* @throws IllegalArgumentException if the key provided was invalid.
*/
@WorkerThread
@@ -390,37 +1043,75 @@
}
/**
+ * Get the provisioning status for the IMS RCS capability specified.
+ *
+ * If provisioning is not required for the queried
+ * {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method will always return
+ * {@code true}.
+ *
+ * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+ * @return true if the device is provisioned for the capability or does not require
+ * provisioning, false if the capability does require provisioning and has not been
+ * provisioned yet.
+ */
+ @WorkerThread
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public boolean getRcsProvisioningStatusForCapability(
+ @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
+ try {
+ return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Set the provisioning status for the IMS RCS capability using the specified subscription.
+ *
+ * Provisioning may or may not be required, depending on the carrier configuration. If
+ * provisioning is not required for the carrier associated with this subscription or the device
+ * does not support the capability/technology combination specified, this operation will be a
+ * no-op.
+ *
+ * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+ * @param isProvisioned true if the device is provisioned for the RCS capability specified,
+ * false otherwise.
+ */
+ @WorkerThread
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public void setRcsProvisioningStatusForCapability(
+ @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+ boolean isProvisioned) {
+ try {
+ getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability,
+ isProvisioned);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
* Notify the framework that an RCS autoconfiguration XML file has been received for
* provisioning.
+ * <p>
+ * Requires Permission: Manifest.permission.MODIFY_PHONE_STATE or that the calling app has
+ * carrier privileges (see {@link #hasCarrierPrivileges}).
* @param config The XML file to be read. ASCII/UTF8 encoded text if not compressed.
* @param isCompressed The XML file is compressed in gzip format and must be decompressed
* before being read.
- * @hide
+ *
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void notifyRcsAutoConfigurationReceived(@NonNull byte[] config, boolean isCompressed) {
if (config == null) {
throw new IllegalArgumentException("Must include a non-null config XML file.");
}
- // TODO: Connect to ImsConfigImplBase.
- throw new UnsupportedOperationException("notifyRcsAutoConfigurationReceived is not"
- + "supported");
- }
-
- private static boolean isImsAvailableOnDevice() {
- IPackageManager pm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
- if (pm == null) {
- // For some reason package manger is not available.. This will fail internally anyways,
- // so do not throw error and allow.
- return true;
- }
try {
- return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0);
+ getITelephony().notifyRcsAutoConfigurationReceived(mSubId, config, isCompressed);
} catch (RemoteException e) {
- // For some reason package manger is not available.. This will fail internally anyways,
- // so do not throw error and allow.
+ throw e.rethrowAsRuntimeException();
}
- return true;
+
}
private static ITelephony getITelephony() {
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index 492170b..3e2903f 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -35,6 +36,7 @@
* Contains the User Capability Exchange capabilities corresponding to a contact's URI.
* @hide
*/
+@SystemApi
public final class RcsContactUceCapability implements Parcelable {
/** Supports 1-to-1 chat */
@@ -81,8 +83,23 @@
public static final int CAPABILITY_RCS_VOICE_CALL = (1 << 19);
/** Supports RCS video calling */
public static final int CAPABILITY_RCS_VIDEO_CALL = (1 << 20);
- /** Supports RCS video calling, where video media can not be dropped */
+ /** Supports RCS video calling, where video media can not be dropped. */
public static final int CAPABILITY_RCS_VIDEO_ONLY_CALL = (1 << 21);
+ /** Supports call composer, where outgoing calls can be enriched with pre-call content.*/
+ public static final int CAPABILITY_CALL_COMPOSER = (1 << 22);
+ /** Supports post call information that is included in the call if the call is missed.*/
+ public static final int CAPABILITY_POST_CALL = (1 << 23);
+ /** Supports sharing a map where the user can draw, share markers, and share their position. */
+ public static final int CAPABILITY_SHARED_MAP = (1 << 24);
+ /** Supports sharing a canvas, where users can draw, add images, and change background colors.*/
+ public static final int CAPABILITY_SHARED_SKETCH = (1 << 25);
+ /** Supports communication with Chatbots. */
+ public static final int CAPABILITY_CHAT_BOT = (1 << 26);
+ /** Supports Chatbot roles. */
+ public static final int CAPABILITY_CHAT_BOT_ROLE = (1 << 27);
+ /** Supports the unidirectional plug-ins framework. */
+ public static final int CAPABILITY_PLUG_IN = (1 << 28);
+
/** @hide*/
@Retention(RetentionPolicy.SOURCE)
@@ -108,7 +125,14 @@
CAPABILITY_GEOLOCATION_PULL_FILE_TRANSFER,
CAPABILITY_RCS_VOICE_CALL,
CAPABILITY_RCS_VIDEO_CALL,
- CAPABILITY_RCS_VIDEO_ONLY_CALL
+ CAPABILITY_RCS_VIDEO_ONLY_CALL,
+ CAPABILITY_CALL_COMPOSER,
+ CAPABILITY_POST_CALL,
+ CAPABILITY_SHARED_MAP,
+ CAPABILITY_SHARED_SKETCH,
+ CAPABILITY_CHAT_BOT,
+ CAPABILITY_CHAT_BOT_ROLE,
+ CAPABILITY_PLUG_IN
})
public @interface CapabilityFlag {}
@@ -135,7 +159,7 @@
* @param type The capability to map to a service URI that is different from the contact's
* URI.
*/
- public Builder add(@CapabilityFlag int type, @NonNull Uri serviceUri) {
+ public @NonNull Builder add(@CapabilityFlag int type, @NonNull Uri serviceUri) {
mCapabilities.mCapabilities |= type;
// Put each of these capabilities into the map separately.
for (int shift = 0; shift < Integer.SIZE; shift++) {
@@ -157,7 +181,7 @@
* Add a UCE capability flag that this contact supports.
* @param type the capability that the contact supports.
*/
- public Builder add(@CapabilityFlag int type) {
+ public @NonNull Builder add(@CapabilityFlag int type) {
mCapabilities.mCapabilities |= type;
return this;
}
@@ -167,7 +191,7 @@
* @param extension A string containing a carrier specific service tag that is an extension
* of the {@link CapabilityFlag}s that are defined here.
*/
- public Builder add(@NonNull String extension) {
+ public @NonNull Builder add(@NonNull String extension) {
mCapabilities.mExtensionTags.add(extension);
return this;
}
@@ -175,13 +199,13 @@
/**
* @return the constructed instance.
*/
- public RcsContactUceCapability build() {
+ public @NonNull RcsContactUceCapability build() {
return mCapabilities;
}
}
private final Uri mContactUri;
- private int mCapabilities;
+ private long mCapabilities;
private List<String> mExtensionTags = new ArrayList<>();
private Map<Integer, Uri> mServiceMap = new HashMap<>();
@@ -196,7 +220,7 @@
private RcsContactUceCapability(Parcel in) {
mContactUri = in.readParcelable(Uri.class.getClassLoader());
- mCapabilities = in.readInt();
+ mCapabilities = in.readLong();
in.readStringList(mExtensionTags);
// read mServiceMap as key,value pair
int mapSize = in.readInt();
@@ -205,7 +229,7 @@
}
}
- public static final Creator<RcsContactUceCapability> CREATOR =
+ public static final @NonNull Creator<RcsContactUceCapability> CREATOR =
new Creator<RcsContactUceCapability>() {
@Override
public RcsContactUceCapability createFromParcel(Parcel in) {
@@ -219,9 +243,9 @@
};
@Override
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeParcelable(mContactUri, 0);
- out.writeInt(mCapabilities);
+ out.writeLong(mCapabilities);
out.writeStringList(mExtensionTags);
// write mServiceMap as key,value pairs
int mapSize = mServiceMap.keySet().size();
diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java
index 99bb259..a1f6b78 100644
--- a/telephony/java/android/telephony/ims/RegistrationManager.java
+++ b/telephony/java/android/telephony/ims/RegistrationManager.java
@@ -22,8 +22,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.net.Uri;
import android.os.Binder;
import android.telephony.AccessNetworkConstants;
@@ -41,10 +39,7 @@
/**
* Manages IMS Service registration state for associated {@link ImsFeature}s.
- * @hide
*/
-@SystemApi
-@TestApi
public interface RegistrationManager {
/**
@@ -139,7 +134,6 @@
getAccessType(imsRadioTech), info)));
}
- @Override
public void onSubscriberAssociatedUriChanged(Uri[] uris) {
if (mLocalCallback == null) return;
@@ -225,7 +219,11 @@
/**
* Registers a {@link RegistrationCallback} with the system. Use
- * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed
+ * @param executor The {@link Executor} that will be used to call the IMS registration state
+ * callback.
+ * @param c A callback called on the supplied {@link Executor} that will contain the
+ * registration state of the IMS service, which will be one of the
+ * {@see SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed
* events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
*
* When the callback is registered, it will initiate the callback c to be called with the
@@ -275,10 +273,10 @@
* Gets the Transport Type associated with the current IMS registration.
* @param executor The {@link Executor} that will be used to call the transportTypeCallback.
* @param transportTypeCallback The transport type associated with the current IMS registration,
- * which will be one of following:
- * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN},
- * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or
- * {@link AccessNetworkConstants#TRANSPORT_TYPE_INVALID}.
+ * which will be one of following:
+ * {@see AccessNetworkConstants#TRANSPORT_TYPE_WWAN},
+ * {@see AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or
+ * {@see AccessNetworkConstants#TRANSPORT_TYPE_INVALID}.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
void getRegistrationTransportType(
diff --git a/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
index d64e67a..cc2ebb9 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
@@ -92,11 +92,11 @@
/**
* Notifies of handover information for this call
*/
- void callSessionHandover(int srcAccessTech, int targetAccessTech,
+ void callSessionHandover(int srcNetworkType, int targetNetworkType,
in ImsReasonInfo reasonInfo);
- void callSessionHandoverFailed(int srcAccessTech, int targetAccessTech,
+ void callSessionHandoverFailed(int srcNetworkType, int targetNetworkType,
in ImsReasonInfo reasonInfo);
- void callSessionMayHandover(int srcAccessTech, int targetAccessTech);
+ void callSessionMayHandover(int srcNetworkType, int targetNetworkType);
/**
* Notifies the TTY mode change by remote party.
diff --git a/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
index 53e4596..57206c9 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
@@ -40,4 +40,5 @@
// Return result code defined in ImsConfig#OperationStatusConstants
int setConfigString(int item, String value);
void updateImsCarrierConfigs(in PersistableBundle bundle);
+ void notifyRcsAutoConfigurationReceived(in byte[] config, boolean isCompressed);
}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index e81bac0..6f6aa44 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -19,6 +19,9 @@
import android.net.Uri;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
+import android.telephony.ims.aidl.IImsRegistrationCallback;
+
+import com.android.internal.telephony.IIntegerConsumer;
/**
* Interface used to interact with the Telephony IMS.
@@ -26,6 +29,13 @@
* {@hide}
*/
interface IImsRcsController {
+ // IMS RCS registration commands
+ void registerImsRegistrationCallback(int subId, IImsRegistrationCallback c);
+ void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback c);
+ void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer);
+ void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer);
+
+ // IMS RCS capability commands
void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback c);
void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback c);
boolean isCapable(int subId, int capability, int radioTech);
diff --git a/telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl b/telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl
index 881b477..70cf651 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl
@@ -32,11 +32,11 @@
oneway void onNetworkResponse(int code, in String reason, int operationToken);
oneway void onCapabilityRequestResponsePresence(in List<RcsContactUceCapability> infos,
int operationToken);
- oneway void onNotifyUpdateCapabilities();
+ oneway void onNotifyUpdateCapabilities(int publishTriggerType);
oneway void onUnpublish();
// RcsSipOptionsImplBase specific
oneway void onCapabilityRequestResponseOptions(int code, in String reason,
in RcsContactUceCapability info, int operationToken);
oneway void onRemoteCapabilityRequest(in Uri contactUri, in RcsContactUceCapability remoteInfo,
int operationToken);
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/ims/compat/ImsService.java b/telephony/java/android/telephony/ims/compat/ImsService.java
index 97a8517..eafbb14 100644
--- a/telephony/java/android/telephony/ims/compat/ImsService.java
+++ b/telephony/java/android/telephony/ims/compat/ImsService.java
@@ -17,8 +17,8 @@
package android.telephony.ims.compat;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
diff --git a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
index de4f174..5a9e8e2 100644
--- a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
@@ -17,7 +17,7 @@
package android.telephony.ims.compat.feature;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.IInterface;
import android.os.RemoteException;
diff --git a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
index 3fd356a..b52c371 100644
--- a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
@@ -16,8 +16,8 @@
package android.telephony.ims.compat.feature;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Message;
import android.os.RemoteException;
import android.telephony.ims.ImsCallProfile;
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
index d77f78e..75bd6a7 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
@@ -16,10 +16,11 @@
package android.telephony.ims.compat.stub;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Message;
import android.os.RemoteException;
import android.telephony.CallQuality;
+import android.telephony.ServiceState;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsCallSession;
import android.telephony.ims.ImsConferenceState;
@@ -547,19 +548,25 @@
@Override
public void callSessionHandover(IImsCallSession i, int srcAccessTech, int targetAccessTech,
ImsReasonInfo reasonInfo) throws RemoteException {
- mNewListener.callSessionHandover(srcAccessTech, targetAccessTech, reasonInfo);
+ mNewListener.callSessionHandover(
+ ServiceState.rilRadioTechnologyToNetworkType(srcAccessTech),
+ ServiceState.rilRadioTechnologyToNetworkType(targetAccessTech), reasonInfo);
}
@Override
public void callSessionHandoverFailed(IImsCallSession i, int srcAccessTech,
int targetAccessTech, ImsReasonInfo reasonInfo) throws RemoteException {
- mNewListener.callSessionHandoverFailed(srcAccessTech, targetAccessTech, reasonInfo);
+ mNewListener.callSessionHandoverFailed(
+ ServiceState.rilRadioTechnologyToNetworkType(srcAccessTech),
+ ServiceState.rilRadioTechnologyToNetworkType(targetAccessTech), reasonInfo);
}
@Override
public void callSessionMayHandover(IImsCallSession i, int srcAccessTech, int targetAccessTech)
throws RemoteException {
- mNewListener.callSessionMayHandover(srcAccessTech, targetAccessTech);
+ mNewListener.callSessionMayHandover(
+ ServiceState.rilRadioTechnologyToNetworkType(srcAccessTech),
+ ServiceState.rilRadioTechnologyToNetworkType(targetAccessTech));
}
@Override
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
index e55c3d0..aae6f92 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
@@ -16,7 +16,7 @@
package android.telephony.ims.compat.stub;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
index e2024742..ce291d4 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
@@ -16,7 +16,7 @@
package android.telephony.ims.compat.stub;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.ims.ImsCallForwardInfo;
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 72390d0..5d102cb4 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -60,15 +60,21 @@
* This feature supports emergency calling over MMTEL. If defined, the framework will try to
* place an emergency call over IMS first. If it is not defined, the framework will only use
* CSFB for emergency calling.
+ * @hide
*/
+ @SystemApi @TestApi
public static final int FEATURE_EMERGENCY_MMTEL = 0;
/**
* This feature supports the MMTEL feature.
+ * @hide
*/
+ @SystemApi @TestApi
public static final int FEATURE_MMTEL = 1;
/**
* This feature supports the RCS feature.
+ * @hide
*/
+ @SystemApi @TestApi
public static final int FEATURE_RCS = 2;
/**
* Total number of features defined
@@ -116,18 +122,24 @@
* This {@link ImsFeature}'s state is unavailable and should not be communicated with. This will
* remove all bindings back to the framework. Any attempt to communicate with the framework
* during this time will result in an {@link IllegalStateException}.
+ * @hide
*/
+ @SystemApi @TestApi
public static final int STATE_UNAVAILABLE = 0;
/**
* This {@link ImsFeature} state is initializing and should not be communicated with. This will
* remove all bindings back to the framework. Any attempt to communicate with the framework
* during this time will result in an {@link IllegalStateException}.
+ * @hide
*/
+ @SystemApi @TestApi
public static final int STATE_INITIALIZING = 1;
/**
* This {@link ImsFeature} is ready for communication. Do not attempt to call framework methods
- * until {@link #onFeatureReady()} is called.
+ * until {@see #onFeatureReady()} is called.
+ * @hide
*/
+ @SystemApi @TestApi
public static final int STATE_READY = 2;
/**
@@ -155,11 +167,15 @@
/**
* The capability was unable to be changed.
+ * @hide
*/
+ @SystemApi @TestApi
public static final int CAPABILITY_ERROR_GENERIC = -1;
/**
* The capability was able to be changed.
+ * @hide
*/
+ @SystemApi @TestApi
public static final int CAPABILITY_SUCCESS = 0;
/**
@@ -331,17 +347,20 @@
*
* @see SubscriptionManager#getSubscriptionIds(int) for more information on getting the
* subscription IDs associated with this slot.
+ * @hide
*/
+ @SystemApi @TestApi
public final int getSlotIndex() {
return mSlotId;
}
/**
- * @return The current state of the feature, defined as {@link #STATE_UNAVAILABLE},
- * {@link #STATE_INITIALIZING}, or {@link #STATE_READY}.
+ * @return The current state of the ImsFeature, set previously by {@link #setFeatureState(int)}
+ * or {@link #STATE_UNAVAILABLE} if it has not been updated yet.
* @hide
*/
- public int getFeatureState() {
+ @SystemApi @TestApi
+ public @ImsState int getFeatureState() {
synchronized (mLock) {
return mState;
}
@@ -352,7 +371,9 @@
* stop communication, depending on the state sent.
* @param state The ImsFeature's state, defined as {@link #STATE_UNAVAILABLE},
* {@link #STATE_INITIALIZING}, or {@link #STATE_READY}.
+ * @hide
*/
+ @SystemApi @TestApi
public final void setFeatureState(@ImsState int state) {
synchronized (mLock) {
if (mState != state) {
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 56c8771..0d5a979 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -52,14 +52,18 @@
*
* Any class wishing to use MmTelFeature should extend this class and implement all methods that the
* service supports.
- * @hide
*/
-@SystemApi
-@TestApi
public class MmTelFeature extends ImsFeature {
private static final String LOG_TAG = "MmTelFeature";
+ /**
+ * @hide
+ */
+ @SystemApi @TestApi
+ public MmTelFeature() {
+ }
+
private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() {
@Override
@@ -215,11 +219,11 @@
* {@link MmTelCapabilities#CAPABILITY_TYPE_SMS}.
*
* The capabilities of this MmTelFeature will be set by the framework and can be queried with
- * {@link #queryCapabilityStatus()}.
+ * {@see #queryCapabilityStatus()}.
*
* This MmTelFeature can then return the status of each of these capabilities (enabled or not)
- * by sending a {@link #notifyCapabilitiesStatusChanged} callback to the framework. The current
- * status can also be queried using {@link #queryCapabilityStatus()}.
+ * by sending a {@see #notifyCapabilitiesStatusChanged} callback to the framework. The current
+ * status can also be queried using {@see #queryCapabilityStatus()}.
* @see #isCapable(int)
*/
public static class MmTelCapabilities extends Capabilities {
@@ -228,13 +232,18 @@
* Create a new empty {@link MmTelCapabilities} instance.
* @see #addCapabilities(int)
* @see #removeCapabilities(int)
+ * @hide
*/
+ @SystemApi @TestApi
public MmTelCapabilities() {
super();
}
- /**@deprecated Use {@link MmTelCapabilities} to construct a new instance instead.*/
+ /**@deprecated Use {@link MmTelCapabilities} to construct a new instance instead.
+ * @hide
+ */
@Deprecated
+ @SystemApi @TestApi
public MmTelCapabilities(Capabilities c) {
mCapabilities = c.mCapabilities;
}
@@ -243,11 +252,17 @@
* Create a new {link @MmTelCapabilities} instance with the provided capabilities.
* @param capabilities The capabilities that are supported for MmTel in the form of a
* bitfield.
+ * @hide
*/
+ @SystemApi @TestApi
public MmTelCapabilities(@MmTelCapability int capabilities) {
super(capabilities);
}
+ /**
+ * @hide
+ */
+ @SystemApi @TestApi
@IntDef(flag = true,
value = {
CAPABILITY_TYPE_VOICE,
@@ -278,23 +293,39 @@
*/
public static final int CAPABILITY_TYPE_SMS = 1 << 3;
+ /**
+ * @hide
+ */
@Override
+ @SystemApi @TestApi
public final void addCapabilities(@MmTelCapability int capabilities) {
super.addCapabilities(capabilities);
}
+ /**
+ * @hide
+ */
@Override
+ @SystemApi @TestApi
public final void removeCapabilities(@MmTelCapability int capability) {
super.removeCapabilities(capability);
}
+ /**
+ * @hide
+ */
@Override
+ @SystemApi @TestApi
public final boolean isCapable(@MmTelCapability int capabilities) {
return super.isCapable(capabilities);
}
+ /**
+ * @hide
+ */
@NonNull
@Override
+ @SystemApi @TestApi
public String toString() {
StringBuilder builder = new StringBuilder("MmTel Capabilities - [");
builder.append("Voice: ");
@@ -319,8 +350,10 @@
/**
* Called when the IMS provider receives an incoming call.
* @param c The {@link ImsCallSession} associated with the new call.
+ * @hide
*/
@Override
+ @SystemApi @TestApi
public void onIncomingCall(IImsCallSession c, Bundle extras) {
}
@@ -329,8 +362,10 @@
* Called when the IMS provider implicitly rejects an incoming call during setup.
* @param callProfile An {@link ImsCallProfile} with the call details.
* @param reason The {@link ImsReasonInfo} reason for call rejection.
+ * @hide
*/
@Override
+ @SystemApi @TestApi
public void onRejectedCall(ImsCallProfile callProfile, ImsReasonInfo reason) {
}
@@ -338,8 +373,10 @@
/**
* Updates the Listener when the voice message count for IMS has changed.
* @param count an integer representing the new message count.
+ * @hide
*/
@Override
+ @SystemApi @TestApi
public void onVoiceMessageCountUpdate(int count) {
}
@@ -348,14 +385,22 @@
/**
* To be returned by {@link #shouldProcessCall(String[])} when the ImsService should process the
* outgoing call as IMS.
+ * @hide
*/
+ @SystemApi @TestApi
public static final int PROCESS_CALL_IMS = 0;
/**
* To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should
* not process the outgoing call as IMS and should instead use circuit switch.
+ * @hide
*/
+ @SystemApi @TestApi
public static final int PROCESS_CALL_CSFB = 1;
+ /**
+ * @hide
+ */
+ @SystemApi @TestApi
@IntDef(flag = true,
value = {
PROCESS_CALL_IMS,
@@ -368,7 +413,9 @@
* If the flag is present and true, it indicates that the incoming call is for USSD.
* <p>
* This is an optional boolean flag.
+ * @hide
*/
+ @SystemApi @TestApi
public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
/**
@@ -379,7 +426,9 @@
* certain situations.
* <p>
* This is an optional boolean flag.
+ * @hide
*/
+ @SystemApi @TestApi
public static final String EXTRA_IS_UNKNOWN_CALL =
"android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
@@ -388,6 +437,7 @@
/**
* @param listener A {@link Listener} used when the MmTelFeature receives an incoming call and
* notifies the framework.
+ * @hide
*/
private void setListener(IImsMmTelListener listener) {
synchronized (mLock) {
@@ -406,9 +456,11 @@
* Should be a subset of the capabilities that are enabled by the framework in
* {@link #changeEnabledCapabilities}.
* @return A copy of the current MmTelFeature capability status.
+ * @hide
*/
@Override
- public final MmTelCapabilities queryCapabilityStatus() {
+ @SystemApi @TestApi
+ public @NonNull final MmTelCapabilities queryCapabilityStatus() {
return new MmTelCapabilities(super.queryCapabilityStatus());
}
@@ -420,7 +472,9 @@
* the status of that capability is disabled. This can happen if the network does not currently
* support the capability that is enabled. A capability that is disabled by the framework (via
* {@link #changeEnabledCapabilities}) should also show the status as disabled.
+ * @hide
*/
+ @SystemApi @TestApi
public final void notifyCapabilitiesStatusChanged(@NonNull MmTelCapabilities c) {
if (c == null) {
throw new IllegalArgumentException("MmTelCapabilities must be non-null!");
@@ -433,7 +487,9 @@
* @param c The {@link ImsCallSessionImplBase} of the new incoming call.
* @param extras A bundle containing extra parameters related to the call. See
* {@link #EXTRA_IS_UNKNOWN_CALL} and {@link #EXTRA_IS_USSD} above.
+ * @hide
*/
+ @SystemApi @TestApi
public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c,
@NonNull Bundle extras) {
if (c == null || extras == null) {
@@ -458,7 +514,9 @@
* @param callProfile The {@link ImsCallProfile} IMS call profile with details.
* This can be null if no call information is available for the rejected call.
* @param reason The {@link ImsReasonInfo} call rejection reason.
+ * * @hide
*/
+ @SystemApi @TestApi
public final void notifyRejectedCall(@NonNull ImsCallProfile callProfile,
@NonNull ImsReasonInfo reason) {
if (callProfile == null || reason == null) {
@@ -497,7 +555,9 @@
/**
* Notify the framework of a change in the Voice Message count.
* @link count the new Voice Message count.
+ * @hide
*/
+ @SystemApi @TestApi
public final void notifyVoiceMessageCountUpdate(int count) {
synchronized (mLock) {
if (mListener == null) {
@@ -518,8 +578,10 @@
* status for capability A.
* @param capability The capability that we are querying the configuration for.
* @return true if the capability is enabled, false otherwise.
+ * @hide
*/
@Override
+ @SystemApi @TestApi
public boolean queryCapabilityConfiguration(@MmTelCapabilities.MmTelCapability int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
// Base implementation - Override to provide functionality
@@ -537,8 +599,10 @@
* Enabling/Disabling a capability here indicates that the capability should be registered or
* deregistered (depending on the capability change) and become available or unavailable to
* the framework.
+ * * @hide
*/
@Override
+ @SystemApi @TestApi
public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request,
@NonNull CapabilityCallbackProxy c) {
// Base implementation, no-op
@@ -561,7 +625,9 @@
* {@link ImsCallProfile#CALL_TYPE_VS_TX}
* {@link ImsCallProfile#CALL_TYPE_VS_RX}
* @return a {@link ImsCallProfile} object
+ * @hide
*/
+ @SystemApi @TestApi
public @Nullable ImsCallProfile createCallProfile(int callSessionType, int callType) {
// Base Implementation - Should be overridden
return null;
@@ -582,7 +648,9 @@
* {@link ImsCallSession} directly.
*
* @param profile a call profile to make the call
+ * @hide
*/
+ @SystemApi @TestApi
public @Nullable ImsCallSessionImplBase createCallSession(@NonNull ImsCallProfile profile) {
// Base Implementation - Should be overridden
return null;
@@ -599,7 +667,9 @@
* call as a conference.
* @return a {@link ProcessCallResult} to the framework, which will be used to determine if the
* call will be placed over IMS or via CSFB.
+ * @hide
*/
+ @SystemApi @TestApi
public @ProcessCallResult int shouldProcessCall(@NonNull String[] numbers) {
return PROCESS_CALL_IMS;
}
@@ -632,7 +702,9 @@
/**
* @return The {@link ImsUtImplBase} Ut interface implementation for the supplementary service
* configuration.
+ * @hide
*/
+ @SystemApi @TestApi
public @NonNull ImsUtImplBase getUt() {
// Base Implementation - Should be overridden
return new ImsUtImplBase();
@@ -641,7 +713,9 @@
/**
* @return The {@link ImsEcbmImplBase} Emergency call-back mode interface for emergency VoLTE
* calls that support it.
+ * @hide
*/
+ @SystemApi @TestApi
public @NonNull ImsEcbmImplBase getEcbm() {
// Base Implementation - Should be overridden
return new ImsEcbmImplBase();
@@ -650,7 +724,9 @@
/**
* @return The {@link ImsMultiEndpointImplBase} implementation for implementing Dialog event
* package processing for multi-endpoint.
+ * @hide
*/
+ @SystemApi @TestApi
public @NonNull ImsMultiEndpointImplBase getMultiEndpoint() {
// Base Implementation - Should be overridden
return new ImsMultiEndpointImplBase();
@@ -676,7 +752,9 @@
* // Remote side is dead
* }
* }
+ * @hide
*/
+ @SystemApi @TestApi
public void setUiTtyMode(int mode, @Nullable Message onCompleteMessage) {
// Base Implementation - Should be overridden
}
@@ -710,7 +788,9 @@
*
* @return an instance of {@link ImsSmsImplBase} which should be implemented by the IMS
* Provider.
+ * @hide
*/
+ @SystemApi @TestApi
public @NonNull ImsSmsImplBase getSmsImplementation() {
return new ImsSmsImplBase();
}
@@ -719,14 +799,22 @@
return getSmsImplementation().getSmsFormat();
}
- /**{@inheritDoc}*/
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
@Override
+ @SystemApi @TestApi
public void onFeatureRemoved() {
// Base Implementation - Should be overridden
}
- /**{@inheritDoc}*/
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
@Override
+ @SystemApi @TestApi
public void onFeatureReady() {
// Base Implementation - Should be overridden
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 4c0de7f..e0d576d 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -17,12 +17,14 @@
package android.telephony.ims.stub;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.Context;
import android.os.PersistableBundle;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
import android.util.Log;
@@ -199,6 +201,12 @@
}
}
+ @Override
+ public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed)
+ throws RemoteException {
+ getImsConfigImpl().notifyRcsAutoConfigurationReceived(config, isCompressed);
+ }
+
private void notifyImsConfigChanged(int item, int value) throws RemoteException {
getImsConfigImpl().notifyConfigChanged(item, value);
}
@@ -228,7 +236,8 @@
* The configuration requested resulted in an unknown result. This may happen if the
* IMS configurations are unavailable.
*/
- public static final int CONFIG_RESULT_UNKNOWN = -1;
+ public static final int CONFIG_RESULT_UNKNOWN = ProvisioningManager.PROVISIONING_RESULT_UNKNOWN;
+
/**
* Setting the configuration value completed.
*/
@@ -355,9 +364,9 @@
* @param config The XML file to be read, if not compressed, it should be in ASCII/UTF8 format.
* @param isCompressed The XML file is compressed in gzip format and must be decompressed
* before being read.
- * @hide
+ *
*/
- public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed) {
+ public void notifyRcsAutoConfigurationReceived(@NonNull byte[] config, boolean isCompressed) {
}
/**
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index feac3c2..3ec4f34 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -16,6 +16,7 @@
package android.telephony.ims.stub;
+import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.os.Bundle;
@@ -25,6 +26,9 @@
import com.android.ims.internal.IImsUt;
import com.android.ims.internal.IImsUtListener;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Base implementation of IMS UT interface, which implements stubs. Override these methods to
* implement functionality.
@@ -36,6 +40,70 @@
@SystemApi
@TestApi
public class ImsUtImplBase {
+ /**
+ * Bar all incoming calls. (See 3GPP TS 24.611)
+ */
+ public static final int CALL_BARRING_ALL_INCOMING = 1;
+
+ /**
+ * Bar all outgoing calls. (See 3GPP TS 24.611)
+ */
+ public static final int CALL_BARRING_ALL_OUTGOING = 2;
+
+ /**
+ * Bar all outgoing international calls. (See 3GPP TS 24.611)
+ */
+ public static final int CALL_BARRING_OUTGOING_INTL = 3;
+
+ /**
+ * Bar all outgoing international calls, excluding those to the home PLMN country
+ * (See 3GPP TS 24.611)
+ */
+ public static final int CALL_BARRING_OUTGOING_INTL_EXCL_HOME = 4;
+
+ /**
+ * Bar all incoming calls when roaming (See 3GPP TS 24.611)
+ */
+ public static final int CALL_BLOCKING_INCOMING_WHEN_ROAMING = 5;
+
+ /**
+ * Enable Anonymous Communication Rejection (See 3GPP TS 24.611)
+ */
+ public static final int CALL_BARRING_ANONYMOUS_INCOMING = 6;
+
+ /**
+ * Bar all incoming and outgoing calls. (See 3GPP TS 24.611)
+ */
+ public static final int CALL_BARRING_ALL = 7;
+
+ /**
+ * Bar all outgoing service requests, including calls. (See 3GPP TS 24.611)
+ */
+ public static final int CALL_BARRING_OUTGOING_ALL_SERVICES = 8;
+
+ /**
+ * Bar all incoming service requests, including calls. (See 3GPP TS 24.611)
+ */
+ public static final int CALL_BARRING_INCOMING_ALL_SERVICES = 9;
+
+ /**
+ * Bar specific incoming calls. (See 3GPP TS 24.611)
+ */
+ public static final int CALL_BARRING_SPECIFIC_INCOMING_CALLS = 10;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "CALL_BARRING_", value = {CALL_BARRING_ALL_INCOMING, CALL_BARRING_ALL_OUTGOING,
+ CALL_BARRING_OUTGOING_INTL, CALL_BARRING_OUTGOING_INTL_EXCL_HOME,
+ CALL_BLOCKING_INCOMING_WHEN_ROAMING, CALL_BARRING_ANONYMOUS_INCOMING,
+ CALL_BARRING_ALL, CALL_BARRING_OUTGOING_ALL_SERVICES,
+ CALL_BARRING_INCOMING_ALL_SERVICES, CALL_BARRING_SPECIFIC_INCOMING_CALLS})
+ public @interface CallBarringMode {}
+
+ /**
+ * Constant used to denote an invalid return value.
+ */
+ public static final int INVALID_RESULT = -1;
private IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
@Override
@@ -247,15 +315,15 @@
/**
* Updates the configuration of the call barring.
*/
- public int updateCallBarring(int cbType, int action, String[] barrList) {
+ public int updateCallBarring(@CallBarringMode int cbType, int action, String[] barrList) {
return -1;
}
/**
* Updates the configuration of the call barring for specified service class.
*/
- public int updateCallBarringForServiceClass(int cbType, int action, String[] barrList,
- int serviceClass) {
+ public int updateCallBarringForServiceClass(@CallBarringMode int cbType, int action,
+ String[] barrList, int serviceClass) {
return -1;
}
diff --git a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
index 055fca5..bb03448 100644
--- a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
@@ -113,6 +113,51 @@
})
public @interface PresenceResponseCode {}
+
+ /** A capability update has been requested due to the Entity Tag (ETag) expiring. */
+ public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0;
+ /** A capability update has been requested due to moving to LTE with VoPS disabled. */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1;
+ /** A capability update has been requested due to moving to LTE with VoPS enabled. */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2;
+ /** A capability update has been requested due to moving to eHRPD. */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3;
+ /** A capability update has been requested due to moving to HSPA+. */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4;
+ /** A capability update has been requested due to moving to 3G. */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5;
+ /** A capability update has been requested due to moving to 2G. */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6;
+ /** A capability update has been requested due to moving to WLAN */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7;
+ /** A capability update has been requested due to moving to IWLAN */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8;
+ /** A capability update has been requested but the reason is unknown. */
+ public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9;
+ /** A capability update has been requested due to moving to 5G NR with VoPS disabled. */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10;
+ /** A capability update has been requested due to moving to 5G NR with VoPS enabled. */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11;
+
+ /** @hide*/
+ @IntDef(value = {
+ CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN,
+ CAPABILITY_UPDATE_TRIGGER_UNKNOWN,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED
+ }, prefix = "CAPABILITY_UPDATE_TRIGGER_")
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StackPublishTriggerType {
+ }
+
/**
* Provide the framework with a subsequent network response update to
* {@link #updateCapabilities(RcsContactUceCapability, int)} and
@@ -164,15 +209,18 @@
* This is typically used when trying to generate an initial PUBLISH for a new subscription to
* the network. The device will cache all presence publications after boot until this method is
* called once.
+ * @param publishTriggerType {@link StackPublishTriggerType} The reason for the capability
+ * update request.
* @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently
* connected to the framework. This can happen if the {@link RcsFeature} is not
* {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
* {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
* Telephony stack has crashed.
*/
- public final void onNotifyUpdateCapabilites() throws ImsException {
+ public final void onNotifyUpdateCapabilites(@StackPublishTriggerType int publishTriggerType)
+ throws ImsException {
try {
- getListener().onNotifyUpdateCapabilities();
+ getListener().onNotifyUpdateCapabilities(publishTriggerType);
} catch (RemoteException e) {
throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index 4fc6a19..0f6ce13 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -17,15 +17,16 @@
package com.android.ims;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.RemoteException;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
+import com.android.internal.telephony.util.HandlerExecutor;
+
import java.util.concurrent.Executor;
/**
@@ -134,363 +135,596 @@
/**
* AMR CODEC Mode Value set, 0-7 in comma separated sequence.
* Value is in String format.
+ * @deprecated use {@link ProvisioningManager#KEY_AMR_CODEC_MODE_SET_VALUES} instead.
*/
- public static final int VOCODER_AMRMODESET = CONFIG_START;
+ @Deprecated
+ public static final int VOCODER_AMRMODESET =
+ ProvisioningManager.KEY_AMR_CODEC_MODE_SET_VALUES;
/**
* Wide Band AMR CODEC Mode Value set,0-7 in comma separated sequence.
* Value is in String format.
+ * @deprecated use {@link ProvisioningManager#KEY_AMR_WB_CODEC_MODE_SET_VALUES} instead.
*/
- public static final int VOCODER_AMRWBMODESET = 1;
+ @Deprecated
+ public static final int VOCODER_AMRWBMODESET =
+ ProvisioningManager.KEY_AMR_WB_CODEC_MODE_SET_VALUES;
/**
* SIP Session Timer value (seconds).
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_SIP_SESSION_TIMER_SEC} instead.
*/
- public static final int SIP_SESSION_TIMER = 2;
+ @Deprecated
+ public static final int SIP_SESSION_TIMER = ProvisioningManager.KEY_SIP_SESSION_TIMER_SEC;
/**
* Minimum SIP Session Expiration Timer in (seconds).
* Value is in Integer format.
+ * @deprecated use
+ * {@link ProvisioningManager#KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC} instead.
*/
- public static final int MIN_SE = 3;
+ @Deprecated
+ public static final int MIN_SE =
+ ProvisioningManager.KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC;
/**
* SIP_INVITE cancellation time out value (in milliseconds). Integer format.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_SIP_INVITE_CANCELLATION_TIMER_MS} instead.
*/
- public static final int CANCELLATION_TIMER = 4;
+ @Deprecated
+ public static final int CANCELLATION_TIMER =
+ ProvisioningManager.KEY_SIP_INVITE_CANCELLATION_TIMER_MS;
/**
* Delay time when an iRAT transition from eHRPD/HRPD/1xRTT to LTE.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_TRANSITION_TO_LTE_DELAY_MS} instead.
*/
- public static final int TDELAY = 5;
+ @Deprecated
+ public static final int TDELAY = ProvisioningManager.KEY_TRANSITION_TO_LTE_DELAY_MS;
/**
* Silent redial status of Enabled (True), or Disabled (False).
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_ENABLE_SILENT_REDIAL} instead.
*/
- public static final int SILENT_REDIAL_ENABLE = 6;
+ @Deprecated
+ public static final int SILENT_REDIAL_ENABLE = ProvisioningManager.KEY_ENABLE_SILENT_REDIAL;
/**
* SIP T1 timer value in milliseconds. See RFC 3261 for define.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_T1_TIMER_VALUE_MS} instead.
*/
- public static final int SIP_T1_TIMER = 7;
+ @Deprecated
+ public static final int SIP_T1_TIMER = ProvisioningManager.KEY_T1_TIMER_VALUE_MS;
/**
* SIP T2 timer value in milliseconds. See RFC 3261 for define.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_T2_TIMER_VALUE_MS} instead.
*/
- public static final int SIP_T2_TIMER = 8;
+ @Deprecated
+ public static final int SIP_T2_TIMER = ProvisioningManager.KEY_T2_TIMER_VALUE_MS;
- /**
+ /**
* SIP TF timer value in milliseconds. See RFC 3261 for define.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_TF_TIMER_VALUE_MS} instead.
*/
- public static final int SIP_TF_TIMER = 9;
+ @Deprecated
+ public static final int SIP_TF_TIMER = ProvisioningManager.KEY_TF_TIMER_VALUE_MS;
/**
* VoLTE status for VLT/s status of Enabled (1), or Disabled (0).
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_VOLTE_PROVISIONING_STATUS} instead.
*/
- public static final int VLT_SETTING_ENABLED = 10;
+ @Deprecated
+ public static final int VLT_SETTING_ENABLED =
+ ProvisioningManager.KEY_VOLTE_PROVISIONING_STATUS;
/**
* VoLTE status for LVC/s status of Enabled (1), or Disabled (0).
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_VT_PROVISIONING_STATUS} instead.
*/
- public static final int LVC_SETTING_ENABLED = 11;
+ @Deprecated
+ public static final int LVC_SETTING_ENABLED =
+ ProvisioningManager.KEY_VT_PROVISIONING_STATUS;
+
/**
* Domain Name for the device to populate the request URI for REGISTRATION.
* Value is in String format.
+ * @deprecated use {@link ProvisioningManager#KEY_REGISTRATION_DOMAIN_NAME}.
*/
- public static final int DOMAIN_NAME = 12;
+ @Deprecated
+ public static final int DOMAIN_NAME = ProvisioningManager.KEY_REGISTRATION_DOMAIN_NAME;
+
/**
* Device Outgoing SMS based on either 3GPP or 3GPP2 standards.
* Value is in Integer format. 3GPP2(0), 3GPP(1)
- */
- public static final int SMS_FORMAT = 13;
+ * @deprecated use {@link ProvisioningManager#KEY_SMS_FORMAT}.
+ */
+ @Deprecated
+ public static final int SMS_FORMAT = ProvisioningManager.KEY_SMS_FORMAT;
+
/**
* Turns IMS ON/OFF on the device.
* Value is in Integer format. ON (1), OFF(0).
- */
- public static final int SMS_OVER_IP = 14;
+ * @deprecated use {@link ProvisioningManager#KEY_SMS_OVER_IP_ENABLED}.
+ */
+ @Deprecated
+ public static final int SMS_OVER_IP = ProvisioningManager.KEY_SMS_OVER_IP_ENABLED;
+
/**
* Requested expiration for Published Online availability.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RCS_PUBLISH_TIMER_SEC}.
*/
- public static final int PUBLISH_TIMER = 15;
+ @Deprecated
+ public static final int PUBLISH_TIMER = ProvisioningManager.KEY_RCS_PUBLISH_TIMER_SEC;
+
/**
* Requested expiration for Published Offline availability.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC}.
*/
- public static final int PUBLISH_TIMER_EXTENDED = 16;
+ @Deprecated
+ public static final int PUBLISH_TIMER_EXTENDED =
+ ProvisioningManager.KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC;
+
/**
*
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RCS_CAPABILITY_DISCOVERY_ENABLED}.
*/
- public static final int CAPABILITY_DISCOVERY_ENABLED = 17;
+ @Deprecated
+ public static final int CAPABILITY_DISCOVERY_ENABLED =
+ ProvisioningManager.KEY_RCS_CAPABILITY_DISCOVERY_ENABLED;
+
/**
- * Period of time the capability information of the contact is cached on handset.
+ * Period of time the capability information of the contact is cached on handset.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC}.
*/
- public static final int CAPABILITIES_CACHE_EXPIRATION = 18;
+ @Deprecated
+ public static final int CAPABILITIES_CACHE_EXPIRATION =
+ ProvisioningManager.KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC;
+
/**
* Peiod of time the availability information of a contact is cached on device.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC}.
*/
- public static final int AVAILABILITY_CACHE_EXPIRATION = 19;
+ @Deprecated
+ public static final int AVAILABILITY_CACHE_EXPIRATION =
+ ProvisioningManager.KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC;
+
/**
* Interval between successive capabilities polling.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RCS_CAPABILITIES_POLL_INTERVAL_SEC}.
*/
- public static final int CAPABILITIES_POLL_INTERVAL = 20;
+ @Deprecated
+ public static final int CAPABILITIES_POLL_INTERVAL =
+ ProvisioningManager.KEY_RCS_CAPABILITIES_POLL_INTERVAL_SEC;
+
/**
* Minimum time between two published messages from the device.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS}.
*/
- public static final int SOURCE_THROTTLE_PUBLISH = 21;
+ @Deprecated
+ public static final int SOURCE_THROTTLE_PUBLISH =
+ ProvisioningManager.KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS;
+
/**
* The Maximum number of MDNs contained in one Request Contained List.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RCS_MAX_NUM_ENTRIES_IN_RCL}.
*/
- public static final int MAX_NUMENTRIES_IN_RCL = 22;
+ @Deprecated
+ public static final int MAX_NUMENTRIES_IN_RCL =
+ ProvisioningManager.KEY_RCS_MAX_NUM_ENTRIES_IN_RCL;
+
/**
* Expiration timer for subscription of a Request Contained List, used in capability
* polling.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC}.
*/
- public static final int CAPAB_POLL_LIST_SUB_EXP = 23;
+ @Deprecated
+ public static final int CAPAB_POLL_LIST_SUB_EXP =
+ ProvisioningManager.KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC;
+
/**
* Applies compression to LIST Subscription.
* Value is in Integer format. Enable (1), Disable(0).
+ * @deprecated use {@link ProvisioningManager#KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION}.
*/
- public static final int GZIP_FLAG = 24;
+ @Deprecated
+ public static final int GZIP_FLAG = ProvisioningManager.KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION;
+
/**
* VOLTE Status for EAB/s status of Enabled (1), or Disabled (0).
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_EAB_PROVISIONING_STATUS}.
*/
- public static final int EAB_SETTING_ENABLED = 25;
+ @Deprecated
+ public static final int EAB_SETTING_ENABLED =
+ ProvisioningManager.KEY_EAB_PROVISIONING_STATUS;
+
/**
* Wi-Fi calling roaming status.
* Value is in Integer format. ON (1), OFF(0).
+ * @deprecated use {@link ProvisioningManager#KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE}
+ * instead.
*/
+ @Deprecated
public static final int VOICE_OVER_WIFI_ROAMING =
ProvisioningManager.KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE;
+
/**
- * Wi-Fi calling modem - WfcModeFeatureValueConstants.
+ * Wi-Fi calling mode - WfcModeFeatureValueConstants.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_VOICE_OVER_WIFI_MODE_OVERRIDE}
+ * instead.
*/
+ @Deprecated
public static final int VOICE_OVER_WIFI_MODE =
ProvisioningManager.KEY_VOICE_OVER_WIFI_MODE_OVERRIDE;
+
/**
* VOLTE Status for voice over wifi status of Enabled (1), or Disabled (0).
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE}.
*/
- public static final int VOICE_OVER_WIFI_SETTING_ENABLED = 28;
+ @Deprecated
+ public static final int VOICE_OVER_WIFI_SETTING_ENABLED =
+ ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE;
+
+
/**
* Mobile data enabled.
* Value is in Integer format. On (1), OFF(0).
+ * @deprecated use {@link ProvisioningManager#KEY_MOBILE_DATA_ENABLED}.
*/
- public static final int MOBILE_DATA_ENABLED = 29;
+ @Deprecated
+ public static final int MOBILE_DATA_ENABLED = ProvisioningManager.KEY_MOBILE_DATA_ENABLED;
+
/**
* VoLTE user opted in status.
* Value is in Integer format. Opted-in (1) Opted-out (0).
+ * @deprecated use {@link ProvisioningManager#KEY_VOLTE_USER_OPT_IN_STATUS}.
*/
- public static final int VOLTE_USER_OPT_IN_STATUS = 30;
+ @Deprecated
+ public static final int VOLTE_USER_OPT_IN_STATUS =
+ ProvisioningManager.KEY_VOLTE_USER_OPT_IN_STATUS;
+
/**
* Proxy for Call Session Control Function(P-CSCF) address for Local-BreakOut(LBO).
* Value is in String format.
+ * @deprecated use {@link ProvisioningManager#KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS}.
*/
- public static final int LBO_PCSCF_ADDRESS = 31;
+ @Deprecated
+ public static final int LBO_PCSCF_ADDRESS =
+ ProvisioningManager.KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS;
+
/**
* Keep Alive Enabled for SIP.
* Value is in Integer format. On(1), OFF(0).
+ * @deprecated use {@link ProvisioningManager#KEY_SIP_KEEP_ALIVE_ENABLED}.
*/
- public static final int KEEP_ALIVE_ENABLED = 32;
+ @Deprecated
+ public static final int KEEP_ALIVE_ENABLED = ProvisioningManager.KEY_SIP_KEEP_ALIVE_ENABLED;
+
/**
* Registration retry Base Time value in seconds.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_REGISTRATION_RETRY_BASE_TIME_SEC}.
*/
- public static final int REGISTRATION_RETRY_BASE_TIME_SEC = 33;
+ @Deprecated
+ public static final int REGISTRATION_RETRY_BASE_TIME_SEC =
+ ProvisioningManager.KEY_REGISTRATION_RETRY_BASE_TIME_SEC;
+
/**
* Registration retry Max Time value in seconds.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_REGISTRATION_RETRY_MAX_TIME_SEC}.
*/
- public static final int REGISTRATION_RETRY_MAX_TIME_SEC = 34;
+ @Deprecated
+ public static final int REGISTRATION_RETRY_MAX_TIME_SEC =
+ ProvisioningManager.KEY_REGISTRATION_RETRY_MAX_TIME_SEC;
+
/**
* Smallest RTP port for speech codec.
* Value is in integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RTP_SPEECH_START_PORT}.
*/
- public static final int SPEECH_START_PORT = 35;
+ @Deprecated
+ public static final int SPEECH_START_PORT = ProvisioningManager.KEY_RTP_SPEECH_START_PORT;
+
/**
* Largest RTP port for speech code.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RTP_SPEECH_END_PORT}.
*/
- public static final int SPEECH_END_PORT = 36;
+ @Deprecated
+ public static final int SPEECH_END_PORT = ProvisioningManager.KEY_RTP_SPEECH_END_PORT;
+
/**
* SIP Timer A's value in milliseconds. Timer A is the INVITE request
* retransmit interval, for UDP only.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS}.
*/
- public static final int SIP_INVITE_REQ_RETX_INTERVAL_MSEC = 37;
+ @Deprecated
+ public static final int SIP_INVITE_REQ_RETX_INTERVAL_MSEC =
+ ProvisioningManager.KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS;
+
/**
* SIP Timer B's value in milliseconds. Timer B is the wait time for
* INVITE message to be acknowledged.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_SIP_INVITE_ACK_WAIT_TIME_MS}.
*/
- public static final int SIP_INVITE_RSP_WAIT_TIME_MSEC = 38;
+ @Deprecated
+ public static final int SIP_INVITE_RSP_WAIT_TIME_MSEC =
+ ProvisioningManager.KEY_SIP_INVITE_ACK_WAIT_TIME_MS;
+
/**
* SIP Timer D's value in milliseconds. Timer D is the wait time for
* response retransmits of the invite client transactions.
* Value is in Integer format.
+ * @deprecated use
+ * {@link ProvisioningManager#KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS}.
*/
- public static final int SIP_INVITE_RSP_RETX_WAIT_TIME_MSEC = 39;
+ @Deprecated
+ public static final int SIP_INVITE_RSP_RETX_WAIT_TIME_MSEC =
+ ProvisioningManager.KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS;
+
/**
* SIP Timer E's value in milliseconds. Timer E is the value Non-INVITE
* request retransmit interval, for UDP only.
* Value is in Integer format.
+ * @deprecated use
+ * {@link ProvisioningManager#KEY_SIP_NON_INVITE_REQUEST_RETRANSMIT_INTERVAL_MS}.
*/
- public static final int SIP_NON_INVITE_REQ_RETX_INTERVAL_MSEC = 40;
+ @Deprecated
+ public static final int SIP_NON_INVITE_REQ_RETX_INTERVAL_MSEC =
+ ProvisioningManager.KEY_SIP_NON_INVITE_REQUEST_RETRANSMIT_INTERVAL_MS;
+
/**
* SIP Timer F's value in milliseconds. Timer F is the Non-INVITE transaction
* timeout timer.
* Value is in Integer format.
+ * @deprecated use
+ * {@link ProvisioningManager#KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS}.
*/
- public static final int SIP_NON_INVITE_TXN_TIMEOUT_TIMER_MSEC = 41;
+ @Deprecated
+ public static final int SIP_NON_INVITE_TXN_TIMEOUT_TIMER_MSEC =
+ ProvisioningManager.KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS;
+
/**
* SIP Timer G's value in milliseconds. Timer G is the value of INVITE response
* retransmit interval.
* Value is in Integer format.
+ * @deprecated use
+ * {@link ProvisioningManager#KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS}.
*/
- public static final int SIP_INVITE_RSP_RETX_INTERVAL_MSEC = 42;
+ @Deprecated
+ public static final int SIP_INVITE_RSP_RETX_INTERVAL_MSEC =
+ ProvisioningManager.KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS;
+
/**
* SIP Timer H's value in milliseconds. Timer H is the value of wait time for
* ACK receipt.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS}.
*/
- public static final int SIP_ACK_RECEIPT_WAIT_TIME_MSEC = 43;
+ @Deprecated
+ public static final int SIP_ACK_RECEIPT_WAIT_TIME_MSEC =
+ ProvisioningManager.KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS;
+
/**
* SIP Timer I's value in milliseconds. Timer I is the value of wait time for
* ACK retransmits.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS}.
*/
- public static final int SIP_ACK_RETX_WAIT_TIME_MSEC = 44;
+ @Deprecated
+ public static final int SIP_ACK_RETX_WAIT_TIME_MSEC =
+ ProvisioningManager.KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS;
+
/**
* SIP Timer J's value in milliseconds. Timer J is the value of wait time for
* non-invite request retransmission.
* Value is in Integer format.
+ * @deprecated use
+ * {@link ProvisioningManager#KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS}.
*/
- public static final int SIP_NON_INVITE_REQ_RETX_WAIT_TIME_MSEC = 45;
+ @Deprecated
+ public static final int SIP_NON_INVITE_REQ_RETX_WAIT_TIME_MSEC =
+ ProvisioningManager.KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS;
+
/**
* SIP Timer K's value in milliseconds. Timer K is the value of wait time for
* non-invite response retransmits.
* Value is in Integer format.
+ * @deprecated use
+ * {@link ProvisioningManager#KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS}.
*/
- public static final int SIP_NON_INVITE_RSP_RETX_WAIT_TIME_MSEC = 46;
+ @Deprecated
+ public static final int SIP_NON_INVITE_RSP_RETX_WAIT_TIME_MSEC =
+ ProvisioningManager.KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS;
+
/**
* AMR WB octet aligned dynamic payload type.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE}.
*/
- public static final int AMR_WB_OCTET_ALIGNED_PT = 47;
+ @Deprecated
+ public static final int AMR_WB_OCTET_ALIGNED_PT =
+ ProvisioningManager.KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE;
+
/**
* AMR WB bandwidth efficient payload type.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE}.
*/
- public static final int AMR_WB_BANDWIDTH_EFFICIENT_PT = 48;
+ @Deprecated
+ public static final int AMR_WB_BANDWIDTH_EFFICIENT_PT =
+ ProvisioningManager.KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE;
+
/**
* AMR octet aligned dynamic payload type.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE}.
*/
- public static final int AMR_OCTET_ALIGNED_PT = 49;
+ @Deprecated
+ public static final int AMR_OCTET_ALIGNED_PT =
+ ProvisioningManager.KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE;
+
/**
* AMR bandwidth efficient payload type.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE}.
*/
- public static final int AMR_BANDWIDTH_EFFICIENT_PT = 50;
+ @Deprecated
+ public static final int AMR_BANDWIDTH_EFFICIENT_PT =
+ ProvisioningManager.KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE;
+
/**
* DTMF WB payload type.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_DTMF_WB_PAYLOAD_TYPE}.
*/
- public static final int DTMF_WB_PT = 51;
+ @Deprecated
+ public static final int DTMF_WB_PT = ProvisioningManager.KEY_DTMF_WB_PAYLOAD_TYPE;
+
/**
* DTMF NB payload type.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_DTMF_NB_PAYLOAD_TYPE}.
*/
- public static final int DTMF_NB_PT = 52;
+ @Deprecated
+ public static final int DTMF_NB_PT = ProvisioningManager.KEY_DTMF_NB_PAYLOAD_TYPE;
+
/**
* AMR Default encoding mode.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_AMR_DEFAULT_ENCODING_MODE}.
*/
- public static final int AMR_DEFAULT_MODE = 53;
+ @Deprecated
+ public static final int AMR_DEFAULT_MODE =
+ ProvisioningManager.KEY_AMR_DEFAULT_ENCODING_MODE;
+
/**
* SMS Public Service Identity.
* Value is in String format.
+ * @deprecated use {@link ProvisioningManager#KEY_SMS_PUBLIC_SERVICE_IDENTITY}.
*/
- public static final int SMS_PSI = 54;
+ @Deprecated
+ public static final int SMS_PSI = ProvisioningManager.KEY_SMS_PUBLIC_SERVICE_IDENTITY;
+
/**
* Video Quality - VideoQualityFeatureValuesConstants.
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_VIDEO_QUALITY}.
*/
- public static final int VIDEO_QUALITY = 55;
+ @Deprecated
+ public static final int VIDEO_QUALITY = ProvisioningManager.KEY_VIDEO_QUALITY;
+
/**
* LTE threshold.
* Handover from LTE to WiFi if LTE < THLTE1 and WiFi >= VOWT_A.
+ * @deprecated use {@link ProvisioningManager#KEY_LTE_THRESHOLD_1}.
*/
- public static final int TH_LTE1 = 56;
+ @Deprecated
+ public static final int TH_LTE1 = ProvisioningManager.KEY_LTE_THRESHOLD_1;
+
/**
* LTE threshold.
* Handover from WiFi to LTE if LTE >= THLTE3 or (WiFi < VOWT_B and LTE >= THLTE2).
+ * @deprecated use {@link ProvisioningManager#KEY_LTE_THRESHOLD_2}.
*/
- public static final int TH_LTE2 = 57;
+ @Deprecated
+ public static final int TH_LTE2 = ProvisioningManager.KEY_LTE_THRESHOLD_2;
+
/**
* LTE threshold.
* Handover from WiFi to LTE if LTE >= THLTE3 or (WiFi < VOWT_B and LTE >= THLTE2).
+ * @deprecated use {@link ProvisioningManager#KEY_LTE_THRESHOLD_3}.
*/
- public static final int TH_LTE3 = 58;
+ @Deprecated
+ public static final int TH_LTE3 = ProvisioningManager.KEY_LTE_THRESHOLD_3;
+
/**
* 1x threshold.
* Handover from 1x to WiFi if 1x < TH1x
+ * @deprecated use {@link ProvisioningManager#KEY_1X_THRESHOLD}.
*/
- public static final int TH_1x = 59;
+ @Deprecated
+ public static final int TH_1x = ProvisioningManager.KEY_1X_THRESHOLD;
+
/**
* WiFi threshold.
* Handover from LTE to WiFi if LTE < THLTE1 and WiFi >= VOWT_A.
+ * @deprecated use {@link ProvisioningManager#KEY_WIFI_THRESHOLD_A}.
*/
- public static final int VOWT_A = 60;
+ @Deprecated
+ public static final int VOWT_A = ProvisioningManager.KEY_WIFI_THRESHOLD_A;
+
/**
* WiFi threshold.
* Handover from WiFi to LTE if LTE >= THLTE3 or (WiFi < VOWT_B and LTE >= THLTE2).
+ * @deprecated use {@link ProvisioningManager#KEY_WIFI_THRESHOLD_B}.
*/
- public static final int VOWT_B = 61;
+ @Deprecated
+ public static final int VOWT_B = ProvisioningManager.KEY_WIFI_THRESHOLD_B;
+
/**
* LTE ePDG timer.
* Device shall not handover back to LTE until the T_ePDG_LTE timer expires.
+ * @deprecated use {@link ProvisioningManager#KEY_LTE_EPDG_TIMER_SEC}.
*/
- public static final int T_EPDG_LTE = 62;
+ @Deprecated
+ public static final int T_EPDG_LTE = ProvisioningManager.KEY_LTE_EPDG_TIMER_SEC;
+
/**
* WiFi ePDG timer.
* Device shall not handover back to WiFi until the T_ePDG_WiFi timer expires.
+ * @deprecated use {@link ProvisioningManager#KEY_WIFI_EPDG_TIMER_SEC}.
*/
- public static final int T_EPDG_WIFI = 63;
+ @Deprecated
+ public static final int T_EPDG_WIFI = ProvisioningManager.KEY_WIFI_EPDG_TIMER_SEC;
+
/**
* 1x ePDG timer.
* Device shall not re-register on 1x until the T_ePDG_1x timer expires.
+ * @deprecated use {@link ProvisioningManager#KEY_1X_EPDG_TIMER_SEC}.
*/
- public static final int T_EPDG_1X = 64;
+ @Deprecated
+ public static final int T_EPDG_1X = ProvisioningManager.KEY_1X_EPDG_TIMER_SEC;
+
/**
* MultiEndpoint status: Enabled (1), or Disabled (0).
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_MULTIENDPOINT_ENABLED}.
*/
- public static final int VICE_SETTING_ENABLED = 65;
+ @Deprecated
+ public static final int VICE_SETTING_ENABLED = ProvisioningManager.KEY_MULTIENDPOINT_ENABLED;
/**
* RTT status: Enabled (1), or Disabled (0).
* Value is in Integer format.
+ * @deprecated use {@link ProvisioningManager#KEY_RTT_ENABLED}.
*/
- public static final int RTT_SETTING_ENABLED = 66;
+ @Deprecated
+ public static final int RTT_SETTING_ENABLED = ProvisioningManager.KEY_RTT_ENABLED;
// Expand the operator config items as needed here, need to change
// PROVISIONED_CONFIG_END after that.
diff --git a/telephony/java/com/android/ims/ImsUtInterface.java b/telephony/java/com/android/ims/ImsUtInterface.java
index e80087d..15f8371 100644
--- a/telephony/java/com/android/ims/ImsUtInterface.java
+++ b/telephony/java/com/android/ims/ImsUtInterface.java
@@ -16,12 +16,12 @@
package com.android.ims;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Message;
import android.telephony.ims.ImsCallForwardInfo;
import android.telephony.ims.ImsSsInfo;
-
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.telephony.ims.stub.ImsUtImplBase;
/**
* Provides APIs for the supplementary service settings using IMS (Ut interface).
@@ -59,47 +59,48 @@
* CDIV (Communication Diversion, 3GPP TS 24.604)
* actions: target, no reply timer
*/
- public static final int CDIV_CF_UNCONDITIONAL = 0;
- public static final int CDIV_CF_BUSY = 1;
- public static final int CDIV_CF_NO_REPLY = 2;
- public static final int CDIV_CF_NOT_REACHABLE = 3;
+ public static final int CDIV_CF_UNCONDITIONAL = ImsCallForwardInfo.CDIV_CF_REASON_UNCONDITIONAL;
+ public static final int CDIV_CF_BUSY = ImsCallForwardInfo.CDIV_CF_REASON_BUSY;
+ public static final int CDIV_CF_NO_REPLY = ImsCallForwardInfo.CDIV_CF_REASON_NO_REPLY;
+ public static final int CDIV_CF_NOT_REACHABLE = ImsCallForwardInfo.CDIV_CF_REASON_NOT_REACHABLE;
// For CS service code: 002
- public static final int CDIV_CF_ALL = 4;
+ public static final int CDIV_CF_ALL = ImsCallForwardInfo.CDIV_CF_REASON_ALL;
// For CS service code: 004
- public static final int CDIV_CF_ALL_CONDITIONAL = 5;
+ public static final int CDIV_CF_ALL_CONDITIONAL =
+ ImsCallForwardInfo.CDIV_CF_REASON_ALL_CONDITIONAL;
// It's only supported in the IMS service (CS does not define it).
// IR.92 recommends that an UE activates both the CFNRc and the CFNL
// (CDIV using condition not-registered) to the same target.
- public static final int CDIV_CF_NOT_LOGGED_IN = 6;
+ public static final int CDIV_CF_NOT_LOGGED_IN = ImsCallForwardInfo.CDIV_CF_REASON_NOT_LOGGED_IN;
/**
* CB (Communication Barring, 3GPP TS 24.611)
*/
// Barring of All Incoming Calls
- public static final int CB_BAIC = 1;
+ public static final int CB_BAIC = ImsUtImplBase.CALL_BARRING_ALL_INCOMING;
// Barring of All Outgoing Calls
- public static final int CB_BAOC = 2;
+ public static final int CB_BAOC = ImsUtImplBase.CALL_BARRING_ALL_OUTGOING;
// Barring of Outgoing International Calls
- public static final int CB_BOIC = 3;
+ public static final int CB_BOIC = ImsUtImplBase.CALL_BARRING_OUTGOING_INTL;
// Barring of Outgoing International Calls - excluding Home Country
- public static final int CB_BOIC_EXHC = 4;
+ public static final int CB_BOIC_EXHC = ImsUtImplBase.CALL_BARRING_OUTGOING_INTL_EXCL_HOME;
// Barring of Incoming Calls - when roaming
- public static final int CB_BIC_WR = 5;
+ public static final int CB_BIC_WR = ImsUtImplBase.CALL_BLOCKING_INCOMING_WHEN_ROAMING;
// Barring of Anonymous Communication Rejection (ACR) - a particular case of ICB service
- public static final int CB_BIC_ACR = 6;
+ public static final int CB_BIC_ACR = ImsUtImplBase.CALL_BARRING_ANONYMOUS_INCOMING;
// Barring of All Calls
- public static final int CB_BA_ALL = 7;
+ public static final int CB_BA_ALL = ImsUtImplBase.CALL_BARRING_ALL;
// Barring of Outgoing Services (Service Code 333 - 3GPP TS 22.030 Table B-1)
- public static final int CB_BA_MO = 8;
+ public static final int CB_BA_MO = ImsUtImplBase.CALL_BARRING_OUTGOING_ALL_SERVICES;
// Barring of Incoming Services (Service Code 353 - 3GPP TS 22.030 Table B-1)
- public static final int CB_BA_MT = 9;
+ public static final int CB_BA_MT = ImsUtImplBase.CALL_BARRING_INCOMING_ALL_SERVICES;
// Barring of Specific Incoming calls
- public static final int CB_BS_MT = 10;
+ public static final int CB_BS_MT = ImsUtImplBase.CALL_BARRING_SPECIFIC_INCOMING_CALLS;
/**
* Invalid result value.
*/
- public static final int INVALID = (-1);
+ public static final int INVALID = ImsUtImplBase.INVALID_RESULT;
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index e1113eb..1449a62 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -15,9 +15,9 @@
*/
package com.android.internal.telephony;
-import com.android.internal.util.Protocol;
+import android.compat.annotation.UnsupportedAppUsage;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import com.android.internal.util.Protocol;
/**
* @hide
@@ -111,6 +111,9 @@
public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49;
public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 50;
public static final int EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED = BASE + 51;
+ public static final int EVENT_SERVICE_STATE_CHANGED = BASE + 52;
+ public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53;
+ public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54;
/***** Constants *****/
diff --git a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
index 4e79660..76ebc0f 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -23,9 +23,13 @@
*/
interface ICarrierConfigLoader {
+ /** @deprecated Use {@link #getConfigForSubIdWithFeature(int, String, String) instead */
@UnsupportedAppUsage
PersistableBundle getConfigForSubId(int subId, String callingPackage);
+ PersistableBundle getConfigForSubIdWithFeature(int subId, String callingPackage,
+ String callingFeatureId);
+
void overrideConfig(int subId, in PersistableBundle overrides, boolean persistent);
void notifyConfigChangedForSubId(int subId);
diff --git a/telephony/java/com/android/internal/telephony/IOns.aidl b/telephony/java/com/android/internal/telephony/IOns.aidl
index 2c48b65..76b6951 100755
--- a/telephony/java/com/android/internal/telephony/IOns.aidl
+++ b/telephony/java/com/android/internal/telephony/IOns.aidl
@@ -83,7 +83,7 @@
* subscription id
*
*/
- int getPreferredDataSubscriptionId(String callingPackage);
+ int getPreferredDataSubscriptionId(String callingPackage, String callingFeatureId);
/**
* Update availability of a list of networks in the current location.
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 5b509b7..28ef235 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -24,113 +24,128 @@
*/
interface IPhoneSubInfo {
+ /** @deprecated Use {@link #getDeviceIdWithFeature(String, String) instead */
+ @UnsupportedAppUsage
+ String getDeviceId(String callingPackage);
+
/**
* Retrieves the unique device ID, e.g., IMEI for GSM phones.
*/
- String getDeviceId(String callingPackage);
+ String getDeviceIdWithFeature(String callingPackage, String callingFeatureId);
/**
* Retrieves the unique Network Access ID
*/
- String getNaiForSubscriber(int subId, String callingPackage);
+ String getNaiForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the unique device ID of a phone for the device, e.g., IMEI
* for GSM phones.
*/
- String getDeviceIdForPhone(int phoneId, String callingPackage);
+ String getDeviceIdForPhone(int phoneId, String callingPackage, String callingFeatureId);
/**
* Retrieves the IMEI.
*/
- String getImeiForSubscriber(int subId, String callingPackage);
+ String getImeiForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the software version number for the device, e.g., IMEI/SV
* for GSM phones.
*/
- String getDeviceSvn(String callingPackage);
+ String getDeviceSvn(String callingPackage, String callingFeatureId);
/**
* Retrieves the software version number of a subId for the device, e.g., IMEI/SV
* for GSM phones.
*/
- String getDeviceSvnUsingSubId(int subId, String callingPackage);
+ String getDeviceSvnUsingSubId(int subId, String callingPackage, String callingFeatureId);
- /**
- * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
- */
+ /** @deprecated Use {@link #getSubscriberIdWithFeature(String, String) instead */
@UnsupportedAppUsage
String getSubscriberId(String callingPackage);
/**
+ * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
+ */
+ String getSubscriberIdWithFeature(String callingPackage, String callingComponenId);
+
+ /**
* Retrieves the unique subscriber ID of a given subId, e.g., IMSI for GSM phones.
*/
- String getSubscriberIdForSubscriber(int subId, String callingPackage);
+ String getSubscriberIdForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves the Group Identifier Level1 for GSM phones of a subId.
*/
- String getGroupIdLevel1ForSubscriber(int subId, String callingPackage);
+ String getGroupIdLevel1ForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
- /**
- * Retrieves the serial number of the ICC, if applicable.
- */
+ /** @deprecared Use {@link getIccSerialNumberWithFeature(String, String)} instead */
@UnsupportedAppUsage
String getIccSerialNumber(String callingPackage);
/**
+ * Retrieves the serial number of the ICC, if applicable.
+ */
+ String getIccSerialNumberWithFeature(String callingPackage, String callingFeatureId);
+
+ /**
* Retrieves the serial number of a given subId.
*/
- String getIccSerialNumberForSubscriber(int subId, String callingPackage);
+ String getIccSerialNumberForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves the phone number string for line 1.
*/
- String getLine1Number(String callingPackage);
+ String getLine1Number(String callingPackage, String callingFeatureId);
/**
* Retrieves the phone number string for line 1 of a subcription.
*/
- String getLine1NumberForSubscriber(int subId, String callingPackage);
+ String getLine1NumberForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the alpha identifier for line 1.
*/
- String getLine1AlphaTag(String callingPackage);
+ String getLine1AlphaTag(String callingPackage, String callingFeatureId);
/**
* Retrieves the alpha identifier for line 1 of a subId.
*/
- String getLine1AlphaTagForSubscriber(int subId, String callingPackage);
+ String getLine1AlphaTagForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves MSISDN Number.
*/
- String getMsisdn(String callingPackage);
+ String getMsisdn(String callingPackage, String callingFeatureId);
/**
* Retrieves the Msisdn of a subId.
*/
- String getMsisdnForSubscriber(int subId, String callingPackage);
+ String getMsisdnForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the voice mail number.
*/
- String getVoiceMailNumber(String callingPackage);
+ String getVoiceMailNumber(String callingPackage, String callingFeatureId);
/**
* Retrieves the voice mail number of a given subId.
*/
- String getVoiceMailNumberForSubscriber(int subId, String callingPackage);
+ String getVoiceMailNumberForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves the Carrier information used to encrypt IMSI and IMPI.
*/
ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType,
- String callingPackage);
+ String callingPackage);
/**
* Stores the Carrier information used to encrypt IMSI and IMPI.
@@ -148,13 +163,14 @@
/**
* Retrieves the alpha identifier associated with the voice mail number.
*/
- String getVoiceMailAlphaTag(String callingPackage);
+ String getVoiceMailAlphaTag(String callingPackage, String callingFeatureId);
/**
* Retrieves the alpha identifier associated with the voice mail number
* of a subId.
*/
- String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage);
+ String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the IMS private user identity (IMPI) that was loaded from the ISIM.
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 45dd581..c07a171 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -1,18 +1,18 @@
/*
-** Copyright 2007, 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.
-*/
+ * Copyright 2007, 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.internal.telephony;
@@ -22,7 +22,7 @@
import com.android.internal.telephony.SmsRawData;
/**
- * Interface for applications to access the ICC phone book.
+ * Service interface to handle SMS API requests
*
* See also SmsManager.java.
*/
@@ -542,6 +542,13 @@
in List<PendingIntent> deliveryIntents);
/**
+ * Get carrier-dependent configuration values.
+ *
+ * @param subId the subscription Id
+ */
+ Bundle getCarrierConfigValuesForSubscriber(int subId);
+
+ /**
* Create an app-only incoming SMS request for the calling package.
*
* If an incoming text contains the token returned by this method the provided
@@ -573,7 +580,8 @@
*
* @param destAddress the destination address to test for possible short code
*/
- int checkSmsShortCodeDestination(int subId, String callingApk, String destAddress, String countryIso);
+ int checkSmsShortCodeDestination(int subId, String callingApk, String callingFeatureId,
+ String destAddress, String countryIso);
/**
* Gets the SMSC address from (U)SIM.
diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
index 020b92b..ddd3457 100644
--- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -186,6 +186,11 @@
}
@Override
+ public Bundle getCarrierConfigValuesForSubscriber(int subId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public String createAppSpecificSmsToken(int subId, String callingPkg, PendingIntent intent) {
throw new UnsupportedOperationException();
}
@@ -197,8 +202,8 @@
}
@Override
- public int checkSmsShortCodeDestination(
- int subid, String callingApk, String destAddress, String countryIso) {
+ public int checkSmsShortCodeDestination(int subid, String callingPackage,
+ String callingFeatureId, String destAddress, String countryIso) {
throw new UnsupportedOperationException();
}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 92aab4b..cc02a40 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -23,47 +23,56 @@
interface ISub {
/**
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return a list of all subscriptions in the database, this includes
* all subscriptions that have been seen.
*/
- List<SubscriptionInfo> getAllSubInfoList(String callingPackage);
+ List<SubscriptionInfo> getAllSubInfoList(String callingPackage, String callingFeatureId);
/**
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return the count of all subscriptions in the database, this includes
* all subscriptions that have been seen.
*/
- int getAllSubInfoCount(String callingPackage);
+ int getAllSubInfoCount(String callingPackage, String callingFeatureId);
/**
* Get the active SubscriptionInfo with the subId key
* @param subId The unique SubscriptionInfo key in database
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return SubscriptionInfo, maybe null if its not active
*/
- SubscriptionInfo getActiveSubscriptionInfo(int subId, String callingPackage);
+ SubscriptionInfo getActiveSubscriptionInfo(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Get the active SubscriptionInfo associated with the iccId
* @param iccId the IccId of SIM card
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return SubscriptionInfo, maybe null if its not active
*/
- SubscriptionInfo getActiveSubscriptionInfoForIccId(String iccId, String callingPackage);
+ SubscriptionInfo getActiveSubscriptionInfoForIccId(String iccId, String callingPackage,
+ String callingFeatureId);
/**
* Get the active SubscriptionInfo associated with the slotIndex
* @param slotIndex the slot which the subscription is inserted
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* @return SubscriptionInfo, null for Remote-SIMs or non-active slotIndex.
*/
- SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, String callingPackage);
+ SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, String callingPackage,
+ String callingFeatureId);
/**
* Get the SubscriptionInfo(s) of the active subscriptions. The records will be sorted
* by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}.
*
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return Sorted list of the currently {@link SubscriptionInfo} records available on the device.
* <ul>
* <li>
@@ -80,13 +89,15 @@
* </li>
* </ul>
*/
- List<SubscriptionInfo> getActiveSubscriptionInfoList(String callingPackage);
+ List<SubscriptionInfo> getActiveSubscriptionInfoList(String callingPackage,
+ String callingFeatureId);
/**
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return the number of active subscriptions
*/
- int getActiveSubInfoCount(String callingPackage);
+ int getActiveSubInfoCount(String callingPackage, String callingFeatureId);
/**
* @return the maximum number of subscriptions this device will support at any one time.
@@ -96,7 +107,8 @@
/**
* @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList
*/
- List<SubscriptionInfo> getAvailableSubscriptionInfoList(String callingPackage);
+ List<SubscriptionInfo> getAvailableSubscriptionInfoList(String callingPackage,
+ String callingFeatureId);
/**
* @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList
@@ -225,7 +237,8 @@
* Return opportunistic subscriptions that can be visible to the caller.
* @return the list of opportunistic subscription info. If none exists, an empty list.
*/
- List<SubscriptionInfo> getOpportunisticSubscriptions(String callingPackage);
+ List<SubscriptionInfo> getOpportunisticSubscriptions(String callingPackage,
+ String callingFeatureId);
void removeSubscriptionsFromGroup(in int[] subIdList, in ParcelUuid groupUuid,
String callingPackage);
@@ -233,7 +246,8 @@
void addSubscriptionsIntoGroup(in int[] subIdList, in ParcelUuid groupUuid,
String callingPackage);
- List<SubscriptionInfo> getSubscriptionsInGroup(in ParcelUuid groupUuid, String callingPackage);
+ List<SubscriptionInfo> getSubscriptionsInGroup(in ParcelUuid groupUuid, String callingPackage,
+ String callingFeatureId);
int getSlotIndex(int subId);
@@ -265,7 +279,8 @@
int setSubscriptionProperty(int subId, String propKey, String propValue);
- String getSubscriptionProperty(int subId, String propKey, String callingPackage);
+ String getSubscriptionProperty(int subId, String propKey, String callingPackage,
+ String callingFeatureId);
boolean setSubscriptionEnabled(boolean enable, int subId);
@@ -278,11 +293,13 @@
*/
int getSimStateForSlotIndex(int slotIndex);
- boolean isActiveSubId(int subId, String callingPackage);
+ boolean isActiveSubId(int subId, String callingPackage, String callingFeatureId);
boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow);
int getActiveDataSubscriptionId();
boolean canDisablePhysicalSubscription();
+
+ int setUiccApplicationsEnabled(boolean enabled, int subscriptionId);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index feb1368..1f84451 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -30,6 +30,7 @@
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telephony.CarrierRestrictionRules;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.ClientRequestStats;
import android.telephony.IccOpenLogicalChannelResponse;
@@ -89,29 +90,33 @@
@UnsupportedAppUsage
void call(String callingPackage, String number);
- /**
- * Check to see if the radio is on or not.
- * @param callingPackage the name of the package making the call.
- * @return returns true if the radio is on.
- */
+ /** @deprecated Use {@link #isRadioOnWithFeature(String, String) instead */
+ @UnsupportedAppUsage
boolean isRadioOn(String callingPackage);
/**
- * Check to see if the radio is on or not on particular subId.
- * @param subId user preferred subId.
+ * Check to see if the radio is on or not.
* @param callingPackage the name of the package making the call.
+ * @param callingFeatureId The feature in the package.
* @return returns true if the radio is on.
*/
+ boolean isRadioOnWithFeature(String callingPackage, String callingFeatureId);
+
+ /**
+ * @deprecated Use {@link #isRadioOnForSubscriberWithFeature(int, String, String) instead
+ */
@UnsupportedAppUsage
boolean isRadioOnForSubscriber(int subId, String callingPackage);
/**
- * Supply a pin to unlock the SIM. Blocks until a result is determined.
- * @param pin The pin to check.
- * @return whether the operation was a success.
+ * Check to see if the radio is on or not on particular subId.
+ * @param subId user preferred subId.
+ * @param callingPackage the name of the package making the call.
+ * @param callingFeatureId The feature in the package.
+ * @return returns true if the radio is on.
*/
- @UnsupportedAppUsage
- boolean supplyPin(String pin);
+ boolean isRadioOnForSubscriberWithFeature(int subId, String callingPackage, String callingFeatureId);
+
/**
* Supply a pin to unlock the SIM for particular subId.
@@ -127,15 +132,6 @@
* Blocks until a result is determined.
* @param puk The puk to check.
* pin The new pin to be set in SIM
- * @return whether the operation was a success.
- */
- boolean supplyPuk(String puk, String pin);
-
- /**
- * Supply puk to unlock the SIM and set SIM pin to new pin.
- * Blocks until a result is determined.
- * @param puk The puk to check.
- * pin The new pin to be set in SIM
* @param subId user preferred subId.
* @return whether the operation was a success.
*/
@@ -148,15 +144,6 @@
* @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
* retValue[1] = number of attempts remaining if known otherwise -1
*/
- int[] supplyPinReportResult(String pin);
-
- /**
- * Supply a pin to unlock the SIM. Blocks until a result is determined.
- * Returns a specific success/error code.
- * @param pin The pin to check.
- * @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
- * retValue[1] = number of attempts remaining if known otherwise -1
- */
int[] supplyPinReportResultForSubscriber(int subId, String pin);
/**
@@ -168,17 +155,6 @@
* @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
* retValue[1] = number of attempts remaining if known otherwise -1
*/
- int[] supplyPukReportResult(String puk, String pin);
-
- /**
- * Supply puk to unlock the SIM and set SIM pin to new pin.
- * Blocks until a result is determined.
- * Returns a specific success/error code
- * @param puk The puk to check
- * pin The pin to check.
- * @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
- * retValue[1] = number of attempts remaining if known otherwise -1
- */
int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin);
/**
@@ -294,19 +270,20 @@
*/
boolean isDataConnectivityPossible(int subId);
- Bundle getCellLocation(String callingPkg);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ CellIdentity getCellLocation(String callingPkg, String callingFeatureId);
/**
* Returns the ISO country code equivalent of the current registered
* operator's MCC (Mobile Country Code).
* @see android.telephony.TelephonyManager#getNetworkCountryIso
*/
- String getNetworkCountryIsoForPhone(int phoneId, String callingPkg);
+ String getNetworkCountryIsoForPhone(int phoneId, String callingPkg, String callingFeatureId);
/**
* Returns the neighboring cell information of the device.
*/
- List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg);
+ List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg, String callingFeatureId);
@UnsupportedAppUsage
int getCallState();
@@ -370,23 +347,27 @@
/**
* Returns the CDMA ERI icon index to display
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconIndex(String callingPackage);
+ int getCdmaEriIconIndex(String callingPackage, String callingFeatureId);
/**
* Returns the CDMA ERI icon index to display on particular subId.
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage);
+ int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the CDMA ERI icon mode,
* 0 - ON
* 1 - FLASHING
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconMode(String callingPackage);
+ int getCdmaEriIconMode(String callingPackage, String callingFeatureId);
/**
* Returns the CDMA ERI icon mode on particular subId,
@@ -394,21 +375,25 @@
* 1 - FLASHING
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconModeForSubscriber(int subId, String callingPackage);
+ int getCdmaEriIconModeForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the CDMA ERI text,
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- String getCdmaEriText(String callingPackage);
+ String getCdmaEriText(String callingPackage, String callingFeatureId);
/**
* Returns the CDMA ERI text for particular subId,
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- String getCdmaEriTextForSubscriber(int subId, String callingPackage);
+ String getCdmaEriTextForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Returns true if OTA service provisioning needs to run.
@@ -451,7 +436,8 @@
* @param subId user preferred subId.
* Returns the unread count of voicemails
*/
- int getVoiceMessageCountForSubscriber(int subId, String callingPackage);
+ int getVoiceMessageCountForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns true if current state supports both voice and data
@@ -461,7 +447,7 @@
Bundle getVisualVoicemailSettings(String callingPackage, int subId);
- String getVisualVoicemailPackageName(String callingPackage, int subId);
+ String getVisualVoicemailPackageName(String callingPackage, String callingFeatureId, int subId);
// Not oneway, caller needs to make sure the vaule is set before receiving a SMS
void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
@@ -493,29 +479,35 @@
* Returns the network type of a subId.
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getNetworkTypeForSubscriber(int subId, String callingPackage);
+ int getNetworkTypeForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Returns the network type for data transmission
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getDataNetworkType(String callingPackage);
+ int getDataNetworkType(String callingPackage, String callingFeatureId);
/**
* Returns the data network type of a subId
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getDataNetworkTypeForSubscriber(int subId, String callingPackage);
+ int getDataNetworkTypeForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the voice network type of a subId
* @param subId user preferred subId.
- * @param callingPackage package making the call.
+ * @param callingPackage package making the call.getLteOnCdmaMode
+ * @param callingFeatureId The feature in the package.
* Returns the network type
*/
- int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage);
+ int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Return true if an ICC card is present
@@ -536,10 +528,11 @@
* the mode may be unknown.
*
* @param callingPackage the name of the calling package
+ * @param callingFeatureId The feature in the package.
* @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
* or {@link PHone#LTE_ON_CDMA_TRUE}
*/
- int getLteOnCdmaMode(String callingPackage);
+ int getLteOnCdmaMode(String callingPackage, String callingFeatureId);
/**
* Return if the current radio is LTE on CDMA. This
@@ -547,21 +540,23 @@
* the mode may be unknown.
*
* @param callingPackage the name of the calling package
+ * @param callingFeatureId The feature in the package.
* @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
* or {@link PHone#LTE_ON_CDMA_TRUE}
*/
- int getLteOnCdmaModeForSubscriber(int subId, String callingPackage);
+ int getLteOnCdmaModeForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Returns all observed cell information of the device.
*/
- List<CellInfo> getAllCellInfo(String callingPkg);
+ List<CellInfo> getAllCellInfo(String callingPkg, String callingFeatureId);
/**
* Request a cell information update for the specified subscription,
* reported via the CellInfoCallback.
*/
- void requestCellInfoUpdate(int subId, in ICellInfoCallback cb, String callingPkg);
+ void requestCellInfoUpdate(int subId, in ICellInfoCallback cb, String callingPkg,
+ String callingFeatureId);
/**
* Request a cell information update for the specified subscription,
@@ -569,8 +564,8 @@
*
* @param workSource the requestor to whom the power consumption for this should be attributed.
*/
- void requestCellInfoUpdateWithWorkSource(
- int subId, in ICellInfoCallback cb, in String callingPkg, in WorkSource ws);
+ void requestCellInfoUpdateWithWorkSource(int subId, in ICellInfoCallback cb,
+ in String callingPkg, String callingFeatureId, in WorkSource ws);
/**
* Sets minimum time in milli-seconds between onCellInfoChanged
@@ -798,10 +793,11 @@
* Get the calculated preferred network type.
* Used for device configuration by some CDMA operators.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
*
* @return the calculated preferred network type, defined in RILConstants.java.
*/
- int getCalculatedPreferredNetworkType(String callingPackage);
+ int getCalculatedPreferredNetworkType(String callingPackage, String callingFeatureId);
/*
* Get the preferred network type.
@@ -882,9 +878,12 @@
* Perform a radio scan and return the list of avialble networks.
*
* @param subId the id of the subscription.
+ * @param callingPackage the calling package
+ * @param callingFeatureId The feature in the package
* @return CellNetworkScanResult containing status of scan and networks.
*/
- CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage);
+ CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Perform a radio network scan and return the id of this scan.
@@ -894,10 +893,11 @@
* @param messenger Callback messages will be sent using this messenger.
* @param binder the binder object instantiated in TelephonyManager.
* @param callingPackage the calling package
+ * @param callingFeatureId The feature in the package
* @return An id for this scan.
*/
int requestNetworkScan(int subId, in NetworkScanRequest request, in Messenger messenger,
- in IBinder binder, in String callingPackage);
+ in IBinder binder, in String callingPackage, String callingFeatureId);
/**
* Stop an existing radio network scan.
@@ -976,8 +976,9 @@
* Get P-CSCF address from PCO after data connection is established or modified.
* @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- String[] getPcscfAddress(String apnType, String callingPackage);
+ String[] getPcscfAddress(String apnType, String callingPackage, String callingFeatureId);
/**
* Set IMS registration state
@@ -1067,9 +1068,10 @@
*
* @param subId whose dialing number for line 1 is returned.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return the displayed dialing number if set, or null if not set.
*/
- String getLine1NumberForDisplay(int subId, String callingPackage);
+ String getLine1NumberForDisplay(int subId, String callingPackage, String callingFeatureId);
/**
* Returns the displayed alphatag of the dialing number if it was set
@@ -1077,10 +1079,11 @@
*
* @param subId whose alphatag associated with line 1 is returned.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return the displayed alphatag of the dialing number if set, or null if
* not set.
*/
- String getLine1AlphaTagForDisplay(int subId, String callingPackage);
+ String getLine1AlphaTagForDisplay(int subId, String callingPackage, String callingFeatureId);
/**
* Return the set of subscriber IDs that should be considered "merged together" for data usage
@@ -1092,7 +1095,7 @@
*
* @hide
*/
- String[] getMergedSubscriberIds(int subId, String callingPackage);
+ String[] getMergedSubscriberIds(int subId, String callingPackage, String callingFeatureId);
/**
* @hide
@@ -1191,26 +1194,29 @@
* Whether video calling has been enabled by the user.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@code true} if the user has enabled video calling, {@code false} otherwise.
*/
- boolean isVideoCallingEnabled(String callingPackage);
+ boolean isVideoCallingEnabled(String callingPackage, String callingFeatureId);
/**
* Whether the DTMF tone length can be changed.
*
* @param subId The subscription to use.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@code true} if the DTMF tone length can be changed.
*/
- boolean canChangeDtmfToneLength(int subId, String callingPackage);
+ boolean canChangeDtmfToneLength(int subId, String callingPackage, String callingFeatureId);
/**
* Whether the device is a world phone.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@code true} if the devices is a world phone.
*/
- boolean isWorldPhone(int subId, String callingPackage);
+ boolean isWorldPhone(int subId, String callingPackage, String callingFeatureId);
/**
* Whether the phone supports TTY mode.
@@ -1252,25 +1258,31 @@
*/
int getImsRegTechnologyForMmTel(int subId);
+ /** @deprecated Use {@link #getDeviceIdWithFeature(String, String) instead */
+ @UnsupportedAppUsage
+ String getDeviceId(String callingPackage);
+
/**
* Returns the unique device ID of phone, for example, the IMEI for
* GSM and the MEID for CDMA phones. Return null if device ID is not available.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getDeviceId(String callingPackage);
+ String getDeviceIdWithFeature(String callingPackage, String callingFeatureId);
/**
* Returns the IMEI for the given slot.
*
* @param slotIndex - device slot.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getImeiForSlot(int slotIndex, String callingPackage);
+ String getImeiForSlot(int slotIndex, String callingPackage, String callingFeatureId);
/**
* Returns the Type Allocation Code from the IMEI for the given slot.
@@ -1284,10 +1296,11 @@
*
* @param slotIndex - device slot.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getMeidForSlot(int slotIndex, String callingPackage);
+ String getMeidForSlot(int slotIndex, String callingPackage, String callingFeatureId);
/**
* Returns the Manufacturer Code from the MEID for the given slot.
@@ -1301,10 +1314,12 @@
*
* @param slotIndex - device slot.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage);
+ String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage,
+ String callingFeatureId);
/**
* Returns the subscription ID associated with the specified PhoneAccount.
@@ -1315,7 +1330,7 @@
* Returns the subscription ID associated with the specified PhoneAccountHandle.
*/
int getSubIdForPhoneAccountHandle(in PhoneAccountHandle phoneAccountHandle,
- String callingPackage);
+ String callingPackage, String callingFeatureId);
/**
* Returns the PhoneAccountHandle associated with a subscription ID.
@@ -1345,9 +1360,11 @@
* Get the service state on specified subscription
* @param subId Subscription id
* @param callingPackage The package making the call
+ * @param callingFeatureId The feature in the package
* @return Service state on specified subscription.
*/
- ServiceState getServiceStateForSubscriber(int subId, String callingPackage);
+ ServiceState getServiceStateForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the URI for the per-account voicemail ringtone set in Phone settings.
@@ -1597,10 +1614,12 @@
* Get Client request stats which will contain statistical information
* on each request made by client.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
* @param subId Subscription index
* @hide
*/
- List<ClientRequestStats> getClientRequestStats(String callingPackage, int subid);
+ List<ClientRequestStats> getClientRequestStats(String callingPackage, String callingFeatureId,
+ int subid);
/**
* Set SIM card power state.
@@ -1619,7 +1638,8 @@
* @param subId subscription ID used for authentication
* @param appType the icc application type, like {@link #APPTYPE_USIM}
*/
- String[] getForbiddenPlmns(int subId, int appType, String callingPackage);
+ String[] getForbiddenPlmns(int subId, int appType, String callingPackage,
+ String callingFeatureId);
/**
* Set the forbidden PLMN list from the givven app type (ex APPTYPE_USIM) on a particular
@@ -1628,10 +1648,12 @@
* @param subId subId the id of the subscription
* @param appType appType the uicc app type, must be USIM or SIM.
* @param fplmns plmns the Forbiden plmns list that needed to be written to the SIM.
- * @param content callingPackage the op Package name.
+ * @param callingPackage the op Package name.
+ * @param callingFeatureId the feature in the package.
* @return number of fplmns that is successfully written to the SIM
*/
- int setForbiddenPlmns(int subId, int appType, in List<String> fplmns, String callingPackage);
+ int setForbiddenPlmns(int subId, int appType, in List<String> fplmns, String callingPackage,
+ String callingFeatureId);
/**
* Check if phone is in emergency callback mode
@@ -1775,7 +1797,8 @@
* How many modems can have simultaneous data connections.
* @hide
*/
- int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage);
+ int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Return the network selection mode on the subscription with id {@code subId}.
@@ -1791,7 +1814,7 @@
* Return the modem radio power state for slot index.
*
*/
- int getRadioPowerState(int slotIndex, String callingPackage);
+ int getRadioPowerState(int slotIndex, String callingPackage, String callingFeatureId);
// IMS specific AIDL commands, see ImsMmTelManager.java
@@ -1921,7 +1944,7 @@
/**
* Return the emergency number list from all the active subscriptions.
*/
- Map getEmergencyNumberList(String callingPackage);
+ Map getEmergencyNumberList(String callingPackage, String callingFeatureId);
/**
* Identify if the number is emergency number, based on all the active subscriptions.
@@ -1954,6 +1977,17 @@
*/
boolean getImsProvisioningStatusForCapability(int subId, int capability, int tech);
+ /**
+ * Get the provisioning status for the IMS Rcs capability specified.
+ */
+ boolean getRcsProvisioningStatusForCapability(int subId, int capability);
+
+ /**
+ * Set the provisioning status for the IMS Rcs capability using the specified subscription.
+ */
+ void setRcsProvisioningStatusForCapability(int subId, int capability,
+ boolean isProvisioned);
+
/** Is the capability and tech flagged as provisioned in the cache */
boolean isMmTelCapabilityProvisionedInCache(int subId, int capability, int tech);
@@ -2021,12 +2055,13 @@
* Returns if the usage of multiple SIM cards at the same time is supported.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@link #MULTISIM_ALLOWED} if the device supports multiple SIMs.
* {@link #MULTISIM_NOT_SUPPORTED_BY_HARDWARE} if the device does not support multiple SIMs.
* {@link #MULTISIM_NOT_SUPPORTED_BY_CARRIER} in the device supports multiple SIMs, but the
* functionality is restricted by the carrier.
*/
- int isMultiSimSupported(String callingPackage);
+ int isMultiSimSupported(String callingPackage, String callingFeatureId);
/**
* Switch configs to enable multi-sim or switch back to single-sim
@@ -2038,7 +2073,8 @@
* Get if altering modems configurations will trigger reboot.
* @hide
*/
- boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage);
+ boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Get the mapping from logical slots to physical slots.
@@ -2057,12 +2093,14 @@
*/
boolean isApplicationOnUicc(int subId, int appType);
- boolean isModemEnabledForSlot(int slotIndex, String callingPackage);
+ boolean isModemEnabledForSlot(int slotIndex, String callingPackage, String callingFeatureId);
boolean isDataEnabledForApn(int apnType, int subId, String callingPackage);
boolean isApnMetered(int apnType, int subId);
+ boolean isMvnoMatched(int subId, int mvnoType, String mvnoMatchData);
+
/**
* Enqueue a pending sms Consumer, which will answer with the user specified selection for an
* outgoing SmsManager operation.
@@ -2094,4 +2132,9 @@
* Command line command to enable or disable handling of CEP data for test purposes.
*/
oneway void setCepEnabled(boolean isCepEnabled);
+
+ /**
+ * Notify Rcs auto config received.
+ */
+ void notifyRcsAutoConfigurationReceived(int subId, in byte[] config, boolean isCompressed);
}
diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java
index 25f03c2..94dfae8 100644
--- a/telephony/java/com/android/internal/telephony/IccCardConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java
@@ -15,11 +15,10 @@
*/
package com.android.internal.telephony;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.telephony.TelephonyManager;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
/**
* {@hide}
*/
diff --git a/telephony/java/com/android/internal/telephony/OperatorInfo.java b/telephony/java/com/android/internal/telephony/OperatorInfo.java
index 59c39b1..64d7863 100644
--- a/telephony/java/com/android/internal/telephony/OperatorInfo.java
+++ b/telephony/java/com/android/internal/telephony/OperatorInfo.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 888746a..7ec2269 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -15,7 +15,7 @@
*/
package com.android.internal.telephony;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 9cbcd7f..284544b 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -16,10 +16,9 @@
package com.android.internal.telephony;
+import android.compat.annotation.UnsupportedAppUsage;
import android.sysprop.TelephonyProperties;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.util.Optional;
/**
@@ -555,4 +554,5 @@
int RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG = 1101;
int RIL_UNSOL_EMERGENCY_NUMBER_LIST = 1102;
int RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED = 1103;
+ int RIL_UNSOL_REGISTRATION_FAILED = 1104;
}
diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
index d672642..8e86ff7 100644
--- a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
+++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
@@ -16,17 +16,16 @@
package com.android.internal.telephony;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.util.SparseIntArray;
import com.android.internal.telephony.cdma.sms.UserData;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.telephony.util.XmlUtils;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
public class Sms7BitEncodingTranslator {
private static final String TAG = "Sms7BitEncodingTranslator";
@UnsupportedAppUsage
diff --git a/telephony/java/com/android/internal/telephony/SmsAddress.java b/telephony/java/com/android/internal/telephony/SmsAddress.java
index 2a8de8c..f18256a 100644
--- a/telephony/java/com/android/internal/telephony/SmsAddress.java
+++ b/telephony/java/com/android/internal/telephony/SmsAddress.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
public abstract class SmsAddress {
// From TS 23.040 9.1.2.5 and TS 24.008 table 10.5.118
diff --git a/telephony/java/com/android/internal/telephony/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java
index dd77b01..ab3fdf4 100644
--- a/telephony/java/com/android/internal/telephony/SmsHeader.java
+++ b/telephony/java/com/android/internal/telephony/SmsHeader.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.HexDump;
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index e396f0c..f21f888 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.telephony.SmsMessage;
import android.text.TextUtils;
diff --git a/telephony/java/com/android/internal/telephony/SmsRawData.java b/telephony/java/com/android/internal/telephony/SmsRawData.java
index 18727f3..9776c8f 100644
--- a/telephony/java/com/android/internal/telephony/SmsRawData.java
+++ b/telephony/java/com/android/internal/telephony/SmsRawData.java
@@ -17,7 +17,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 8e1a78c..eef96c4 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -18,6 +18,7 @@
import android.content.Intent;
import android.telephony.SubscriptionManager;
+import android.telephony.ims.ImsManager;
/**
* The intents that the telephony services broadcast.
@@ -172,24 +173,6 @@
= "android.intent.action.ANY_DATA_STATE";
/**
- * Broadcast Action: An attempt to establish a data connection has failed.
- * The intent will have the following extra values:</p>
- * <dl>
- * <dt>phoneName</dt><dd>A string version of the phone name.</dd>
- * <dt>state</dt><dd>One of {@code CONNECTED}, {@code CONNECTING}, or {code DISCONNECTED}.</dd>
- * <dt>reason</dt><dd>A string indicating the reason for the failure, if available.</dd>
- * </dl>
- *
- * <p class="note">
- * Requires the READ_PHONE_STATE permission.
- *
- * <p class="note">This is a protected intent that can only be sent
- * by the system.
- */
- public static final String ACTION_DATA_CONNECTION_FAILED
- = "android.intent.action.DATA_CONNECTION_FAILED";
-
- /**
* Broadcast Action: The sim card state has changed.
* The intent will have the following extra values:</p>
* <dl>
@@ -222,8 +205,6 @@
public static final String ACTION_SIM_STATE_CHANGED
= Intent.ACTION_SIM_STATE_CHANGED;
- public static final String EXTRA_REBROADCAST_ON_UNLOCK= "rebroadcastOnUnlock";
-
/**
* <p>Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms
* <p class="note">.
@@ -241,9 +222,11 @@
* <p class="note">
* This is for the OEM applications to understand about possible provisioning issues.
* Used in OMA-DM applications.
+ * @deprecated Use {@link ImsManager#ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION} instead.
*/
- public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION
- = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
+ @Deprecated
+ public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION =
+ ImsManager.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION;
/**
* Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 4e42c20..ff70f8b 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Contains a list of string constants used to get or set telephone properties
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 1f7715b..d0c8024 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -16,10 +16,11 @@
package com.android.internal.telephony.cdma;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.sysprop.TelephonyProperties;
import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
import android.telephony.cdma.CdmaSmsCbProgramData;
@@ -41,8 +42,6 @@
import com.android.internal.util.BitwiseInputStream;
import com.android.internal.util.HexDump;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -149,10 +148,9 @@
}
/**
- * Create an SmsMessage from an SMS EF record.
+ * Creates an SmsMessage from an SMS EF record.
*
- * @param index Index of SMS record. This should be index in ArrayList
- * returned by RuimSmsInterfaceManager.getAllMessagesFromIcc + 1.
+ * @param index Index of SMS EF record.
* @param data Record data.
* @return An SmsMessage representing the record.
*
@@ -203,26 +201,16 @@
}
/**
- * TODO(cleanup): why do getSubmitPdu methods take an scAddr input
- * and do nothing with it? GSM allows us to specify a SC (eg,
- * when responding to an SMS that explicitly requests the response
- * is sent to a specific SC), or pass null to use the default
- * value. Is there no similar notion in CDMA? Or do we just not
- * have it hooked up?
- */
-
- /**
- * Get an SMS-SUBMIT PDU for a destination address and a message
+ * Gets an SMS-SUBMIT PDU for a destination address and a message.
*
- * @param scAddr Service Centre address. Null means use default.
- * @param destAddr Address of the recipient.
- * @param message String representation of the message payload.
- * @param statusReportRequested Indicates whether a report is requested for this message.
- * @param smsHeader Array containing the data for the User Data Header, preceded
- * by the Element Identifiers.
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param scAddr Service Centre address. No use for this message.
+ * @param destAddr the address of the destination for the message.
+ * @param message string representation of the message payload.
+ * @param statusReportRequested indicates whether a report is requested for this message.
+ * @param smsHeader array containing the data for the User Data Header, preceded by the Element
+ * Identifiers.
+ * @return a <code>SubmitPdu</code> containing null SC address and the encoded message. Returns
+ * null on encode error.
* @hide
*/
@UnsupportedAppUsage
@@ -232,18 +220,17 @@
}
/**
- * Get an SMS-SUBMIT PDU for a destination address and a message
+ * Gets an SMS-SUBMIT PDU for a destination address and a message.
*
- * @param scAddr Service Centre address. Null means use default.
- * @param destAddr Address of the recipient.
- * @param message String representation of the message payload.
- * @param statusReportRequested Indicates whether a report is requested for this message.
- * @param smsHeader Array containing the data for the User Data Header, preceded
- * by the Element Identifiers.
- * @param priority Priority level of the message
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param scAddr Service Centre address. No use for this message.
+ * @param destAddr the address of the destination for the message.
+ * @param message string representation of the message payload.
+ * @param statusReportRequested indicates whether a report is requested for this message.
+ * @param smsHeader array containing the data for the User Data Header, preceded by the Element
+ * Identifiers.
+ * @param priority priority level of the message.
+ * @return a <code>SubmitPdu</code> containing null SC address and the encoded message. Returns
+ * null on encode error.
* @hide
*/
@UnsupportedAppUsage
@@ -266,16 +253,15 @@
}
/**
- * Get an SMS-SUBMIT PDU for a data message to a destination address and port.
+ * Gets an SMS-SUBMIT PDU for a data message to a destination address & port.
*
- * @param scAddr Service Centre address. null == use default
- * @param destAddr the address of the destination for the message
- * @param destPort the port to deliver the message to at the
- * destination
- * @param data the data for the message
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param scAddr Service Centre address. No use for this message.
+ * @param destAddr the address of the destination for the message.
+ * @param destPort the port to deliver the message to at the destination.
+ * @param data the data for the message.
+ * @param statusReportRequested indicates whether a report is requested for this message.
+ * @return a <code>SubmitPdu</code> containing null SC address and the encoded message. Returns
+ * null on encode error.
*/
@UnsupportedAppUsage
public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, int destPort,
@@ -306,14 +292,13 @@
}
/**
- * Get an SMS-SUBMIT PDU for a data message to a destination address & port
+ * Gets an SMS-SUBMIT PDU for a data message to a destination address & port.
*
- * @param destAddr the address of the destination for the message
- * @param userData the data for the message
- * @param statusReportRequested Indicates whether a report is requested for this message.
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param destAddr the address of the destination for the message.
+ * @param userData the data for the message.
+ * @param statusReportRequested indicates whether a report is requested for this message.
+ * @return a <code>SubmitPdu</code> containing null SC address and the encoded message. Returns
+ * null on encode error.
*/
@UnsupportedAppUsage
public static SubmitPdu getSubmitPdu(String destAddr, UserData userData,
@@ -322,15 +307,14 @@
}
/**
- * Get an SMS-SUBMIT PDU for a data message to a destination address & port
+ * Gets an SMS-SUBMIT PDU for a data message to a destination address & port.
*
- * @param destAddr the address of the destination for the message
- * @param userData the data for the message
- * @param statusReportRequested Indicates whether a report is requested for this message.
- * @param priority Priority level of the message
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param destAddr the address of the destination for the message.
+ * @param userData the data for the message.
+ * @param statusReportRequested indicates whether a report is requested for this message.
+ * @param priority Priority level of the message.
+ * @return a <code>SubmitPdu</code> containing null SC address and the encoded message. Returns
+ * null on encode error.
*/
@UnsupportedAppUsage
public static SubmitPdu getSubmitPdu(String destAddr, UserData userData,
@@ -1060,6 +1044,72 @@
}
/**
+ * Gets an SMS-DELIVER PDU for a originating address and a message.
+ *
+ * @param origAddr the address of the originating for the message.
+ * @param message string representation of the message payload.
+ * @param date the time stamp the message was received.
+ * @return a <code>SubmitPdu</code> containing null SC address and the encoded message. Returns
+ * null on encode error.
+ * @hide
+ */
+ public static SubmitPdu getDeliverPdu(String origAddr, String message, long date) {
+ if (origAddr == null || message == null) {
+ return null;
+ }
+
+ CdmaSmsAddress addr = CdmaSmsAddress.parse(origAddr);
+ if (addr == null) return null;
+
+ BearerData bearerData = new BearerData();
+ bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+
+ bearerData.messageId = 0;
+
+ bearerData.deliveryAckReq = false;
+ bearerData.userAckReq = false;
+ bearerData.readAckReq = false;
+ bearerData.reportReq = false;
+
+ bearerData.userData = new UserData();
+ bearerData.userData.payloadStr = message;
+
+ bearerData.msgCenterTimeStamp = BearerData.TimeStamp.fromMillis(date);
+
+ byte[] encodedBearerData = BearerData.encode(bearerData);
+ if (encodedBearerData == null) return null;
+
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
+ DataOutputStream dos = new DataOutputStream(baos);
+ dos.writeInt(SmsEnvelope.TELESERVICE_WMT);
+ dos.writeInt(0); // servicePresent
+ dos.writeInt(0); // serviceCategory
+ dos.write(addr.digitMode);
+ dos.write(addr.numberMode);
+ dos.write(addr.ton); // number_type
+ dos.write(addr.numberPlan);
+ dos.write(addr.numberOfDigits);
+ dos.write(addr.origBytes, 0, addr.origBytes.length); // digits
+ // Subaddress is not supported.
+ dos.write(0); // subaddressType
+ dos.write(0); // subaddr_odd
+ dos.write(0); // subaddr_nbr_of_digits
+ dos.write(encodedBearerData.length);
+ dos.write(encodedBearerData, 0, encodedBearerData.length);
+ dos.close();
+
+ SubmitPdu pdu = new SubmitPdu();
+ pdu.encodedMessage = baos.toByteArray();
+ pdu.encodedScAddress = null;
+ return pdu;
+ } catch (IOException ex) {
+ Rlog.e(LOG_TAG, "creating Deliver PDU failed: " + ex);
+ }
+ return null;
+ }
+
+ /**
* Creates byte array (pseudo pdu) from SMS object.
* Note: Do not call this method more than once per object!
* @hide
diff --git a/telephony/java/com/android/internal/telephony/cdma/UserData.java b/telephony/java/com/android/internal/telephony/cdma/UserData.java
index d960f05..d7e2968 100644
--- a/telephony/java/com/android/internal/telephony/cdma/UserData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/UserData.java
@@ -16,13 +16,12 @@
package com.android.internal.telephony.cdma.sms;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.SparseIntArray;
import com.android.internal.telephony.SmsHeader;
import com.android.internal.util.HexDump;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
public class UserData {
@UnsupportedAppUsage
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index e9378e7..f4a96a6 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -16,8 +16,9 @@
package com.android.internal.telephony.cdma.sms;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.telephony.SmsCbCmasInfo;
import android.telephony.cdma.CdmaSmsCbProgramData;
import android.telephony.cdma.CdmaSmsCbProgramResults;
@@ -31,8 +32,7 @@
import com.android.internal.util.BitwiseInputStream;
import com.android.internal.util.BitwiseOutputStream;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
+import java.io.ByteArrayOutputStream;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
@@ -285,6 +285,33 @@
return ts;
}
+ public static TimeStamp fromMillis(long timeInMillis) {
+ TimeStamp ts = new TimeStamp();
+ LocalDateTime localDateTime =
+ Instant.ofEpochMilli(timeInMillis).atZone(ts.mZoneId).toLocalDateTime();
+ int year = localDateTime.getYear();
+ if (year < 1996 || year > 2095) return null;
+ ts.year = year;
+ ts.month = localDateTime.getMonthValue();
+ ts.monthDay = localDateTime.getDayOfMonth();
+ ts.hour = localDateTime.getHour();
+ ts.minute = localDateTime.getMinute();
+ ts.second = localDateTime.getSecond();
+ return ts;
+ }
+
+ public byte[] toByteArray() {
+ int year = this.year % 100; // 00 - 99
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream(6);
+ outStream.write((((year / 10) & 0x0F) << 4) | ((year % 10) & 0x0F));
+ outStream.write((((month / 10) << 4) & 0xF0) | ((month % 10) & 0x0F));
+ outStream.write((((monthDay / 10) << 4) & 0xF0) | ((monthDay % 10) & 0x0F));
+ outStream.write((((hour / 10) << 4) & 0xF0) | ((hour % 10) & 0x0F));
+ outStream.write((((minute / 10) << 4) & 0xF0) | ((minute % 10) & 0x0F));
+ outStream.write((((second / 10) << 4) & 0xF0) | ((second % 10) & 0x0F));
+ return outStream.toByteArray();
+ }
+
public long toMillis() {
LocalDateTime localDateTime =
LocalDateTime.of(year, month + 1, monthDay, hour, minute, second);
@@ -958,6 +985,12 @@
}
}
+ private static void encodeMsgCenterTimeStamp(BearerData bData, BitwiseOutputStream outStream)
+ throws BitwiseOutputStream.AccessException {
+ outStream.write(8, 6);
+ outStream.writeByteArray(8 * 6, bData.msgCenterTimeStamp.toByteArray());
+ };
+
/**
* Create serialized representation for BearerData object.
* (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
@@ -1022,6 +1055,10 @@
outStream.write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS);
encodeScpResults(bData, outStream);
}
+ if (bData.msgCenterTimeStamp != null) {
+ outStream.write(8, SUBPARAM_MESSAGE_CENTER_TIME_STAMP);
+ encodeMsgCenterTimeStamp(bData, outStream);
+ }
return outStream.toByteArray();
} catch (BitwiseOutputStream.AccessException ex) {
Rlog.e(LOG_TAG, "BearerData encode failed: " + ex);
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
index b268ee8..039b176 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
@@ -16,14 +16,13 @@
package com.android.internal.telephony.cdma.sms;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.SmsAddress;
import com.android.internal.util.HexDump;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
public class CdmaSmsAddress extends SmsAddress {
/**
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
index be1eab1..964e2fb 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
@@ -17,10 +17,9 @@
package com.android.internal.telephony.cdma.sms;
+import android.compat.annotation.UnsupportedAppUsage;
import android.telephony.cdma.CdmaSmsCbProgramData;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
public final class SmsEnvelope {
/**
* Message Types
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
index 19e0b2d..c2adbc21 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
@@ -16,13 +16,12 @@
package com.android.internal.telephony.gsm;
+import android.compat.annotation.UnsupportedAppUsage;
import android.telephony.PhoneNumberUtils;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.SmsAddress;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.text.ParseException;
public class GsmSmsAddress extends SmsAddress {
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
index 11bc5de..f29410d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
@@ -16,13 +16,12 @@
package com.android.internal.telephony.gsm;
+import android.compat.annotation.UnsupportedAppUsage;
import android.telephony.SmsCbCmasInfo;
import android.telephony.SmsCbEtwsInfo;
import com.android.internal.telephony.SmsConstants;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.util.Arrays;
import java.util.Locale;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index e7b385c..4538193 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -25,9 +25,10 @@
import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_SEPTETS;
import static com.android.internal.telephony.SmsConstants.MessageClass;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.telephony.PhoneNumberUtils;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import android.text.TextUtils;
import com.android.internal.telephony.EncodeException;
@@ -38,13 +39,14 @@
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.uicc.IccUtils;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
+import java.time.Instant;
import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
/**
* A Short Message Service message.
@@ -169,10 +171,9 @@
}
/**
- * Create an SmsMessage from an SMS EF record.
+ * Creates an SmsMessage from an SMS EF record.
*
- * @param index Index of SMS record. This should be index in ArrayList
- * returned by SmsManager.getAllMessagesFromSim + 1.
+ * @param index Index of SMS EF record.
* @param data Record data.
* @return An SmsMessage representing the record.
*
@@ -261,12 +262,15 @@
}
/**
- * Get an SMS-SUBMIT PDU for a destination address and a message
+ * Gets an SMS-SUBMIT PDU for a destination address and a message.
*
- * @param scAddress Service Centre address. Null means use default.
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param scAddress Service Centre address. Null means use default.
+ * @param destinationAddress the address of the destination for the message.
+ * @param message string representation of the message payload.
+ * @param statusReportRequested indicates whether a report is reuested for this message.
+ * @param header a byte array containing the data for the User Data Header.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
* @hide
*/
@UnsupportedAppUsage
@@ -279,17 +283,19 @@
/**
- * Get an SMS-SUBMIT PDU for a destination address and a message using the
- * specified encoding.
+ * Gets an SMS-SUBMIT PDU for a destination address and a message using the specified encoding.
*
- * @param scAddress Service Centre address. Null means use default.
- * @param encoding Encoding defined by constants in
- * com.android.internal.telephony.SmsConstants.ENCODING_*
+ * @param scAddress Service Centre address. Null means use default.
+ * @param destinationAddress the address of the destination for the message.
+ * @param message string representation of the message payload.
+ * @param statusReportRequested indicates whether a report is reuested for this message.
+ * @param header a byte array containing the data for the User Data Header.
+ * @param encoding encoding defined by constants in
+ * com.android.internal.telephony.SmsConstants.ENCODING_*
* @param languageTable
* @param languageShiftTable
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
* @hide
*/
@UnsupportedAppUsage
@@ -302,18 +308,20 @@
}
/**
- * Get an SMS-SUBMIT PDU for a destination address and a message using the
- * specified encoding.
+ * Gets an SMS-SUBMIT PDU for a destination address and a message using the specified encoding.
*
- * @param scAddress Service Centre address. Null means use default.
- * @param encoding Encoding defined by constants in
- * com.android.internal.telephony.SmsConstants.ENCODING_*
+ * @param scAddress Service Centre address. Null means use default.
+ * @param destinationAddress the address of the destination for the message.
+ * @param message string representation of the message payload.
+ * @param statusReportRequested indicates whether a report is reuested for this message.
+ * @param header a byte array containing the data for the User Data Header.
+ * @param encoding encoding defined by constants in
+ * com.android.internal.telephony.SmsConstants.ENCODING_*
* @param languageTable
* @param languageShiftTable
* @param validityPeriod Validity Period of the message in Minutes.
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
* @hide
*/
@UnsupportedAppUsage
@@ -485,12 +493,14 @@
}
/**
- * Get an SMS-SUBMIT PDU for a destination address and a message
+ * Gets an SMS-SUBMIT PDU for a destination address and a message.
*
- * @param scAddress Service Centre address. Null means use default.
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param scAddress Service Centre address. Null means use default.
+ * @param destinationAddress the address of the destination for the message.
+ * @param message string representation of the message payload.
+ * @param statusReportRequested indicates whether a report is reuested for this message.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
*/
@UnsupportedAppUsage
public static SubmitPdu getSubmitPdu(String scAddress,
@@ -501,15 +511,15 @@
}
/**
- * Get an SMS-SUBMIT PDU for a destination address and a message
+ * Gets an SMS-SUBMIT PDU for a destination address and a message.
*
- * @param scAddress Service Centre address. Null means use default.
- * @param destinationAddress the address of the destination for the message
- * @param statusReportRequested staus report of the message Requested
+ * @param scAddress Service Centre address. Null means use default.
+ * @param destinationAddress the address of the destination for the message.
+ * @param message string representation of the message payload.
+ * @param statusReportRequested indicates whether a report is reuested for this message.
* @param validityPeriod Validity Period of the message in Minutes.
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
*/
@UnsupportedAppUsage
public static SubmitPdu getSubmitPdu(String scAddress,
@@ -520,16 +530,15 @@
}
/**
- * Get an SMS-SUBMIT PDU for a data message to a destination address & port
+ * Gets an SMS-SUBMIT PDU for a data message to a destination address & port.
*
- * @param scAddress Service Centre address. null == use default
- * @param destinationAddress the address of the destination for the message
- * @param destinationPort the port to deliver the message to at the
- * destination
- * @param data the data for the message
- * @return a <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message.
- * Returns null on encode error.
+ * @param scAddress Service Centre address. Null means use default.
+ * @param destinationAddress the address of the destination for the message.
+ * @param destinationPort the port to deliver the message to at the destination.
+ * @param data the data for the message.
+ * @param statusReportRequested indicates whether a report is reuested for this message.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
*/
public static SubmitPdu getSubmitPdu(String scAddress,
String destinationAddress, int destinationPort, byte[] data,
@@ -553,8 +562,7 @@
SubmitPdu ret = new SubmitPdu();
ByteArrayOutputStream bo = getSubmitPduHead(
- scAddress, destinationAddress, (byte) 0x41, // MTI = SMS-SUBMIT,
- // TP-UDHI = true
+ scAddress, destinationAddress, (byte) 0x41, /* TP-MTI=SMS-SUBMIT, TP-UDHI=true */
statusReportRequested, ret);
// Skip encoding pdu if error occurs when create pdu head and the error will be handled
// properly later on encodedMessage sanity check.
@@ -581,16 +589,18 @@
}
/**
- * Create the beginning of a SUBMIT PDU. This is the part of the
- * SUBMIT PDU that is common to the two versions of {@link #getSubmitPdu},
- * one of which takes a byte array and the other of which takes a
+ * Creates the beginning of a SUBMIT PDU.
+ *
+ * This is the part of the SUBMIT PDU that is common to the two versions of
+ * {@link #getSubmitPdu}, one of which takes a byte array and the other of which takes a
* <code>String</code>.
*
- * @param scAddress Service Centre address. null == use default
- * @param destinationAddress the address of the destination for the message
+ * @param scAddress Service Centre address. Null means use default.
+ * @param destinationAddress the address of the destination for the message.
* @param mtiByte
- * @param ret <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message. Returns null on encode error.
+ * @param statusReportRequested indicates whether a report is reuested for this message.
+ * @param ret <code>SubmitPdu</code>.
+ * @return a byte array of the beginning of a SUBMIT PDU. Null for invalid destinationAddress.
*/
@UnsupportedAppUsage
private static ByteArrayOutputStream getSubmitPduHead(
@@ -638,6 +648,161 @@
return bo;
}
+ /**
+ * Gets an SMS-DELIVER PDU for an originating address and a message.
+ *
+ * @param scAddress Service Centre address. Null means use default.
+ * @param originatingAddress the address of the originating for the message.
+ * @param message string representation of the message payload.
+ * @param date the time stamp the message was received.
+ * @return a <code>SubmitPdu</code> containing the encoded SC address if applicable and the
+ * encoded message. Returns null on encode error.
+ * @hide
+ */
+ public static SubmitPdu getDeliverPdu(
+ String scAddress, String originatingAddress, String message, long date) {
+ if (originatingAddress == null || message == null) {
+ return null;
+ }
+
+ // Find the best encoding to use
+ TextEncodingDetails ted = calculateLength(message, false);
+ int encoding = ted.codeUnitSize;
+ int languageTable = ted.languageTable;
+ int languageShiftTable = ted.languageShiftTable;
+ byte[] header = null;
+
+ if (encoding == ENCODING_7BIT && (languageTable != 0 || languageShiftTable != 0)) {
+ SmsHeader smsHeader = new SmsHeader();
+ smsHeader.languageTable = languageTable;
+ smsHeader.languageShiftTable = languageShiftTable;
+ header = SmsHeader.toByteArray(smsHeader);
+ }
+
+ SubmitPdu ret = new SubmitPdu();
+
+ ByteArrayOutputStream bo = new ByteArrayOutputStream(MAX_USER_DATA_BYTES + 40);
+
+ // SMSC address with length octet, or 0
+ if (scAddress == null) {
+ ret.encodedScAddress = null;
+ } else {
+ ret.encodedScAddress =
+ PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength(scAddress);
+ }
+
+ // TP-Message-Type-Indicator
+ bo.write(0); // SMS-DELIVER
+
+ byte[] oaBytes;
+
+ oaBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(originatingAddress);
+
+ // Return null for invalid originating address
+ if (oaBytes == null) return null;
+
+ // Originating address length in BCD digits, ignoring TON byte and pad
+ // TODO Should be better.
+ bo.write((oaBytes.length - 1) * 2 - ((oaBytes[oaBytes.length - 1] & 0xf0) == 0xf0 ? 1 : 0));
+
+ // Originating Address
+ bo.write(oaBytes, 0, oaBytes.length);
+
+ // TP-Protocol-Identifier
+ bo.write(0);
+
+ // User Data (and length)
+ byte[] userData;
+ try {
+ if (encoding == ENCODING_7BIT) {
+ userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header,
+ languageTable, languageShiftTable);
+ } else { // Assume UCS-2
+ try {
+ userData = encodeUCS2(message, header);
+ } catch (UnsupportedEncodingException uex) {
+ Rlog.e(LOG_TAG, "Implausible UnsupportedEncodingException ", uex);
+ return null;
+ }
+ }
+ } catch (EncodeException ex) {
+ if (ex.getError() == EncodeException.ERROR_EXCEED_SIZE) {
+ Rlog.e(LOG_TAG, "Exceed size limitation EncodeException", ex);
+ return null;
+ } else {
+ // Encoding to the 7-bit alphabet failed. Let's see if we can send it as a UCS-2
+ // encoded message
+ try {
+ userData = encodeUCS2(message, header);
+ encoding = ENCODING_16BIT;
+ } catch (EncodeException ex1) {
+ Rlog.e(LOG_TAG, "Exceed size limitation EncodeException", ex1);
+ return null;
+ } catch (UnsupportedEncodingException uex) {
+ Rlog.e(LOG_TAG, "Implausible UnsupportedEncodingException ", uex);
+ return null;
+ }
+ }
+ }
+
+ if (encoding == ENCODING_7BIT) {
+ if ((0xff & userData[0]) > MAX_USER_DATA_SEPTETS) {
+ // Message too long
+ Rlog.e(LOG_TAG, "Message too long (" + (0xff & userData[0]) + " septets)");
+ return null;
+ }
+ // TP-Data-Coding-Scheme
+ // Default encoding, uncompressed
+ bo.write(0x00);
+ } else { // Assume UCS-2
+ if ((0xff & userData[0]) > MAX_USER_DATA_BYTES) {
+ // Message too long
+ Rlog.e(LOG_TAG, "Message too long (" + (0xff & userData[0]) + " bytes)");
+ return null;
+ }
+ // TP-Data-Coding-Scheme
+ // UCS-2 encoding, uncompressed
+ bo.write(0x08);
+ }
+
+ // TP-Service-Centre-Time-Stamp
+ byte[] scts = new byte[7];
+
+ ZonedDateTime zoneDateTime = Instant.ofEpochMilli(date).atZone(ZoneId.systemDefault());
+ LocalDateTime localDateTime = zoneDateTime.toLocalDateTime();
+
+ // It indicates the difference, expressed in quarters of an hour, between the local time and
+ // GMT.
+ int timezoneOffset = zoneDateTime.getOffset().getTotalSeconds() / 60 / 15;
+ boolean negativeOffset = timezoneOffset < 0;
+ if (negativeOffset) {
+ timezoneOffset = -timezoneOffset;
+ }
+ int year = localDateTime.getYear();
+ int month = localDateTime.getMonthValue();
+ int day = localDateTime.getDayOfMonth();
+ int hour = localDateTime.getHour();
+ int minute = localDateTime.getMinute();
+ int second = localDateTime.getSecond();
+
+ year = year > 2000 ? year - 2000 : year - 1900;
+ scts[0] = (byte) ((((year % 10) & 0x0F) << 4) | ((year / 10) & 0x0F));
+ scts[1] = (byte) ((((month % 10) & 0x0F) << 4) | ((month / 10) & 0x0F));
+ scts[2] = (byte) ((((day % 10) & 0x0F) << 4) | ((day / 10) & 0x0F));
+ scts[3] = (byte) ((((hour % 10) & 0x0F) << 4) | ((hour / 10) & 0x0F));
+ scts[4] = (byte) ((((minute % 10) & 0x0F) << 4) | ((minute / 10) & 0x0F));
+ scts[5] = (byte) ((((second % 10) & 0x0F) << 4) | ((second / 10) & 0x0F));
+ scts[6] = (byte) ((((timezoneOffset % 10) & 0x0F) << 4) | ((timezoneOffset / 10) & 0x0F));
+ if (negativeOffset) {
+ scts[0] |= 0x08; // Negative offset
+ }
+ bo.write(scts, 0, scts.length);
+
+ bo.write(userData, 0, userData.length);
+ ret.encodedMessage = bo.toByteArray();
+ return ret;
+ }
+
private static class PduParser {
@UnsupportedAppUsage
byte mPdu[];
diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
index f2d4624..0dc7401 100644
--- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -16,17 +16,16 @@
package com.android.internal.telephony.uicc;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.Bitmap;
import android.graphics.Color;
-import android.telephony.Rlog;
+import com.android.telephony.Rlog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.GsmAlphabet;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.UnsupportedEncodingException;
import java.util.List;
diff --git a/telephony/java/com/android/internal/telephony/util/HandlerExecutor.java b/telephony/java/com/android/internal/telephony/util/HandlerExecutor.java
new file mode 100644
index 0000000..8a25457
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/util/HandlerExecutor.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.util;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+
+/**
+ * An adapter {@link Executor} that posts all executed tasks onto the given
+ * {@link Handler}.
+ *
+ * @hide
+ */
+public class HandlerExecutor implements Executor {
+ private final Handler mHandler;
+
+ public HandlerExecutor(@NonNull Handler handler) {
+ if (handler == null) {
+ throw new NullPointerException();
+ }
+ mHandler = handler;
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ if (!mHandler.post(command)) {
+ throw new RejectedExecutionException(mHandler + " is shutting down");
+ }
+ }
+}
diff --git a/telephony/java/com/android/telephony/Rlog.java b/telephony/java/com/android/telephony/Rlog.java
new file mode 100644
index 0000000..9d6c930
--- /dev/null
+++ b/telephony/java/com/android/telephony/Rlog.java
@@ -0,0 +1,154 @@
+/*
+ * 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.telephony;
+
+import android.text.TextUtils;
+import android.util.Base64;
+import android.util.Log;
+
+import com.android.internal.telephony.util.TelephonyUtils;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * A copy of {@link android.telephony.Rlog} to be used within the telephony mainline module.
+ *
+ * @hide
+ */
+public final class Rlog {
+
+ private static final boolean USER_BUILD = TelephonyUtils.IS_USER;
+
+ private Rlog() {
+ }
+
+ private static int log(int priority, String tag, String msg) {
+ return Log.logToRadioBuffer(priority, tag, msg);
+ }
+
+ public static int v(String tag, String msg) {
+ return log(Log.VERBOSE, tag, msg);
+ }
+
+ public static int v(String tag, String msg, Throwable tr) {
+ return log(Log.VERBOSE, tag,
+ msg + '\n' + Log.getStackTraceString(tr));
+ }
+
+ public static int d(String tag, String msg) {
+ return log(Log.DEBUG, tag, msg);
+ }
+
+ public static int d(String tag, String msg, Throwable tr) {
+ return log(Log.DEBUG, tag,
+ msg + '\n' + Log.getStackTraceString(tr));
+ }
+
+ public static int i(String tag, String msg) {
+ return log(Log.INFO, tag, msg);
+ }
+
+ public static int i(String tag, String msg, Throwable tr) {
+ return log(Log.INFO, tag,
+ msg + '\n' + Log.getStackTraceString(tr));
+ }
+
+ public static int w(String tag, String msg) {
+ return log(Log.WARN, tag, msg);
+ }
+
+ public static int w(String tag, String msg, Throwable tr) {
+ return log(Log.WARN, tag,
+ msg + '\n' + Log.getStackTraceString(tr));
+ }
+
+ public static int w(String tag, Throwable tr) {
+ return log(Log.WARN, tag, Log.getStackTraceString(tr));
+ }
+
+ public static int e(String tag, String msg) {
+ return log(Log.ERROR, tag, msg);
+ }
+
+ public static int e(String tag, String msg, Throwable tr) {
+ return log(Log.ERROR, tag,
+ msg + '\n' + Log.getStackTraceString(tr));
+ }
+
+ public static int println(int priority, String tag, String msg) {
+ return log(priority, tag, msg);
+ }
+
+ public static boolean isLoggable(String tag, int level) {
+ return Log.isLoggable(tag, level);
+ }
+
+ /**
+ * Redact personally identifiable information for production users.
+ * @param tag used to identify the source of a log message
+ * @param pii the personally identifiable information we want to apply secure hash on.
+ * @return If tag is loggable in verbose mode or pii is null, return the original input.
+ * otherwise return a secure Hash of input pii
+ */
+ public static String pii(String tag, Object pii) {
+ String val = String.valueOf(pii);
+ if (pii == null || TextUtils.isEmpty(val) || isLoggable(tag, Log.VERBOSE)) {
+ return val;
+ }
+ return "[" + secureHash(val.getBytes()) + "]";
+ }
+
+ /**
+ * Redact personally identifiable information for production users.
+ * @param enablePiiLogging set when caller explicitly want to enable sensitive logging.
+ * @param pii the personally identifiable information we want to apply secure hash on.
+ * @return If enablePiiLogging is set to true or pii is null, return the original input.
+ * otherwise return a secure Hash of input pii
+ */
+ public static String pii(boolean enablePiiLogging, Object pii) {
+ String val = String.valueOf(pii);
+ if (pii == null || TextUtils.isEmpty(val) || enablePiiLogging) {
+ return val;
+ }
+ return "[" + secureHash(val.getBytes()) + "]";
+ }
+
+ /**
+ * Returns a secure hash (using the SHA1 algorithm) of the provided input.
+ *
+ * @return "****" if the build type is user, otherwise the hash
+ * @param input the bytes for which the secure hash should be computed.
+ */
+ private static String secureHash(byte[] input) {
+ // Refrain from logging user personal information in user build.
+ if (USER_BUILD) {
+ return "****";
+ }
+
+ MessageDigest messageDigest;
+
+ try {
+ messageDigest = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException e) {
+ return "####";
+ }
+
+ byte[] result = messageDigest.digest(input);
+ return Base64.encodeToString(
+ result, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+}
diff --git a/test-base/hiddenapi/Android.bp b/test-base/hiddenapi/Android.bp
index c4e0fab..c202467 100644
--- a/test-base/hiddenapi/Android.bp
+++ b/test-base/hiddenapi/Android.bp
@@ -25,5 +25,8 @@
srcs: ["src/**/*.java"],
- libs: ["android.test.base"],
+ libs: [
+ "android.test.base",
+ "unsupportedappusage",
+ ],
}
diff --git a/test-base/hiddenapi/src/android/test/AndroidTestCase.java b/test-base/hiddenapi/src/android/test/AndroidTestCase.java
index 2b9beb1..fcb8d43 100644
--- a/test-base/hiddenapi/src/android/test/AndroidTestCase.java
+++ b/test-base/hiddenapi/src/android/test/AndroidTestCase.java
@@ -16,7 +16,7 @@
package android.test;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import junit.framework.TestCase;
diff --git a/test-base/hiddenapi/src/android/test/InstrumentationTestCase.java b/test-base/hiddenapi/src/android/test/InstrumentationTestCase.java
index 139cd18..a48a56c 100644
--- a/test-base/hiddenapi/src/android/test/InstrumentationTestCase.java
+++ b/test-base/hiddenapi/src/android/test/InstrumentationTestCase.java
@@ -16,7 +16,7 @@
package android.test;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import junit.framework.TestCase;
diff --git a/test-base/hiddenapi/src/junit/framework/TestCase.java b/test-base/hiddenapi/src/junit/framework/TestCase.java
index 5a54861..59fbe2b 100644
--- a/test-base/hiddenapi/src/junit/framework/TestCase.java
+++ b/test-base/hiddenapi/src/junit/framework/TestCase.java
@@ -16,7 +16,7 @@
package junit.framework;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Stub only
diff --git a/test-base/hiddenapi/src/junit/framework/TestSuite.java b/test-base/hiddenapi/src/junit/framework/TestSuite.java
index 368c661..32305c9 100644
--- a/test-base/hiddenapi/src/junit/framework/TestSuite.java
+++ b/test-base/hiddenapi/src/junit/framework/TestSuite.java
@@ -16,7 +16,7 @@
package junit.framework;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.lang.reflect.Method;
diff --git a/tests/TelephonyCommonTests/Android.bp b/tests/TelephonyCommonTests/Android.bp
new file mode 100644
index 0000000..4f7569d
--- /dev/null
+++ b/tests/TelephonyCommonTests/Android.bp
@@ -0,0 +1,49 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "TelephonyCommonTests",
+ srcs: [
+ ":framework-telephony-common-sources",
+ "**/*.java",
+ ],
+ static_libs: [
+ "mockito-target-extended",
+ "androidx.test.rules",
+ "truth-prebuilt",
+ "platform-test-annotations",
+ "androidx.core_core",
+ "androidx.fragment_fragment",
+ "androidx.test.ext.junit"
+ ],
+
+ jni_libs: ["libdexmakerjvmtiagent"],
+
+ // We need to rename SmsApplication to the test package or else it'll get clobbered by the
+ // hidden api checker
+ jarjar_rules: "jarjar-rules.txt",
+
+ // Uncomment this and comment out the jarjar rule if you want to attach a debugger and step
+ // through the renamed classes.
+ // platform_apis: true,
+
+ libs: [
+ "android.test.runner",
+ "android.test.mock",
+ "android.test.base",
+ "unsupportedappusage",
+ ],
+}
diff --git a/tests/TelephonyCommonTests/AndroidManifest.xml b/tests/TelephonyCommonTests/AndroidManifest.xml
new file mode 100644
index 0000000..63f38c6
--- /dev/null
+++ b/tests/TelephonyCommonTests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.telephony.tests"
+ android:debuggable="true">
+
+ <application android:label="TelephonyCommonTests"
+ android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.internal.telephony.tests"
+ android:label="Telephony common tests"
+ android:debuggable="true"/>
+</manifest>
diff --git a/tests/TelephonyCommonTests/AndroidTest.xml b/tests/TelephonyCommonTests/AndroidTest.xml
new file mode 100644
index 0000000..e9fdabc
--- /dev/null
+++ b/tests/TelephonyCommonTests/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<configuration description="Runs Telephony Common 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="TelephonyCommonTests.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="TelephonyCommonTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.internal.telephony.tests" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ </test>
+</configuration>
diff --git a/tests/TelephonyCommonTests/jarjar-rules.txt b/tests/TelephonyCommonTests/jarjar-rules.txt
new file mode 100644
index 0000000..4d1115f
--- /dev/null
+++ b/tests/TelephonyCommonTests/jarjar-rules.txt
@@ -0,0 +1,3 @@
+rule com.android.internal.telephony.SmsApplication* com.android.internal.telephony.tests.SmsApplication@1
+rule android.telephony.PackageChangeReceiver* com.android.internal.telephony.tests.PackageChangeReceiver@1
+rule com.android.internal.os.BackgroundThread* com.android.internal.telephony.tests.BackgroundThread@1
diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
new file mode 100644
index 0000000..83fd208
--- /dev/null
+++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNotNull;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.app.AppOpsManager;
+import android.app.role.RoleManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Telephony;
+import android.telephony.TelephonyManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.telephony.SmsApplication;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Unit tests for the {@link SmsApplication} utility class
+ */
+@RunWith(AndroidJUnit4.class)
+public class SmsApplicationTest {
+ private static final ComponentName TEST_COMPONENT_NAME =
+ ComponentName.unflattenFromString("com.android.test/.TestSmsApp");
+ private static final String MMS_RECEIVER_NAME = "TestMmsReceiver";
+ private static final String RESPOND_VIA_SMS_NAME = "TestRespondViaSmsHandler";
+ private static final String SEND_TO_NAME = "TestSendTo";
+ private static final int SMS_APP_UID = 10001;
+
+ private static final int FAKE_PHONE_UID = 10002;
+ private static final int FAKE_MMS_UID = 10003;
+ private static final int FAKE_BT_UID = 10004;
+ private static final int FAKE_TELEPHONY_PROVIDER_UID = 10005;
+
+ private static final String[] APP_OPS_TO_CHECK = {
+ AppOpsManager.OPSTR_READ_SMS,
+ AppOpsManager.OPSTR_WRITE_SMS,
+ AppOpsManager.OPSTR_RECEIVE_SMS,
+ AppOpsManager.OPSTR_RECEIVE_WAP_PUSH,
+ AppOpsManager.OPSTR_SEND_SMS,
+ AppOpsManager.OPSTR_READ_CELL_BROADCASTS
+ };
+
+ private static final Set<String> SCHEMES_FOR_PREFERRED_APP = Arrays.stream(new String[]{
+ "mms",
+ "mmsto",
+ "sms",
+ "smsto"
+ }).collect(Collectors.toSet());
+
+ @Mock private Context mContext;
+ @Mock private TelephonyManager mTelephonyManager;
+ @Mock private RoleManager mRoleManager;
+ @Mock private PackageManager mPackageManager;
+ @Mock private AppOpsManager mAppOpsManager;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+ when(mContext.getSystemService(Context.ROLE_SERVICE)).thenReturn(mRoleManager);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager);
+ when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
+ when(mContext.createContextAsUser(isNotNull(), anyInt())).thenReturn(mContext);
+
+ doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+ .when(mPackageManager)
+ .queryBroadcastReceiversAsUser(nullable(Intent.class), anyInt(),
+ nullable(UserHandle.class));
+ doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+ .when(mPackageManager)
+ .queryIntentActivitiesAsUser(nullable(Intent.class), anyInt(),
+ nullable(UserHandle.class));
+ doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+ .when(mPackageManager)
+ .queryIntentServicesAsUser(nullable(Intent.class), anyInt(),
+ nullable(UserHandle.class));
+
+ when(mTelephonyManager.isSmsCapable()).thenReturn(true);
+ when(mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)).thenReturn(true);
+ when(mRoleManager.getDefaultSmsPackage(anyInt()))
+ .thenReturn(TEST_COMPONENT_NAME.getPackageName());
+
+ for (String opStr : APP_OPS_TO_CHECK) {
+ when(mAppOpsManager.unsafeCheckOp(
+ opStr, SMS_APP_UID, TEST_COMPONENT_NAME.getPackageName()))
+ .thenReturn(AppOpsManager.MODE_ALLOWED);
+ }
+ }
+
+ @Test
+ public void testGetDefaultSmsApplication() {
+ assertEquals(TEST_COMPONENT_NAME,
+ SmsApplication.getDefaultSmsApplicationAsUser(mContext, false, 0));
+ }
+
+ @Test
+ public void testGetDefaultSmsApplicationWithAppOpsFix() throws Exception {
+ when(mAppOpsManager.unsafeCheckOp(AppOpsManager.OPSTR_READ_SMS, SMS_APP_UID,
+ TEST_COMPONENT_NAME.getPackageName()))
+ .thenReturn(AppOpsManager.MODE_IGNORED);
+ setupPackageInfosForCoreApps();
+
+ assertEquals(TEST_COMPONENT_NAME,
+ SmsApplication.getDefaultSmsApplicationAsUser(mContext, true, 0));
+ verify(mAppOpsManager, atLeastOnce()).setUidMode(AppOpsManager.OPSTR_READ_SMS, SMS_APP_UID,
+ AppOpsManager.MODE_ALLOWED);
+ }
+
+ @Test
+ public void testPackageChanged() throws Exception {
+ setupPackageInfosForCoreApps();
+ SmsApplication.initSmsPackageMonitor(mContext);
+ verify(mContext).createContextAsUser(eq(UserHandle.ALL), anyInt());
+ ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mContext).registerReceiver(captor.capture(), isNotNull(),
+ isNull(), nullable(Handler.class));
+ BroadcastReceiver smsPackageMonitor = captor.getValue();
+
+ Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
+ packageChangedIntent.setData(
+ Uri.fromParts("package", TEST_COMPONENT_NAME.getPackageName(), null));
+ smsPackageMonitor.onReceive(mContext, packageChangedIntent);
+
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+ verify(mPackageManager, times(SCHEMES_FOR_PREFERRED_APP.size()))
+ .replacePreferredActivity(intentFilterCaptor.capture(),
+ eq(IntentFilter.MATCH_CATEGORY_SCHEME
+ | IntentFilter.MATCH_ADJUSTMENT_NORMAL),
+ isNotNull(List.class),
+ eq(new ComponentName(TEST_COMPONENT_NAME.getPackageName(), SEND_TO_NAME)));
+
+ Set<String> capturedSchemes = intentFilterCaptor.getAllValues().stream()
+ .map(intentFilter -> intentFilter.getDataScheme(0))
+ .collect(Collectors.toSet());
+ assertEquals(SCHEMES_FOR_PREFERRED_APP.size(), capturedSchemes.size());
+ assertTrue(SCHEMES_FOR_PREFERRED_APP.containsAll(capturedSchemes));
+ }
+
+ private void setupPackageInfosForCoreApps() throws Exception {
+ PackageInfo phonePackageInfo = new PackageInfo();
+ ApplicationInfo phoneApplicationInfo = new ApplicationInfo();
+ phoneApplicationInfo.uid = FAKE_PHONE_UID;
+ phonePackageInfo.applicationInfo = phoneApplicationInfo;
+ when(mPackageManager.getPackageInfo(eq(SmsApplication.PHONE_PACKAGE_NAME), anyInt()))
+ .thenReturn(phonePackageInfo);
+
+ PackageInfo mmsPackageInfo = new PackageInfo();
+ ApplicationInfo mmsApplicationInfo = new ApplicationInfo();
+ mmsApplicationInfo.uid = FAKE_MMS_UID;
+ mmsPackageInfo.applicationInfo = mmsApplicationInfo;
+ when(mPackageManager.getPackageInfo(eq(SmsApplication.MMS_SERVICE_PACKAGE_NAME), anyInt()))
+ .thenReturn(mmsPackageInfo);
+
+ PackageInfo bluetoothPackageInfo = new PackageInfo();
+ ApplicationInfo bluetoothApplicationInfo = new ApplicationInfo();
+ bluetoothApplicationInfo.uid = FAKE_BT_UID;
+ bluetoothPackageInfo.applicationInfo = bluetoothApplicationInfo;
+ when(mPackageManager.getPackageInfo(eq(SmsApplication.BLUETOOTH_PACKAGE_NAME), anyInt()))
+ .thenReturn(bluetoothPackageInfo);
+
+ PackageInfo telephonyProviderPackageInfo = new PackageInfo();
+ ApplicationInfo telephonyProviderApplicationInfo = new ApplicationInfo();
+ telephonyProviderApplicationInfo.uid = FAKE_TELEPHONY_PROVIDER_UID;
+ telephonyProviderPackageInfo.applicationInfo = telephonyProviderApplicationInfo;
+ when(mPackageManager.getPackageInfo(
+ eq(SmsApplication.TELEPHONY_PROVIDER_PACKAGE_NAME), anyInt()))
+ .thenReturn(telephonyProviderPackageInfo);
+ }
+
+ private List<ResolveInfo> getResolveInfosForIntent(Intent intent) {
+ switch (intent.getAction()) {
+ case Telephony.Sms.Intents.SMS_DELIVER_ACTION:
+ return Collections.singletonList(makeSmsDeliverResolveInfo());
+ case Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION:
+ return Collections.singletonList(makeWapPushResolveInfo());
+ case TelephonyManager.ACTION_RESPOND_VIA_MESSAGE:
+ return Collections.singletonList(makeRespondViaMessageResolveInfo());
+ case Intent.ACTION_SENDTO:
+ return Collections.singletonList(makeSendToResolveInfo());
+ }
+ return Collections.emptyList();
+ }
+
+ private ApplicationInfo makeSmsApplicationInfo() {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.uid = SMS_APP_UID;
+ return applicationInfo;
+ }
+
+ private ResolveInfo makeSmsDeliverResolveInfo() {
+ ResolveInfo info = new ResolveInfo();
+ ActivityInfo activityInfo = new ActivityInfo();
+ activityInfo.applicationInfo = makeSmsApplicationInfo();
+
+ activityInfo.permission = Manifest.permission.BROADCAST_SMS;
+ activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+ activityInfo.name = TEST_COMPONENT_NAME.getClassName();
+
+ info.activityInfo = activityInfo;
+ return info;
+ }
+
+ private ResolveInfo makeWapPushResolveInfo() {
+ ResolveInfo info = new ResolveInfo();
+ ActivityInfo activityInfo = new ActivityInfo();
+
+ activityInfo.permission = Manifest.permission.BROADCAST_WAP_PUSH;
+ activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+ activityInfo.name = MMS_RECEIVER_NAME;
+
+ info.activityInfo = activityInfo;
+ return info;
+ }
+
+ private ResolveInfo makeRespondViaMessageResolveInfo() {
+ ResolveInfo info = new ResolveInfo();
+ ServiceInfo serviceInfo = new ServiceInfo();
+
+ serviceInfo.permission = Manifest.permission.SEND_RESPOND_VIA_MESSAGE;
+ serviceInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+ serviceInfo.name = RESPOND_VIA_SMS_NAME;
+
+ info.serviceInfo = serviceInfo;
+ return info;
+ }
+
+ private ResolveInfo makeSendToResolveInfo() {
+ ResolveInfo info = new ResolveInfo();
+ ActivityInfo activityInfo = new ActivityInfo();
+
+ activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+ activityInfo.name = SEND_TO_NAME;
+
+ info.activityInfo = activityInfo;
+ return info;
+ }
+}
diff --git a/tests/libs-permissions/Android.bp b/tests/libs-permissions/Android.bp
index 330bfc9..66a1f83 100644
--- a/tests/libs-permissions/Android.bp
+++ b/tests/libs-permissions/Android.bp
@@ -2,6 +2,7 @@
name: "com.android.test.libs.product",
installable: true,
product_specific: true,
+ sdk_version: "current",
srcs: ["product/java/**/*.java"],
required: ["com.android.test.libs.product.xml"],
}
diff --git a/tests/net/TEST_MAPPING b/tests/net/TEST_MAPPING
new file mode 100644
index 0000000..a7853b6
--- /dev/null
+++ b/tests/net/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "postsubmit": [
+ {
+ "name": "FrameworksNetIntegrationTests"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/net/common/java/android/net/CaptivePortalTest.java b/tests/net/common/java/android/net/CaptivePortalTest.java
index eed7159f..ca4ba63 100644
--- a/tests/net/common/java/android/net/CaptivePortalTest.java
+++ b/tests/net/common/java/android/net/CaptivePortalTest.java
@@ -44,6 +44,11 @@
}
@Override
+ public void appRequest(final int request) throws RemoteException {
+ mCode = request;
+ }
+
+ @Override
public void logEvent(int eventId, String packageName) throws RemoteException {
mCode = eventId;
mPackageName = packageName;
@@ -80,6 +85,12 @@
}
@Test
+ public void testReevaluateNetwork() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.reevaluateNetwork());
+ assertEquals(result.mCode, CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED);
+ }
+
+ @Test
public void testLogEvent() {
final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.logEvent(
MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY,
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index a7eef05..3f311c9 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -38,6 +38,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
@@ -65,6 +66,7 @@
private static final InetAddress GATEWAY62 = address("fe80::6:22%lo");
private static final InetAddress TESTIPV4ADDR = address("192.168.47.42");
private static final InetAddress TESTIPV6ADDR = address("fe80::7:33%43");
+ private static final Inet4Address DHCPSERVER = (Inet4Address) address("192.0.2.1");
private static final String NAME = "qmi0";
private static final String DOMAINS = "google.com";
private static final String PRIV_DNS_SERVER_NAME = "private.dns.com";
@@ -73,6 +75,9 @@
private static final LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
+ private static final Uri CAPPORT_API_URL = Uri.parse("https://test.example.com/capportapi");
+ private static final CaptivePortalData CAPPORT_DATA = new CaptivePortalData.Builder()
+ .setVenueInfoUrl(Uri.parse("https://test.example.com/venue")).build();
private static InetAddress address(String addrString) {
return InetAddresses.parseNumericAddress(addrString);
@@ -93,11 +98,14 @@
assertNull(lp.getHttpProxy());
assertNull(lp.getTcpBufferSizes());
assertNull(lp.getNat64Prefix());
+ assertNull(lp.getDhcpServerAddress());
assertFalse(lp.isProvisioned());
assertFalse(lp.isIpv4Provisioned());
assertFalse(lp.isIpv6Provisioned());
assertFalse(lp.isPrivateDnsActive());
assertFalse(lp.isWakeOnLanSupported());
+ assertNull(lp.getCaptivePortalApiUrl());
+ assertNull(lp.getCaptivePortalData());
}
private LinkProperties makeTestObject() {
@@ -119,7 +127,10 @@
lp.setMtu(MTU);
lp.setTcpBufferSizes(TCP_BUFFER_SIZES);
lp.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
+ lp.setDhcpServerAddress(DHCPSERVER);
lp.setWakeOnLanSupported(true);
+ lp.setCaptivePortalApiUrl(CAPPORT_API_URL);
+ lp.setCaptivePortalData(CAPPORT_DATA);
return lp;
}
@@ -161,6 +172,12 @@
assertTrue(source.isIdenticalWakeOnLan(target));
assertTrue(target.isIdenticalWakeOnLan(source));
+ assertTrue(source.isIdenticalCaptivePortalApiUrl(target));
+ assertTrue(target.isIdenticalCaptivePortalApiUrl(source));
+
+ assertTrue(source.isIdenticalCaptivePortalData(target));
+ assertTrue(target.isIdenticalCaptivePortalData(source));
+
// Check result of equals().
assertTrue(source.equals(target));
assertTrue(target.equals(source));
@@ -959,12 +976,22 @@
source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96"));
source.setWakeOnLanSupported(true);
+ source.setCaptivePortalApiUrl(CAPPORT_API_URL);
+ source.setCaptivePortalData(CAPPORT_DATA);
+
+ source.setDhcpServerAddress((Inet4Address) GATEWAY1);
final LinkProperties stacked = new LinkProperties();
stacked.setInterfaceName("test-stacked");
source.addStackedLink(stacked);
- assertParcelSane(source, 15 /* fieldCount */);
+ assertParcelSane(source.makeSensitiveFieldsParcelingCopy(), 18 /* fieldCount */);
+
+ // Verify that without using a sensitiveFieldsParcelingCopy, sensitive fields are cleared.
+ final LinkProperties sanitized = new LinkProperties(source);
+ sanitized.setCaptivePortalApiUrl(null);
+ sanitized.setCaptivePortalData(null);
+ assertEquals(sanitized, parcelingRoundTrip(source));
}
@Test
@@ -1091,6 +1118,15 @@
}
@Test
+ public void testDhcpServerAddress() {
+ final LinkProperties lp = makeTestObject();
+ assertEquals(DHCPSERVER, lp.getDhcpServerAddress());
+
+ lp.clear();
+ assertNull(lp.getDhcpServerAddress());
+ }
+
+ @Test
public void testWakeOnLanSupported() {
final LinkProperties lp = makeTestObject();
assertTrue(lp.isWakeOnLanSupported());
@@ -1098,4 +1134,22 @@
lp.clear();
assertFalse(lp.isWakeOnLanSupported());
}
+
+ @Test
+ public void testCaptivePortalApiUrl() {
+ final LinkProperties lp = makeTestObject();
+ assertEquals(CAPPORT_API_URL, lp.getCaptivePortalApiUrl());
+
+ lp.clear();
+ assertNull(lp.getCaptivePortalApiUrl());
+ }
+
+ @Test
+ public void testCaptivePortalData() {
+ final LinkProperties lp = makeTestObject();
+ assertEquals(CAPPORT_DATA, lp.getCaptivePortalData());
+
+ lp.clear();
+ assertNull(lp.getCaptivePortalData());
+ }
}
diff --git a/tests/net/integration/Android.bp b/tests/net/integration/Android.bp
index 7d9b7b7..874bd4b 100644
--- a/tests/net/integration/Android.bp
+++ b/tests/net/integration/Android.bp
@@ -36,6 +36,7 @@
"services.net",
"testables",
],
+ test_suites: ["device-tests"],
use_embedded_native_libs: true,
jni_libs: [
// For mockito extended
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index 1e8d83c..1c69209 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
@@ -35,10 +36,10 @@
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkAgent;
+import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
-import android.net.NetworkFactory;
import android.net.NetworkInfo;
-import android.net.NetworkMisc;
+import android.net.NetworkProvider;
import android.net.NetworkSpecifier;
import android.net.SocketKeepalive;
import android.net.UidRange;
@@ -74,6 +75,7 @@
final String typeName = ConnectivityManager.getNetworkTypeName(type);
mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
mNetworkCapabilities.addTransportType(transport);
switch (transport) {
case TRANSPORT_ETHERNET:
@@ -114,7 +116,7 @@
public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp) {
super(wrapper.mHandlerThread.getLooper(), wrapper.mContext, wrapper.mLogTag,
wrapper.mNetworkInfo, wrapper.mNetworkCapabilities, lp, wrapper.mScore,
- new NetworkMisc(), NetworkFactory.SerialNumber.NONE);
+ new NetworkAgentConfig(), NetworkProvider.ID_NONE);
mWrapper = wrapper;
}
@@ -206,13 +208,11 @@
}
public void suspend() {
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null, null);
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
}
public void resume() {
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ addCapability(NET_CAPABILITY_NOT_SUSPENDED);
}
public void disconnect() {
@@ -222,7 +222,7 @@
@Override
public Network getNetwork() {
- return new Network(mNetworkAgent.netId);
+ return mNetworkAgent.network;
}
public void expectPreventReconnectReceived(long timeoutMs) {
diff --git a/tests/net/java/android/net/CaptivePortalDataTest.kt b/tests/net/java/android/net/CaptivePortalDataTest.kt
new file mode 100644
index 0000000..0071438
--- /dev/null
+++ b/tests/net/java/android/net/CaptivePortalDataTest.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.assertParcelSane
+import com.android.testutils.assertParcelingIsLossless
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CaptivePortalDataTest {
+ private val data = CaptivePortalData.Builder()
+ .setRefreshTime(123L)
+ .setUserPortalUrl(Uri.parse("https://portal.example.com/test"))
+ .setVenueInfoUrl(Uri.parse("https://venue.example.com/test"))
+ .setSessionExtendable(true)
+ .setBytesRemaining(456L)
+ .setExpiryTime(789L)
+ .setCaptive(true)
+ .build()
+
+ private fun makeBuilder() = CaptivePortalData.Builder(data)
+
+ @Test
+ fun testParcelUnparcel() {
+ assertParcelSane(data, fieldCount = 7)
+
+ assertParcelingIsLossless(makeBuilder().setUserPortalUrl(null).build())
+ assertParcelingIsLossless(makeBuilder().setVenueInfoUrl(null).build())
+ }
+
+ @Test
+ fun testEquals() {
+ assertEquals(data, makeBuilder().build())
+
+ assertNotEqualsAfterChange { it.setRefreshTime(456L) }
+ assertNotEqualsAfterChange { it.setUserPortalUrl(Uri.parse("https://example.com/")) }
+ assertNotEqualsAfterChange { it.setUserPortalUrl(null) }
+ assertNotEqualsAfterChange { it.setVenueInfoUrl(Uri.parse("https://example.com/")) }
+ assertNotEqualsAfterChange { it.setVenueInfoUrl(null) }
+ assertNotEqualsAfterChange { it.setSessionExtendable(false) }
+ assertNotEqualsAfterChange { it.setBytesRemaining(789L) }
+ assertNotEqualsAfterChange { it.setExpiryTime(12L) }
+ assertNotEqualsAfterChange { it.setCaptive(false) }
+ }
+
+ private fun CaptivePortalData.mutate(mutator: (CaptivePortalData.Builder) -> Unit) =
+ CaptivePortalData.Builder(this).apply { mutator(this) }.build()
+
+ private fun assertNotEqualsAfterChange(mutator: (CaptivePortalData.Builder) -> Unit) {
+ assertNotEquals(data, data.mutate(mutator))
+ }
+}
\ No newline at end of file
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index c16a0f4..33d77d2 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -64,15 +64,15 @@
@Test
public void testFindIndex() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 5)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11)
- .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12)
- .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12);
assertEquals(4, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES,
@@ -94,21 +94,21 @@
@Test
public void testFindIndexHinted() {
final NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
- .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12)
- .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1024L, 8L, 0L, 0L, 10)
- .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11)
- .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
- .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12)
- .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ .addEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12);
// verify that we correctly find across regardless of hinting
@@ -143,27 +143,27 @@
assertEquals(0, stats.size());
assertEquals(4, stats.internalSize());
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1L, 1L, 2L, 2L, 3);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 2L, 2L, 2L, 2L, 4);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 3L, 3L, 2L, 2L, 5);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_NO, 3L, 3L, 2L, 2L, 5);
assertEquals(4, stats.size());
assertEquals(4, stats.internalSize());
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 4L, 40L, 4L, 40L, 7);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 5L, 50L, 4L, 40L, 8);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 6L, 60L, 5L, 50L, 10);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 7L, 70L, 5L, 50L, 11);
- stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_NO, 7L, 70L, 5L, 50L, 11);
assertEquals(9, stats.size());
@@ -193,8 +193,8 @@
public void testCombineExisting() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 10);
- stats.addValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 10);
- stats.addValues(TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2);
+ stats.addEntry(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 10);
+ stats.addEntry(TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2);
stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L,
-128L, -1L, -1);
@@ -215,12 +215,12 @@
@Test
public void testSubtractIdenticalData() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats after = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats result = after.subtract(before);
@@ -234,12 +234,12 @@
@Test
public void testSubtractIdenticalRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats after = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1025L, 9L, 2L, 1L, 15)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 3L, 1L, 1028L, 9L, 20);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1025L, 9L, 2L, 1L, 15)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 3L, 1L, 1028L, 9L, 20);
final NetworkStats result = after.subtract(before);
@@ -253,13 +253,13 @@
@Test
public void testSubtractNewRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats after = new NetworkStats(TEST_START, 3)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12)
- .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12)
+ .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20);
final NetworkStats result = after.subtract(before);
@@ -275,11 +275,11 @@
@Test
public void testSubtractMissingRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0)
- .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0);
+ .addEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0)
+ .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0);
final NetworkStats after = new NetworkStats(TEST_START, 1)
- .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0);
+ .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0);
final NetworkStats result = after.subtract(before);
@@ -293,40 +293,40 @@
@Test
public void testTotalBytes() throws Exception {
final NetworkStats iface = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L);
+ .addEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L);
assertEquals(384L, iface.getTotalBytes());
final NetworkStats uidSet = new NetworkStats(TEST_START, 3)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
assertEquals(96L, uidSet.getTotalBytes());
final NetworkStats uidTag = new NetworkStats(TEST_START, 6)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L);
assertEquals(64L, uidTag.getTotalBytes());
final NetworkStats uidMetered = new NetworkStats(TEST_START, 3)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
assertEquals(96L, uidMetered.getTotalBytes());
final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
assertEquals(96L, uidRoaming.getTotalBytes());
}
@@ -343,11 +343,11 @@
@Test
public void testGroupedByIfaceAll() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
- .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
- .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 2L, 20L)
- .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES,
+ .addEntry(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L);
final NetworkStats grouped = uidStats.groupedByIface();
@@ -361,19 +361,19 @@
@Test
public void testGroupedByIface() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 7)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L);
final NetworkStats grouped = uidStats.groupedByIface();
@@ -390,19 +390,19 @@
@Test
public void testAddAllValues() {
final NetworkStats first = new NetworkStats(TEST_START, 5)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
+ .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
final NetworkStats second = new NetworkStats(TEST_START, 2)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
+ .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
first.combineAllValues(second);
@@ -421,19 +421,19 @@
@Test
public void testGetTotal() {
final NetworkStats stats = new NetworkStats(TEST_START, 7)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L,32L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L);
assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L);
@@ -459,7 +459,7 @@
assertEquals(0, after.size());
// Test 1 item stats.
- before.addValues(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, 1L, 128L, 0L, 2L, 20L);
+ before.addEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, 1L, 128L, 0L, 2L, 20L);
after = before.clone();
after.removeUids(new int[0]);
assertEquals(1, after.size());
@@ -469,12 +469,12 @@
assertEquals(0, after.size());
// Append remaining test items.
- before.addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 16L, 0L, 0L, 0L)
- .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 8L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 4L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 64L, 2L, 0L, 0L, 0L);
+ before.addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 16L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 8L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 4L, 0L, 0L, 0L)
+ .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 64L, 2L, 0L, 0L, 0L);
assertEquals(7, before.size());
// Test remove with empty uid list.
@@ -505,12 +505,12 @@
@Test
public void testClone() throws Exception {
final NetworkStats original = new NetworkStats(TEST_START, 5)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
// make clone and mutate original
final NetworkStats clone = original.clone();
- original.addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L);
+ original.addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L);
assertEquals(3, original.size());
assertEquals(2, clone.size());
@@ -523,8 +523,8 @@
public void testAddWhenEmpty() throws Exception {
final NetworkStats red = new NetworkStats(TEST_START, -1);
final NetworkStats blue = new NetworkStats(TEST_START, 5)
- .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
- .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
+ .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
+ .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
// We're mostly checking that we don't crash
red.combineAllValues(blue);
@@ -537,39 +537,39 @@
final String underlyingIface = "wlan0";
final int testTag1 = 8888;
NetworkStats delta = new NetworkStats(TEST_START, 17)
- .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 39605L, 46L, 12259L, 55L, 0L)
- .addValues(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
- .addValues(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 72667L, 197L, 43909L, 241L, 0L)
- .addValues(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 9297L, 17L, 4128L, 21L, 0L)
- // VPN package also uses some traffic through unprotected network.
- .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 4983L, 10L, 1801L, 12L, 0L)
- .addValues(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
- // Tag entries
- .addValues(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 21691L, 41L, 13820L, 51L, 0L)
- .addValues(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 1281L, 2L, 665L, 2L, 0L)
- // Irrelevant entries
- .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 1685L, 5L, 2070L, 6L, 0L)
- // Underlying Iface entries
- .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 5178L, 8L, 2139L, 11L, 0L)
- .addValues(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
- .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 149873L, 287L, 59217L /* smaller than sum(tun0) */,
- 299L /* smaller than sum(tun0) */, 0L)
- .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
+ .addEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 39605L, 46L, 12259L, 55L, 0L)
+ .addEntry(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
+ .addEntry(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 72667L, 197L, 43909L, 241L, 0L)
+ .addEntry(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 9297L, 17L, 4128L, 21L, 0L)
+ // VPN package also uses some traffic through unprotected network.
+ .addEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 4983L, 10L, 1801L, 12L, 0L)
+ .addEntry(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
+ // Tag entries
+ .addEntry(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 21691L, 41L, 13820L, 51L, 0L)
+ .addEntry(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 1281L, 2L, 665L, 2L, 0L)
+ // Irrelevant entries
+ .addEntry(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 1685L, 5L, 2070L, 6L, 0L)
+ // Underlying Iface entries
+ .addEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 5178L, 8L, 2139L, 11L, 0L)
+ .addEntry(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
+ .addEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 149873L, 287L, 59217L /* smaller than sum(tun0) */,
+ 299L /* smaller than sum(tun0) */, 0L)
+ .addEntry(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
- delta.migrateTun(tunUid, tunIface, new String[] {underlyingIface});
+ delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface});
assertEquals(20, delta.size());
// tunIface and TEST_IFACE entries are not changed.
@@ -634,21 +634,21 @@
final String tunIface = "tun0";
final String underlyingIface = "wlan0";
NetworkStats delta = new NetworkStats(TEST_START, 9)
- // 2 different apps sent/receive data via tun0.
- .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L)
- .addValues(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L)
- // VPN package resends data through the tunnel (with exaggerated overhead)
- .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 240000, 100L, 120000L, 60L, 0L)
- // 1 app already has some traffic on the underlying interface, the other doesn't yet
- .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 1000L, 10L, 2000L, 20L, 0L)
- // Traffic through the underlying interface via the vpn app.
- // This test should redistribute this data correctly.
- .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L);
+ // 2 different apps sent/receive data via tun0.
+ .addEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L)
+ .addEntry(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L)
+ // VPN package resends data through the tunnel (with exaggerated overhead)
+ .addEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 240000, 100L, 120000L, 60L, 0L)
+ // 1 app already has some traffic on the underlying interface, the other doesn't yet
+ .addEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 1000L, 10L, 2000L, 20L, 0L)
+ // Traffic through the underlying interface via the vpn app.
+ // This test should redistribute this data correctly.
+ .addEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L);
delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface});
assertEquals(9, delta.size());
@@ -697,9 +697,9 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3);
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3);
stats.filter(UID_ALL, INTERFACES_ALL, TAG_ALL);
assertEquals(3, stats.size());
@@ -724,9 +724,9 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3);
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3);
stats.filter(testUid, INTERFACES_ALL, TAG_ALL);
assertEquals(2, stats.size());
@@ -755,10 +755,10 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 4)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3)
- .addValues(entry4);
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3)
+ .addEntry(entry4);
stats.filter(UID_ALL, new String[] { testIf1, testIf2 }, TAG_ALL);
assertEquals(3, stats.size());
@@ -778,8 +778,8 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addValues(entry1)
- .addValues(entry2);
+ .addEntry(entry1)
+ .addEntry(entry2);
stats.filter(UID_ALL, new String[] { }, TAG_ALL);
assertEquals(0, stats.size());
@@ -802,9 +802,9 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3);
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3);
stats.filter(UID_ALL, INTERFACES_ALL, testTag);
assertEquals(2, stats.size());
@@ -831,10 +831,10 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 4)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3)
- .addValues(entry4);
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3)
+ .addEntry(entry4);
stats.filterDebugEntries();
@@ -891,14 +891,14 @@
0 /* operations */);
final NetworkStats statsXt = new NetworkStats(TEST_START, 3)
- .addValues(appEntry)
- .addValues(xtRootUidEntry)
- .addValues(otherEntry);
+ .addEntry(appEntry)
+ .addEntry(xtRootUidEntry)
+ .addEntry(otherEntry);
final NetworkStats statsEbpf = new NetworkStats(TEST_START, 3)
- .addValues(appEntry)
- .addValues(ebpfRootUidEntry)
- .addValues(otherEntry);
+ .addEntry(appEntry)
+ .addEntry(ebpfRootUidEntry)
+ .addEntry(otherEntry);
statsXt.apply464xlatAdjustments(stackedIface, false);
statsEbpf.apply464xlatAdjustments(stackedIface, true);
@@ -945,8 +945,8 @@
0 /* operations */);
NetworkStats stats = new NetworkStats(TEST_START, 2)
- .addValues(firstEntry)
- .addValues(secondEntry);
+ .addEntry(firstEntry)
+ .addEntry(secondEntry);
// Empty map: no adjustment
stats.apply464xlatAdjustments(new ArrayMap<>(), false);
diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
index 5cb0d7e..e632aaf 100644
--- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
+++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
@@ -22,8 +22,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
-import android.net.SocketKeepalive.InvalidPacketException;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/TelephonyNetworkSpecifierTest.java b/tests/net/java/android/net/TelephonyNetworkSpecifierTest.java
new file mode 100644
index 0000000..47afed4
--- /dev/null
+++ b/tests/net/java/android/net/TelephonyNetworkSpecifierTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
+
+import static org.junit.Assert.assertEquals;
+
+import android.telephony.SubscriptionManager;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit test for {@link android.net.TelephonyNetworkSpecifier}.
+ */
+@SmallTest
+public class TelephonyNetworkSpecifierTest {
+ private static final int TEST_SUBID = 5;
+
+ /**
+ * Validate that IllegalArgumentException will be thrown if build TelephonyNetworkSpecifier
+ * without calling {@link TelephonyNetworkSpecifier.Builder#setSubscriptionId(int)}.
+ */
+ @Test
+ public void testBuilderBuildWithDefault() {
+ try {
+ new TelephonyNetworkSpecifier.Builder().build();
+ } catch (IllegalArgumentException iae) {
+ // expected, test pass
+ }
+ }
+
+ /**
+ * Validate that no exception will be thrown even if pass invalid subscription id to
+ * {@link TelephonyNetworkSpecifier.Builder#setSubscriptionId(int)}.
+ */
+ @Test
+ public void testBuilderBuildWithInvalidSubId() {
+ TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier.Builder()
+ .setSubscriptionId(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+ .build();
+ assertEquals(specifier.getSubscriptionId(), SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ }
+
+ /**
+ * Validate the correctness of TelephonyNetworkSpecifier when provide valid subId.
+ */
+ @Test
+ public void testBuilderBuildWithValidSubId() {
+ final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier.Builder()
+ .setSubscriptionId(TEST_SUBID)
+ .build();
+ assertEquals(TEST_SUBID, specifier.getSubscriptionId());
+ }
+
+ /**
+ * Validate that parcel marshalling/unmarshalling works.
+ */
+ @Test
+ public void testParcel() {
+ TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier.Builder()
+ .setSubscriptionId(TEST_SUBID)
+ .build();
+ assertParcelSane(specifier, 1 /* fieldCount */);
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b2d363e..783f8d1 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -21,6 +21,8 @@
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
@@ -114,6 +116,7 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.Manifest;
import android.annotation.NonNull;
import android.app.AlarmManager;
import android.app.NotificationManager;
@@ -129,6 +132,7 @@
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
+import android.net.CaptivePortalData;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.ConnectivityManager.PacketKeepalive;
@@ -165,6 +169,7 @@
import android.net.RouteInfo;
import android.net.SocketKeepalive;
import android.net.UidRange;
+import android.net.Uri;
import android.net.metrics.IpConnectivityLog;
import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
@@ -243,8 +248,10 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -347,6 +354,8 @@
@Spy private Resources mResources;
private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
+ // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
+ private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();
MockContext(Context base, ContentProvider settingsProvider) {
super(base);
@@ -417,13 +426,39 @@
}
@Override
+ public int checkPermission(String permission, int pid, int uid) {
+ final Integer granted = mMockedPermissions.get(permission);
+ if (granted == null) {
+ // All non-mocked permissions should be held by the test or unnecessary: check as
+ // normal to make sure the code does not rely on unexpected permissions.
+ return super.checkPermission(permission, pid, uid);
+ }
+ return granted;
+ }
+
+ @Override
public void enforceCallingOrSelfPermission(String permission, String message) {
- // The mainline permission can only be held if signed with the network stack certificate
- // Skip testing for this permission.
- if (NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK.equals(permission)) return;
- // All other permissions should be held by the test or unnecessary: check as normal to
- // make sure the code does not rely on unexpected permissions.
- super.enforceCallingOrSelfPermission(permission, message);
+ final Integer granted = mMockedPermissions.get(permission);
+ if (granted == null) {
+ super.enforceCallingOrSelfPermission(permission, message);
+ return;
+ }
+
+ if (!granted.equals(PERMISSION_GRANTED)) {
+ throw new SecurityException("[Test] permission denied: " + permission);
+ }
+ }
+
+ /**
+ * Mock checks for the specified permission, and have them behave as per {@code granted}.
+ *
+ * <p>Passing null reverts to default behavior, which does a real permission check on the
+ * test package.
+ * @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
+ * {@link PackageManager#PERMISSION_DENIED}.
+ */
+ public void setPermission(String permission, Integer granted) {
+ mMockedPermissions.put(permission, granted);
}
@Override
@@ -575,7 +610,7 @@
}
};
- assertEquals(na.netId, nmNetworkCaptor.getValue().netId);
+ assertEquals(na.network.netId, nmNetworkCaptor.getValue().netId);
mNmCallbacks = nmCbCaptor.getValue();
mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
@@ -1750,6 +1785,66 @@
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
}
+ private void doNetworkCallbacksSanitizationTest(boolean sanitized) throws Exception {
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ final TestNetworkCallback defaultCallback = new TestNetworkCallback();
+ final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI).build();
+ mCm.registerNetworkCallback(wifiRequest, callback);
+ mCm.registerDefaultNetworkCallback(defaultCallback);
+
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+
+ final LinkProperties newLp = new LinkProperties();
+ final Uri capportUrl = Uri.parse("https://capport.example.com/api");
+ final CaptivePortalData capportData = new CaptivePortalData.Builder()
+ .setCaptive(true).build();
+ newLp.setCaptivePortalApiUrl(capportUrl);
+ newLp.setCaptivePortalData(capportData);
+ mWiFiNetworkAgent.sendLinkProperties(newLp);
+
+ final Uri expectedCapportUrl = sanitized ? null : capportUrl;
+ final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
+ callback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
+ Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())
+ && Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
+ defaultCallback.expectLinkPropertiesThat(mWiFiNetworkAgent, lp ->
+ Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl())
+ && Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
+
+ final LinkProperties lp = mCm.getLinkProperties(mWiFiNetworkAgent.getNetwork());
+ assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
+ assertEquals(expectedCapportData, lp.getCaptivePortalData());
+ }
+
+ @Test
+ public void networkCallbacksSanitizationTest_Sanitize() throws Exception {
+ mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ PERMISSION_DENIED);
+ mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
+ PERMISSION_DENIED);
+ doNetworkCallbacksSanitizationTest(true /* sanitized */);
+ }
+
+ @Test
+ public void networkCallbacksSanitizationTest_NoSanitize_NetworkStack() throws Exception {
+ mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ PERMISSION_GRANTED);
+ mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
+ doNetworkCallbacksSanitizationTest(false /* sanitized */);
+ }
+
+ @Test
+ public void networkCallbacksSanitizationTest_NoSanitize_Settings() throws Exception {
+ mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ PERMISSION_DENIED);
+ mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+ doNetworkCallbacksSanitizationTest(false /* sanitized */);
+ }
+
@Test
public void testMultipleLingering() throws Exception {
// This test would be flaky with the default 120ms timer: that is short enough that
@@ -2628,6 +2723,8 @@
final String testKey = "testkey";
final String testValue = "testvalue";
testBundle.putString(testKey, testValue);
+ mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ PERMISSION_GRANTED);
mCm.startCaptivePortalApp(wifiNetwork, testBundle);
final Intent signInIntent = mServiceContext.expectStartActivityIntent(TIMEOUT_MS);
assertEquals(ACTION_CAPTIVE_PORTAL_SIGN_IN, signInIntent.getAction());
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 535298f..e863266 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -36,9 +36,8 @@
import android.net.INetd;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkFactory;
import android.net.NetworkInfo;
-import android.net.NetworkMisc;
+import android.net.NetworkProvider;
import android.net.NetworkScore;
import android.os.INetworkManagementService;
import android.text.format.DateUtils;
@@ -75,7 +74,6 @@
@Mock INetd mNetd;
@Mock INetworkManagementService mNMS;
@Mock Context mCtx;
- @Mock NetworkMisc mMisc;
@Mock NetworkNotificationManager mNotifier;
@Mock Resources mResources;
@@ -358,8 +356,8 @@
NetworkScore ns = new NetworkScore();
ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50);
NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
- caps, ns, mCtx, null, mMisc, mConnService, mNetd, mDnsResolver, mNMS,
- NetworkFactory.SerialNumber.NONE);
+ caps, ns, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS,
+ NetworkProvider.ID_NONE);
nai.everValidated = true;
return nai;
}
diff --git a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
index b783467..de1028c 100644
--- a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
+++ b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
@@ -51,6 +51,7 @@
import android.net.NetworkPolicyManager;
import android.net.NetworkTemplate;
import android.net.StringNetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
import android.os.Handler;
import android.provider.Settings;
import android.telephony.TelephonyManager;
@@ -229,7 +230,7 @@
verify(mCM).registerNetworkCallback(any(), networkCallback.capture(), any());
// Simulate callback after capability changes
- final NetworkCapabilities capabilities = new NetworkCapabilities()
+ NetworkCapabilities capabilities = new NetworkCapabilities()
.addCapability(NET_CAPABILITY_INTERNET)
.addTransportType(TRANSPORT_CELLULAR)
.setNetworkSpecifier(new StringNetworkSpecifier("234"));
@@ -239,6 +240,19 @@
networkCallback.getValue().onCapabilitiesChanged(
TEST_NETWORK,
capabilities);
+
+ // make sure it also works with the new introduced TelephonyNetworkSpecifier
+ capabilities = new NetworkCapabilities()
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addTransportType(TRANSPORT_CELLULAR)
+ .setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
+ .setSubscriptionId(234).build());
+ if (!roaming) {
+ capabilities.addCapability(NET_CAPABILITY_NOT_ROAMING);
+ }
+ networkCallback.getValue().onCapabilitiesChanged(
+ TEST_NETWORK,
+ capabilities);
}
@Test
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
index b709af1..9b24887 100644
--- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -33,8 +33,8 @@
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.NetworkAgentConfig;
import android.net.NetworkInfo;
-import android.net.NetworkMisc;
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.test.TestLooper;
@@ -63,7 +63,6 @@
static final int NETID = 42;
@Mock ConnectivityService mConnectivity;
- @Mock NetworkMisc mMisc;
@Mock IDnsResolver mDnsResolver;
@Mock INetd mNetd;
@Mock INetworkManagementService mNms;
@@ -72,6 +71,7 @@
TestLooper mLooper;
Handler mHandler;
+ NetworkAgentConfig mAgentConfig = new NetworkAgentConfig();
Nat464Xlat makeNat464Xlat() {
return new Nat464Xlat(mNai, mNetd, mDnsResolver, mNms) {
@@ -93,7 +93,7 @@
mNai.networkInfo = new NetworkInfo(null);
mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI);
when(mNai.connService()).thenReturn(mConnectivity);
- when(mNai.netMisc()).thenReturn(mMisc);
+ when(mNai.netAgentConfig()).thenReturn(mAgentConfig);
when(mNai.handler()).thenReturn(mHandler);
when(mNms.getInterfaceConfig(eq(STACKED_IFACE))).thenReturn(mConfig);
@@ -104,7 +104,7 @@
String msg = String.format("requiresClat expected %b for type=%d state=%s skip=%b "
+ "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(),
nai.networkInfo.getDetailedState(),
- mMisc.skip464xlat, nai.linkProperties.getNat64Prefix(),
+ mAgentConfig.skip464xlat, nai.linkProperties.getNat64Prefix(),
nai.linkProperties.getLinkAddresses());
assertEquals(msg, expected, Nat464Xlat.requiresClat(nai));
}
@@ -113,7 +113,7 @@
String msg = String.format("shouldStartClat expected %b for type=%d state=%s skip=%b "
+ "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(),
nai.networkInfo.getDetailedState(),
- mMisc.skip464xlat, nai.linkProperties.getNat64Prefix(),
+ mAgentConfig.skip464xlat, nai.linkProperties.getNat64Prefix(),
nai.linkProperties.getLinkAddresses());
assertEquals(msg, expected, Nat464Xlat.shouldStartClat(nai));
}
@@ -151,11 +151,11 @@
assertRequiresClat(true, mNai);
assertShouldStartClat(true, mNai);
- mMisc.skip464xlat = true;
+ mAgentConfig.skip464xlat = true;
assertRequiresClat(false, mNai);
assertShouldStartClat(false, mNai);
- mMisc.skip464xlat = false;
+ mAgentConfig.skip464xlat = false;
assertRequiresClat(true, mNai);
assertShouldStartClat(true, mNai);
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
index c0f9dc1..f0e5774 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -326,14 +326,14 @@
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -359,14 +359,14 @@
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -391,14 +391,14 @@
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -424,14 +424,14 @@
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
+ .addEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
+ .addEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 4d42a61..a9e0b9a 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -80,6 +80,7 @@
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
+import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
@@ -102,6 +103,7 @@
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config;
import com.android.testutils.HandlerUtilsKt;
+import com.android.testutils.TestableNetworkStatsProvider;
import libcore.io.IoUtils;
@@ -298,11 +300,11 @@
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 1024L, 8L, 2048L, 16L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L));
mService.setUidForeground(UID_RED, false);
mService.incrementOperationCount(UID_RED, 0xFAAD, 4);
mService.setUidForeground(UID_RED, true);
@@ -407,9 +409,9 @@
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 10);
forcePollAndWaitForIdle();
@@ -429,9 +431,9 @@
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
forcePollAndWaitForIdle();
@@ -443,10 +445,10 @@
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 2176L, 17L, 1536L, 12L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L));
mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10);
forcePollAndWaitForIdle();
@@ -480,10 +482,10 @@
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 4128L, 258L, 544L, 34L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
- .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
+ .addEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
mService.incrementOperationCount(UID_RED, 0xFAAD, 10);
forcePollAndWaitForIdle();
@@ -501,10 +503,10 @@
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 4128L, 258L, 544L, 34L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
- .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
+ .addEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
final Intent intent = new Intent(ACTION_UID_REMOVED);
intent.putExtra(EXTRA_UID, UID_BLUE);
mServiceContext.sendBroadcast(intent);
@@ -536,8 +538,8 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 5);
forcePollAndWaitForIdle();
@@ -552,8 +554,8 @@
states = new NetworkState[] {buildMobile4gState(TEST_IFACE2)};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
forcePollAndWaitForIdle();
@@ -564,10 +566,10 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
- .addValues(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .addEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
+ .addEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L));
mService.incrementOperationCount(UID_RED, 0xFAAD, 5);
forcePollAndWaitForIdle();
@@ -591,9 +593,9 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
forcePollAndWaitForIdle();
@@ -608,9 +610,9 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
- .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L));
forcePollAndWaitForIdle();
// first verify entire history present
@@ -654,9 +656,9 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3));
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .addEntry(entry3));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
NetworkStats stats = mService.getDetailedUidStats(INTERFACES_ALL);
@@ -704,11 +706,11 @@
.thenReturn(augmentedIfaceFilter);
when(mStatsFactory.readNetworkStatsDetail(eq(UID_ALL), any(), eq(TAG_ALL)))
.thenReturn(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(uidStats));
+ .addEntry(uidStats));
when(mNetManager.getNetworkStatsTethering(STATS_PER_UID))
.thenReturn(new NetworkStats(getElapsedRealtime(), 2)
- .addValues(tetheredStats1)
- .addValues(tetheredStats2));
+ .addEntry(tetheredStats1)
+ .addEntry(tetheredStats2));
NetworkStats stats = mService.getDetailedUidStats(ifaceFilter);
@@ -745,8 +747,8 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
forcePollAndWaitForIdle();
@@ -760,10 +762,10 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L));
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L)
+ .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L));
mService.setUidForeground(UID_RED, true);
mService.incrementOperationCount(UID_RED, 0xFAAD, 1);
@@ -804,9 +806,9 @@
// and DEFAULT_NETWORK_YES, because these three properties aren't tracked at that layer.
// We layer them on top by inspecting the iface properties.
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
@@ -843,9 +845,9 @@
// ROAMING_NO, because metered and roaming isn't tracked at that layer. We layer it
// on top by inspecting the iface properties.
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO,
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L));
forcePollAndWaitForIdle();
@@ -885,10 +887,10 @@
// Traffic for UID_RED.
final NetworkStats uidStats = new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L);
+ .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L);
// All tethering traffic, both hardware and software.
final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L,
+ .addEntry(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L,
0L);
expectNetworkStatsSummary(ifaceStats, tetherStatsHardware);
@@ -1001,6 +1003,88 @@
mService.unregisterUsageRequest(unknownRequest);
}
+ @Test
+ public void testStatsProviderUpdateStats() throws Exception {
+ // Pretend that network comes online.
+ expectDefaultSettings();
+ final NetworkState[] states = new NetworkState[]{buildWifiState(true /* isMetered */)};
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
+
+ // Register custom provider and retrieve callback.
+ final TestableNetworkStatsProvider provider = new TestableNetworkStatsProvider();
+ final INetworkStatsProviderCallback cb =
+ mService.registerNetworkStatsProvider("TEST", provider);
+ assertNotNull(cb);
+
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+
+ // Verifies that one requestStatsUpdate will be called during iface update.
+ provider.expectStatsUpdate(0 /* unused */);
+
+ // Create some initial traffic and report to the service.
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ final NetworkStats expectedStats = new NetworkStats(0L, 1)
+ .addValues(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT,
+ TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
+ 128L, 2L, 128L, 2L, 1L))
+ .addValues(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT,
+ 0xF00D, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
+ 64L, 1L, 64L, 1L, 1L));
+ cb.onStatsUpdated(0 /* unused */, expectedStats, expectedStats);
+
+ // Make another empty mutable stats object. This is necessary since the new NetworkStats
+ // object will be used to compare with the old one in NetworkStatsRecoder, two of them
+ // cannot be the same object.
+ expectNetworkStatsUidDetail(buildEmptyStats());
+
+ forcePollAndWaitForIdle();
+
+ // Verifies that one requestStatsUpdate and setAlert will be called during polling.
+ provider.expectStatsUpdate(0 /* unused */);
+ provider.expectSetAlert(MB_IN_BYTES);
+
+ // Verifies that service recorded history, does not verify uid tag part.
+ assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1);
+
+ // Verifies that onStatsUpdated updates the stats accordingly.
+ final NetworkStats stats = mSession.getSummaryForAllUid(
+ sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
+ assertEquals(2, stats.size());
+ assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 1L);
+ assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
+ DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1L);
+
+ // Verifies that unregister the callback will remove the provider from service.
+ cb.unregister();
+ forcePollAndWaitForIdle();
+ provider.assertNoCallback();
+ }
+
+ @Test
+ public void testStatsProviderSetAlert() throws Exception {
+ // Pretend that network comes online.
+ expectDefaultSettings();
+ NetworkState[] states = new NetworkState[]{buildWifiState(true /* isMetered */)};
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+
+ // Register custom provider and retrieve callback.
+ final TestableNetworkStatsProvider provider = new TestableNetworkStatsProvider();
+ final INetworkStatsProviderCallback cb =
+ mService.registerNetworkStatsProvider("TEST", provider);
+ assertNotNull(cb);
+
+ // Simulates alert quota of the provider has been reached.
+ cb.onAlertReached();
+ HandlerUtilsKt.waitForIdle(mHandler, WAIT_TIMEOUT);
+
+ // Verifies that polling is triggered by alert reached.
+ provider.expectStatsUpdate(0 /* unused */);
+ // Verifies that global alert will be re-armed.
+ provider.expectSetAlert(MB_IN_BYTES);
+ }
+
private static File getBaseDir(File statsDir) {
File baseDir = new File(statsDir, "netstats");
baseDir.mkdirs();
@@ -1102,6 +1186,7 @@
private void expectSettings(long persistBytes, long bucketDuration, long deleteAge)
throws Exception {
when(mSettings.getPollInterval()).thenReturn(HOUR_IN_MILLIS);
+ when(mSettings.getPollDelay()).thenReturn(0L);
when(mSettings.getSampleEnabled()).thenReturn(true);
final Config config = new Config(bucketDuration, deleteAge, deleteAge);
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 45cea81..40eae54 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -1643,8 +1643,14 @@
ParsedResource* out_resource) {
out_resource->name.type = ResourceType::kStyleable;
- // Declare-styleable is kPrivate by default, because it technically only exists in R.java.
- out_resource->visibility_level = Visibility::Level::kPublic;
+ if (!options_.preserve_visibility_of_styleables) {
+ // This was added in change Idd21b5de4d20be06c6f8c8eb5a22ccd68afc4927 to mimic aapt1, but no one
+ // knows exactly what for.
+ //
+ // FWIW, styleables only appear in generated R classes. For custom views these should always be
+ // package-private (to be used only by the view class); themes are a different story.
+ out_resource->visibility_level = Visibility::Level::kPublic;
+ }
// Declare-styleable only ends up in default config;
if (out_resource->config != ConfigDescription::DefaultConfig()) {
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index 06bb0c9..9d3ecc8 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -46,6 +46,12 @@
*/
bool error_on_positional_arguments = true;
+ /**
+ * If true, apply the same visibility rules for styleables as are used for
+ * all other resources. Otherwise, all styleables will be made public.
+ */
+ bool preserve_visibility_of_styleables = false;
+
// If visibility was forced, we need to use it when creating a new resource and also error if we
// try to parse the <public>, <public-group>, <java-symbol> or <symbol> tags.
Maybe<Visibility::Level> visibility;
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 464225f..46ad7cb 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -611,6 +611,32 @@
EXPECT_THAT(styleable->entries[2].name, Eq(make_value(test::ParseNameOrDie("attr/baz"))));
}
+TEST_F(ResourceParserTest, ParseDeclareStyleablePreservingVisibility) {
+ StringInputStream input(R"(
+ <resources>
+ <declare-styleable name="foo">
+ <attr name="myattr" />
+ </declare-styleable>
+ <declare-styleable name="bar">
+ <attr name="myattr" />
+ </declare-styleable>
+ <public type="styleable" name="bar" />
+ </resources>)");
+ ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"},
+ ConfigDescription::DefaultConfig(),
+ ResourceParserOptions{.preserve_visibility_of_styleables = true});
+
+ xml::XmlPullParser xml_parser(&input);
+ ASSERT_TRUE(parser.Parse(&xml_parser));
+
+ EXPECT_EQ(
+ table_.FindResource(test::ParseNameOrDie("styleable/foo")).value().entry->visibility.level,
+ Visibility::Level::kUndefined);
+ EXPECT_EQ(
+ table_.FindResource(test::ParseNameOrDie("styleable/bar")).value().entry->visibility.level,
+ Visibility::Level::kPublic);
+}
+
TEST_F(ResourceParserTest, ParsePrivateAttributesDeclareStyleable) {
std::string input = R"(
<declare-styleable xmlns:privAndroid="http://schemas.android.com/apk/prv/res/android"
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index 9b81369f..2171970 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -159,6 +159,7 @@
ResourceParserOptions parser_options;
parser_options.error_on_positional_arguments = !options.legacy_mode;
+ parser_options.preserve_visibility_of_styleables = options.preserve_visibility_of_styleables;
parser_options.translatable = translatable_file;
// If visibility was forced, we need to use it when creating a new resource and also error if
diff --git a/tools/aapt2/cmd/Compile.h b/tools/aapt2/cmd/Compile.h
index d3456b2..1752a1a 100644
--- a/tools/aapt2/cmd/Compile.h
+++ b/tools/aapt2/cmd/Compile.h
@@ -35,6 +35,8 @@
bool pseudolocalize = false;
bool no_png_crunch = false;
bool legacy_mode = false;
+ // See comments on aapt::ResourceParserOptions.
+ bool preserve_visibility_of_styleables = false;
bool verbose = false;
};
@@ -56,6 +58,11 @@
AddOptionalSwitch("--no-crunch", "Disables PNG processing", &options_.no_png_crunch);
AddOptionalSwitch("--legacy", "Treat errors that used to be valid in AAPT as warnings",
&options_.legacy_mode);
+ AddOptionalSwitch("--preserve-visibility-of-styleables",
+ "If specified, apply the same visibility rules for\n"
+ "styleables as are used for all other resources.\n"
+ "Otherwise, all stylesables will be made public.",
+ &options_.preserve_visibility_of_styleables);
AddOptionalFlag("--visibility",
"Sets the visibility of the compiled resources to the specified\n"
"level. Accepted levels: public, private, default", &visibility_);
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index 46105f4..0b2077d 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -149,7 +149,12 @@
The package name of the class containing the field/method.
"""
full_class_name = signature.split(";->")[0]
- package_name = full_class_name[1:full_class_name.rindex("/")]
+ # Example: Landroid/hardware/radio/V1_2/IRadio$Proxy
+ if (full_class_name[0] != "L"):
+ raise ValueError("Expected to start with 'L': %s" % full_class_name)
+ full_class_name = full_class_name[1:]
+ # If full_class_name doesn't contain '/', then package_name will be ''.
+ package_name = full_class_name.rpartition("/")[0]
return package_name.replace('/', '.')
class FlagsDict:
diff --git a/tools/lock_agent/Android.bp b/tools/lock_agent/Android.bp
index 79dce4a..7b2ca9a 100644
--- a/tools/lock_agent/Android.bp
+++ b/tools/lock_agent/Android.bp
@@ -25,6 +25,7 @@
srcs: ["agent.cpp"],
static_libs: [
"libbase",
+ "liblog",
"libz",
"slicer",
],
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index c08f9b0..d3958a6 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -21,9 +21,16 @@
name: "stats-log-api-gen",
srcs: [
"Collation.cpp",
+ "atoms_info_writer.cpp",
+ "java_writer.cpp",
+ "java_writer_q.cpp",
"main.cpp",
+ "native_writer.cpp",
+ "native_writer_q.cpp",
+ "utils.cpp",
],
cflags: [
+ "-DSTATS_SCHEMA_LEGACY",
"-Wall",
"-Werror",
],
@@ -98,28 +105,23 @@
cc_library {
name: "libstatslog",
host_supported: true,
- generated_sources: ["statslog.cpp"],
- generated_headers: ["statslog.h"],
+ generated_sources: [
+ "statslog.cpp",
+ ],
+ generated_headers: [
+ "statslog.h"
+ ],
cflags: [
"-Wall",
"-Werror",
],
- export_generated_headers: ["statslog.h"],
+ export_generated_headers: [
+ "statslog.h"
+ ],
shared_libs: [
"liblog",
"libcutils",
],
static_libs: ["libstatssocket"],
- target: {
- android: {
- shared_libs: [
- "libutils",
- ],
- },
- host: {
- static_libs: [
- "libutils",
- ],
- },
- },
}
+
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index 373adca..fa55601 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -379,6 +379,7 @@
int errorCount = 0;
const bool dbg = false;
+ int maxPushedAtomId = 2;
for (int i = 0; i < descriptor->field_count(); i++) {
const FieldDescriptor *atomField = descriptor->field(i);
@@ -447,8 +448,14 @@
}
atoms->non_chained_decls.insert(nonChainedAtomDecl);
}
+
+ if (atomDecl.code < PULL_ATOM_START_ID && atomDecl.code > maxPushedAtomId) {
+ maxPushedAtomId = atomDecl.code;
+ }
}
+ atoms->maxPushedAtomId = maxPushedAtomId;
+
if (dbg) {
printf("signatures = [\n");
for (map<vector<java_type_t>, set<string>>::const_iterator it =
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index 44746c9..3efdd52 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -111,6 +111,7 @@
set<AtomDecl> decls;
set<AtomDecl> non_chained_decls;
map<vector<java_type_t>, set<string>> non_chained_signatures_to_modules;
+ int maxPushedAtomId;
};
/**
@@ -123,4 +124,4 @@
} // namespace android
-#endif // ANDROID_STATS_LOG_API_GEN_COLLATION_H
\ No newline at end of file
+#endif // ANDROID_STATS_LOG_API_GEN_COLLATION_H
diff --git a/tools/stats_log_api_gen/atoms_info_writer.cpp b/tools/stats_log_api_gen/atoms_info_writer.cpp
new file mode 100644
index 0000000..54a9982
--- /dev/null
+++ b/tools/stats_log_api_gen/atoms_info_writer.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "atoms_info_writer.h"
+#include "utils.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+namespace android {
+namespace stats_log_api_gen {
+
+static void write_atoms_info_header_body(FILE* out, const Atoms& atoms) {
+ fprintf(out, "struct StateAtomFieldOptions {\n");
+ fprintf(out, " std::vector<int> primaryFields;\n");
+ fprintf(out, " int exclusiveField;\n");
+ fprintf(out, "};\n");
+ fprintf(out, "\n");
+
+ fprintf(out, "struct AtomsInfo {\n");
+ fprintf(out,
+ " const static std::set<int> "
+ "kTruncatingTimestampAtomBlackList;\n");
+ fprintf(out, " const static std::map<int, int> kAtomsWithUidField;\n");
+ fprintf(out,
+ " const static std::set<int> kAtomsWithAttributionChain;\n");
+ fprintf(out,
+ " const static std::map<int, StateAtomFieldOptions> "
+ "kStateAtomsFieldOptions;\n");
+ fprintf(out,
+ " const static std::map<int, std::vector<int>> "
+ "kBytesFieldAtoms;\n");
+ fprintf(out,
+ " const static std::set<int> kWhitelistedAtoms;\n");
+ fprintf(out, "};\n");
+ fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n", atoms.maxPushedAtomId);
+
+}
+
+static void write_atoms_info_cpp_body(FILE* out, const Atoms& atoms) {
+ std::set<string> kTruncatingAtomNames = {"mobile_radio_power_state_changed",
+ "audio_state_changed",
+ "call_state_changed",
+ "phone_signal_strength_changed",
+ "mobile_bytes_transfer_by_fg_bg",
+ "mobile_bytes_transfer"};
+ fprintf(out,
+ "const std::set<int> "
+ "AtomsInfo::kTruncatingTimestampAtomBlackList = {\n");
+ for (set<string>::const_iterator blacklistedAtom = kTruncatingAtomNames.begin();
+ blacklistedAtom != kTruncatingAtomNames.end(); blacklistedAtom++) {
+ fprintf(out, " %s,\n", make_constant_name(*blacklistedAtom).c_str());
+ }
+ fprintf(out, "};\n");
+ fprintf(out, "\n");
+
+ fprintf(out,
+ "const std::set<int> AtomsInfo::kAtomsWithAttributionChain = {\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ for (vector<AtomField>::const_iterator field = atom->fields.begin();
+ field != atom->fields.end(); field++) {
+ if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ string constant = make_constant_name(atom->name);
+ fprintf(out, " %s,\n", constant.c_str());
+ break;
+ }
+ }
+ }
+
+ fprintf(out, "};\n");
+ fprintf(out, "\n");
+
+ fprintf(out,
+ "const std::set<int> AtomsInfo::kWhitelistedAtoms = {\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ if (atom->whitelisted) {
+ string constant = make_constant_name(atom->name);
+ fprintf(out, " %s,\n", constant.c_str());
+ }
+ }
+
+ fprintf(out, "};\n");
+ fprintf(out, "\n");
+
+ fprintf(out, "static std::map<int, int> getAtomUidField() {\n");
+ fprintf(out, " std::map<int, int> uidField;\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ if (atom->uidField == 0) {
+ continue;
+ }
+ fprintf(out,
+ "\n // Adding uid field for atom "
+ "(%d)%s\n",
+ atom->code, atom->name.c_str());
+ fprintf(out, " uidField[static_cast<int>(%s)] = %d;\n",
+ make_constant_name(atom->name).c_str(), atom->uidField);
+ }
+
+ fprintf(out, " return uidField;\n");
+ fprintf(out, "};\n");
+
+ fprintf(out,
+ "const std::map<int, int> AtomsInfo::kAtomsWithUidField = "
+ "getAtomUidField();\n");
+
+ fprintf(out,
+ "static std::map<int, StateAtomFieldOptions> "
+ "getStateAtomFieldOptions() {\n");
+ fprintf(out, " std::map<int, StateAtomFieldOptions> options;\n");
+ fprintf(out, " StateAtomFieldOptions opt;\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
+ continue;
+ }
+ fprintf(out,
+ "\n // Adding primary and exclusive fields for atom "
+ "(%d)%s\n",
+ atom->code, atom->name.c_str());
+ fprintf(out, " opt.primaryFields.clear();\n");
+ for (const auto& field : atom->primaryFields) {
+ fprintf(out, " opt.primaryFields.push_back(%d);\n", field);
+ }
+
+ fprintf(out, " opt.exclusiveField = %d;\n", atom->exclusiveField);
+ fprintf(out, " options[static_cast<int>(%s)] = opt;\n",
+ make_constant_name(atom->name).c_str());
+ }
+
+ fprintf(out, " return options;\n");
+ fprintf(out, "}\n");
+
+ fprintf(out,
+ "const std::map<int, StateAtomFieldOptions> "
+ "AtomsInfo::kStateAtomsFieldOptions = "
+ "getStateAtomFieldOptions();\n");
+
+ fprintf(out,
+ "static std::map<int, std::vector<int>> "
+ "getBinaryFieldAtoms() {\n");
+ fprintf(out, " std::map<int, std::vector<int>> options;\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ if (atom->binaryFields.size() == 0) {
+ continue;
+ }
+ fprintf(out,
+ "\n // Adding binary fields for atom "
+ "(%d)%s\n",
+ atom->code, atom->name.c_str());
+
+ for (const auto& field : atom->binaryFields) {
+ fprintf(out, " options[static_cast<int>(%s)].push_back(%d);\n",
+ make_constant_name(atom->name).c_str(), field);
+ }
+ }
+
+ fprintf(out, " return options;\n");
+ fprintf(out, "}\n");
+
+ fprintf(out,
+ "const std::map<int, std::vector<int>> "
+ "AtomsInfo::kBytesFieldAtoms = "
+ "getBinaryFieldAtoms();\n");
+
+}
+
+int write_atoms_info_header(FILE* out, const Atoms &atoms, const string& namespaceStr) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+ fprintf(out, "#pragma once\n");
+ fprintf(out, "\n");
+ fprintf(out, "#include <vector>\n");
+ fprintf(out, "#include <map>\n");
+ fprintf(out, "#include <set>\n");
+ fprintf(out, "\n");
+
+ write_namespace(out, namespaceStr);
+
+ write_atoms_info_header_body(out, atoms);
+
+ fprintf(out, "\n");
+ write_closing_namespace(out, namespaceStr);
+
+ return 0;
+}
+
+int write_atoms_info_cpp(FILE *out, const Atoms &atoms, const string& namespaceStr,
+ const string& importHeader, const string& statslogHeader) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+ fprintf(out, "#include <%s>\n", importHeader.c_str());
+ fprintf(out, "#include <%s>\n", statslogHeader.c_str());
+ fprintf(out, "\n");
+
+ write_namespace(out, namespaceStr);
+
+ write_atoms_info_cpp_body(out, atoms);
+
+ // Print footer
+ fprintf(out, "\n");
+ write_closing_namespace(out, namespaceStr);
+
+ return 0;
+}
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/atoms_info_writer.h b/tools/stats_log_api_gen/atoms_info_writer.h
new file mode 100644
index 0000000..12ac862
--- /dev/null
+++ b/tools/stats_log_api_gen/atoms_info_writer.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+int write_atoms_info_cpp(FILE* out, const Atoms& atoms, const string& namespaceStr,
+ const string& importHeader, const string& statslogHeader);
+
+int write_atoms_info_header(FILE* out, const Atoms& atoms, const string& namespaceStr);
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
new file mode 100644
index 0000000..fef490c
--- /dev/null
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "java_writer.h"
+#include "java_writer_q.h"
+#include "utils.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+static int write_java_q_logger_class(
+ FILE* out,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl,
+ const string& moduleName
+ ) {
+ fprintf(out, "\n");
+ fprintf(out, " // Write logging helper methods for statsd in Q and earlier.\n");
+ fprintf(out, " private static class QLogger {\n");
+
+ write_java_q_logging_constants(out, " ");
+
+ // Print Q write methods.
+ fprintf(out, "\n");
+ fprintf(out, " // Write methods.\n");
+ write_java_methods_q_schema(
+ out, signatures_to_modules, attributionDecl, moduleName, " ");
+
+ fprintf(out, " }\n");
+ return 0;
+}
+
+
+static int write_java_methods(
+ FILE* out,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl,
+ const string& moduleName,
+ const bool supportQ
+ ) {
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ // Skip if this signature is not needed for the module.
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+
+ // Print method signature.
+ if (DEFAULT_MODULE_NAME == moduleName) {
+ fprintf(out, " /** @hide */\n");
+ }
+ fprintf(out, " public static void write(int code");
+ vector<java_type_t> signature = signature_to_modules_it->first;
+ int argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ fprintf(out, ", %s[] %s",
+ java_type_name(chainField.javaType), chainField.name.c_str());
+ }
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, ", SparseArray<Object> valueMap");
+ } else {
+ fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ") {\n");
+
+ // Print method body.
+ string indent("");
+ if (supportQ) {
+ // TODO(b/146235828): Use just SDK_INT check once it is incremented from Q.
+ fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q ||\n");
+ fprintf(out, " Build.VERSION.CODENAME.equals(\"R\")) {\n");
+ indent = " ";
+ }
+
+ // Start StatsEvent.Builder.
+ fprintf(out, "%s final StatsEvent.Builder builder = StatsEvent.newBuilder();\n",
+ indent.c_str());
+
+ // Write atom code.
+ fprintf(out, "%s builder.setAtomId(code);\n", indent.c_str());
+
+ // Write the args.
+ argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ switch (*arg) {
+ case JAVA_TYPE_BOOLEAN:
+ fprintf(out, "%s builder.writeBoolean(arg%d);\n", indent.c_str(), argIndex);
+ break;
+ case JAVA_TYPE_INT:
+ case JAVA_TYPE_ENUM:
+ fprintf(out, "%s builder.writeInt(arg%d);\n", indent.c_str(), argIndex);
+ break;
+ case JAVA_TYPE_FLOAT:
+ fprintf(out, "%s builder.writeFloat(arg%d);\n", indent.c_str(), argIndex);
+ break;
+ case JAVA_TYPE_LONG:
+ fprintf(out, "%s builder.writeLong(arg%d);\n", indent.c_str(), argIndex);
+ break;
+ case JAVA_TYPE_STRING:
+ fprintf(out, "%s builder.writeString(arg%d);\n", indent.c_str(), argIndex);
+ break;
+ case JAVA_TYPE_BYTE_ARRAY:
+ fprintf(out, "%s builder.writeByteArray(null == arg%d ? new byte[0] : arg%d);\n",
+ indent.c_str(), argIndex, argIndex);
+ break;
+ case JAVA_TYPE_ATTRIBUTION_CHAIN:
+ {
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+
+ fprintf(out, "%s builder.writeAttributionChain(\n", indent.c_str());
+ fprintf(out, "%s null == %s ? new int[0] : %s,\n",
+ indent.c_str(), uidName, uidName);
+ fprintf(out, "%s null == %s ? new String[0] : %s);\n",
+ indent.c_str(), tagName, tagName);
+ break;
+ }
+ case JAVA_TYPE_KEY_VALUE_PAIR:
+ fprintf(out, "\n");
+ fprintf(out,
+ "%s // Write KeyValuePairs.\n", indent.c_str());
+ fprintf(out,
+ "%s final int count = valueMap.size();\n", indent.c_str());
+ fprintf(out,
+ "%s final SparseIntArray intMap = new SparseIntArray();\n",
+ indent.c_str());
+ fprintf(out,
+ "%s final SparseLongArray longMap = new SparseLongArray();\n",
+ indent.c_str());
+ fprintf(out,
+ "%s final SparseArray<String> stringMap = new SparseArray<>();\n",
+ indent.c_str());
+ fprintf(out,
+ "%s final SparseArray<Float> floatMap = new SparseArray<>();\n",
+ indent.c_str());
+ fprintf(out,
+ "%s for (int i = 0; i < count; i++) {\n", indent.c_str());
+ fprintf(out,
+ "%s final int key = valueMap.keyAt(i);\n", indent.c_str());
+ fprintf(out,
+ "%s final Object value = valueMap.valueAt(i);\n",
+ indent.c_str());
+ fprintf(out,
+ "%s if (value instanceof Integer) {\n", indent.c_str());
+ fprintf(out,
+ "%s intMap.put(key, (Integer) value);\n", indent.c_str());
+ fprintf(out,
+ "%s } else if (value instanceof Long) {\n", indent.c_str());
+ fprintf(out,
+ "%s longMap.put(key, (Long) value);\n", indent.c_str());
+ fprintf(out,
+ "%s } else if (value instanceof String) {\n", indent.c_str());
+ fprintf(out,
+ "%s stringMap.put(key, (String) value);\n", indent.c_str());
+ fprintf(out,
+ "%s } else if (value instanceof Float) {\n", indent.c_str());
+ fprintf(out,
+ "%s floatMap.put(key, (Float) value);\n", indent.c_str());
+ fprintf(out,
+ "%s }\n", indent.c_str());
+ fprintf(out,
+ "%s }\n", indent.c_str());
+ fprintf(out,
+ "%s builder.writeKeyValuePairs("
+ "intMap, longMap, stringMap, floatMap);\n", indent.c_str());
+ break;
+ default:
+ // Unsupported types: OBJECT, DOUBLE.
+ fprintf(stderr, "Encountered unsupported type.");
+ return 1;
+ }
+ argIndex++;
+ }
+
+ fprintf(out, "\n");
+ fprintf(out, "%s builder.usePooledBuffer();\n", indent.c_str());
+ fprintf(out, "%s StatsLog.write(builder.build());\n", indent.c_str());
+
+ // Add support for writing using Q schema if this is not the default module.
+ if (supportQ) {
+ fprintf(out, " } else {\n");
+ fprintf(out, " QLogger.write(code");
+ argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out, ", %s, %s", uidName, tagName);
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ // Module logging does not yet support key value pair.
+ fprintf(stderr, "Module logging does not yet support key value pair.\n");
+ return 1;
+ } else {
+ fprintf(out, ", arg%d", argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ");\n");
+ fprintf(out, " }\n"); // if
+ }
+
+ fprintf(out, " }\n"); // method
+ fprintf(out, "\n");
+ }
+ return 0;
+
+}
+
+int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& javaClass,
+ const string& javaPackage, const bool supportQ) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+ fprintf(out, "package %s;\n", javaPackage.c_str());
+ fprintf(out, "\n");
+ fprintf(out, "\n");
+ if (supportQ) {
+ fprintf(out, "import android.os.Build;\n");
+ fprintf(out, "import android.os.SystemClock;\n");
+ }
+
+ if (DEFAULT_MODULE_NAME == moduleName) {
+ // Mainline modules don't use WorkSource logging.
+ fprintf(out, "import android.os.WorkSource;\n");
+
+ // SparseArray is used for writing KeyValuePairs; not supported for Mainline modules.
+ fprintf(out, "import android.util.SparseArray;\n");
+ fprintf(out, "import android.util.SparseIntArray;\n");
+ fprintf(out, "import android.util.SparseLongArray;\n");
+ }
+
+ fprintf(out, "import android.util.StatsEvent;\n");
+ fprintf(out, "import android.util.StatsLog;\n");
+
+ if (DEFAULT_MODULE_NAME == moduleName) {
+ // List is used for WorkSource writing. Only needed for default module.
+ fprintf(out, "\n");
+ fprintf(out, "import java.util.ArrayList;\n");
+ }
+
+ fprintf(out, "\n");
+ fprintf(out, "\n");
+ fprintf(out, "/**\n");
+ fprintf(out, " * Utility class for logging statistics events.\n");
+ if (DEFAULT_MODULE_NAME == moduleName) {
+ fprintf(out, " * @hide\n");
+ }
+ fprintf(out, " */\n");
+ fprintf(out, "public class %s {\n", javaClass.c_str());
+
+ write_java_atom_codes(out, atoms, moduleName);
+ write_java_enum_values(out, atoms, moduleName);
+
+ int errors = 0;
+
+ // Print write methods.
+ fprintf(out, " // Write methods\n");
+ errors += write_java_methods(
+ out, atoms.signatures_to_modules, attributionDecl, moduleName, supportQ);
+ errors += write_java_non_chained_methods(
+ out, atoms.non_chained_signatures_to_modules, moduleName);
+ if (DEFAULT_MODULE_NAME == moduleName) {
+ errors += write_java_work_source_methods(out, atoms.signatures_to_modules, moduleName);
+ }
+
+ if (supportQ) {
+ errors += write_java_q_logger_class(
+ out, atoms.signatures_to_modules, attributionDecl, moduleName);
+ }
+
+ fprintf(out, "}\n");
+
+ return errors;
+}
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/java_writer.h b/tools/stats_log_api_gen/java_writer.h
new file mode 100644
index 0000000..9324b23
--- /dev/null
+++ b/tools/stats_log_api_gen/java_writer.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& javaClass,
+ const string& javaPackage, const bool supportQ);
+
+} // namespace stats_log_api_gen
+} // namespace android
+
diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp
new file mode 100644
index 0000000..d6899f6
--- /dev/null
+++ b/tools/stats_log_api_gen/java_writer_q.cpp
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "java_writer_q.h"
+#include "utils.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+void write_java_q_logging_constants(FILE* out, const string& indent) {
+ fprintf(out, "%s// Payload limits.\n", indent.c_str());
+ fprintf(out, "%sprivate static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;\n", indent.c_str());
+ fprintf(out,
+ "%sprivate static final int MAX_EVENT_PAYLOAD = LOGGER_ENTRY_MAX_PAYLOAD - 4;\n",
+ indent.c_str());
+
+ // Value types. Must match with EventLog.java and log.h.
+ fprintf(out, "\n");
+ fprintf(out, "%s// Value types.\n", indent.c_str());
+ fprintf(out, "%sprivate static final byte INT_TYPE = 0;\n", indent.c_str());
+ fprintf(out, "%sprivate static final byte LONG_TYPE = 1;\n", indent.c_str());
+ fprintf(out, "%sprivate static final byte STRING_TYPE = 2;\n", indent.c_str());
+ fprintf(out, "%sprivate static final byte LIST_TYPE = 3;\n", indent.c_str());
+ fprintf(out, "%sprivate static final byte FLOAT_TYPE = 4;\n", indent.c_str());
+
+ // Size of each value type.
+ // Booleans, ints, floats, and enums take 5 bytes, 1 for the type and 4 for the value.
+ fprintf(out, "\n");
+ fprintf(out, "%s// Size of each value type.\n", indent.c_str());
+ fprintf(out, "%sprivate static final int INT_TYPE_SIZE = 5;\n", indent.c_str());
+ fprintf(out, "%sprivate static final int FLOAT_TYPE_SIZE = 5;\n", indent.c_str());
+ // Longs take 9 bytes, 1 for the type and 8 for the value.
+ fprintf(out, "%sprivate static final int LONG_TYPE_SIZE = 9;\n", indent.c_str());
+ // Strings take 5 metadata bytes: 1 byte is for the type, 4 are for the length.
+ fprintf(out, "%sprivate static final int STRING_TYPE_OVERHEAD = 5;\n", indent.c_str());
+ fprintf(out, "%sprivate static final int LIST_TYPE_OVERHEAD = 2;\n", indent.c_str());
+}
+
+int write_java_methods_q_schema(
+ FILE* out,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl,
+ const string& moduleName,
+ const string& indent) {
+ int requiredHelpers = 0;
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ // Skip if this signature is not needed for the module.
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+
+ // Print method signature.
+ vector<java_type_t> signature = signature_to_modules_it->first;
+ fprintf(out, "%spublic static void write(int code", indent.c_str());
+ int argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ fprintf(out, ", %s[] %s",
+ java_type_name(chainField.javaType), chainField.name.c_str());
+ }
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ // Module logging does not yet support key value pair.
+ fprintf(stderr, "Module logging does not yet support key value pair.\n");
+ continue;
+ } else {
+ fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ") {\n");
+
+ // Calculate the size of the buffer.
+ fprintf(out, "%s // Initial overhead of the list, timestamp, and atom tag.\n",
+ indent.c_str());
+ fprintf(out,
+ "%s int needed = LIST_TYPE_OVERHEAD + LONG_TYPE_SIZE + INT_TYPE_SIZE;\n",
+ indent.c_str());
+ argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ switch (*arg) {
+ case JAVA_TYPE_BOOLEAN:
+ case JAVA_TYPE_INT:
+ case JAVA_TYPE_FLOAT:
+ case JAVA_TYPE_ENUM:
+ fprintf(out, "%s needed += INT_TYPE_SIZE;\n", indent.c_str());
+ break;
+ case JAVA_TYPE_LONG:
+ // Longs take 9 bytes, 1 for the type and 8 for the value.
+ fprintf(out, "%s needed += LONG_TYPE_SIZE;\n", indent.c_str());
+ break;
+ case JAVA_TYPE_STRING:
+ // Strings take 5 metadata bytes + length of byte encoded string.
+ fprintf(out, "%s if (arg%d == null) {\n", indent.c_str(), argIndex);
+ fprintf(out, "%s arg%d = \"\";\n", indent.c_str(), argIndex);
+ fprintf(out, "%s }\n", indent.c_str());
+ fprintf(out,
+ "%s byte[] arg%dBytes = "
+ "arg%d.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n",
+ indent.c_str(), argIndex, argIndex);
+ fprintf(out, "%s needed += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n",
+ indent.c_str(), argIndex);
+ break;
+ case JAVA_TYPE_BYTE_ARRAY:
+ // Byte arrays take 5 metadata bytes + length of byte array.
+ fprintf(out, "%s if (arg%d == null) {\n", indent.c_str(), argIndex);
+ fprintf(out, "%s arg%d = new byte[0];\n", indent.c_str(), argIndex);
+ fprintf(out, "%s }\n", indent.c_str());
+ fprintf(out, "%s needed += STRING_TYPE_OVERHEAD + arg%d.length;\n",
+ indent.c_str(), argIndex);
+ break;
+ case JAVA_TYPE_ATTRIBUTION_CHAIN:
+ {
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ // Null checks on the params.
+ fprintf(out, "%s if (%s == null) {\n", indent.c_str(), uidName);
+ fprintf(out, "%s %s = new %s[0];\n", indent.c_str(), uidName,
+ java_type_name(attributionDecl.fields.front().javaType));
+ fprintf(out, "%s }\n", indent.c_str());
+ fprintf(out, "%s if (%s == null) {\n", indent.c_str(), tagName);
+ fprintf(out, "%s %s = new %s[0];\n", indent.c_str(), tagName,
+ java_type_name(attributionDecl.fields.back().javaType));
+ fprintf(out, "%s }\n", indent.c_str());
+
+ // First check that the lengths of the uid and tag arrays are the same.
+ fprintf(out, "%s if (%s.length != %s.length) {\n",
+ indent.c_str(), uidName, tagName);
+ fprintf(out, "%s return;\n", indent.c_str());
+ fprintf(out, "%s }\n", indent.c_str());
+ fprintf(out, "%s int attrSize = LIST_TYPE_OVERHEAD;\n", indent.c_str());
+ fprintf(out, "%s for (int i = 0; i < %s.length; i++) {\n",
+ indent.c_str(), tagName);
+ fprintf(out, "%s String str%d = (%s[i] == null) ? \"\" : %s[i];\n",
+ indent.c_str(), argIndex, tagName, tagName);
+ fprintf(out,
+ "%s int str%dlen = "
+ "str%d.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;\n",
+ indent.c_str(), argIndex, argIndex);
+ fprintf(out,
+ "%s attrSize += "
+ "LIST_TYPE_OVERHEAD + INT_TYPE_SIZE + STRING_TYPE_OVERHEAD + str%dlen;\n",
+ indent.c_str(), argIndex);
+ fprintf(out, "%s }\n", indent.c_str());
+ fprintf(out, "%s needed += attrSize;\n", indent.c_str());
+ break;
+ }
+ default:
+ // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIR.
+ fprintf(stderr, "Module logging does not yet support key value pair.\n");
+ return 1;
+ }
+ argIndex++;
+ }
+
+ // Now we have the size that is needed. Check for overflow and return if needed.
+ fprintf(out, "%s if (needed > MAX_EVENT_PAYLOAD) {\n", indent.c_str());
+ fprintf(out, "%s return;\n", indent.c_str());
+ fprintf(out, "%s }\n", indent.c_str());
+
+ // Create new buffer, and associated data types.
+ fprintf(out, "%s byte[] buff = new byte[needed];\n", indent.c_str());
+ fprintf(out, "%s int pos = 0;\n", indent.c_str());
+
+ // Initialize the buffer with list data type.
+ fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 1] = %zu;\n", indent.c_str(), signature.size() + 2);
+ fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+
+ // Write timestamp.
+ fprintf(out, "%s long elapsedRealtime = SystemClock.elapsedRealtimeNanos();\n", indent.c_str());
+ fprintf(out, "%s buff[pos] = LONG_TYPE;\n", indent.c_str());
+ fprintf(out, "%s copyLong(buff, pos + 1, elapsedRealtime);\n", indent.c_str());
+ fprintf(out, "%s pos += LONG_TYPE_SIZE;\n", indent.c_str());
+
+ // Write atom code.
+ fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
+ fprintf(out, "%s copyInt(buff, pos + 1, code);\n", indent.c_str());
+ fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
+
+ // Write the args.
+ argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ switch (*arg) {
+ case JAVA_TYPE_BOOLEAN:
+ fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
+ fprintf(out, "%s copyInt(buff, pos + 1, arg%d? 1 : 0);\n",
+ indent.c_str(), argIndex);
+ fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
+ break;
+ case JAVA_TYPE_INT:
+ case JAVA_TYPE_ENUM:
+ fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
+ fprintf(out, "%s copyInt(buff, pos + 1, arg%d);\n", indent.c_str(), argIndex);
+ fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
+ break;
+ case JAVA_TYPE_FLOAT:
+ requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT;
+ fprintf(out, "%s buff[pos] = FLOAT_TYPE;\n", indent.c_str());
+ fprintf(out, "%s copyFloat(buff, pos + 1, arg%d);\n", indent.c_str(), argIndex);
+ fprintf(out, "%s pos += FLOAT_TYPE_SIZE;\n", indent.c_str());
+ break;
+ case JAVA_TYPE_LONG:
+ fprintf(out, "%s buff[pos] = LONG_TYPE;\n", indent.c_str());
+ fprintf(out, "%s copyLong(buff, pos + 1, arg%d);\n", indent.c_str(), argIndex);
+ fprintf(out, "%s pos += LONG_TYPE_SIZE;\n", indent.c_str());
+ break;
+ case JAVA_TYPE_STRING:
+ fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str());
+ fprintf(out, "%s copyInt(buff, pos + 1, arg%dBytes.length);\n",
+ indent.c_str(), argIndex);
+ fprintf(out, "%s System.arraycopy("
+ "arg%dBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, arg%dBytes.length);\n",
+ indent.c_str(), argIndex, argIndex);
+ fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n",
+ indent.c_str(), argIndex);
+ break;
+ case JAVA_TYPE_BYTE_ARRAY:
+ fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str());
+ fprintf(out, "%s copyInt(buff, pos + 1, arg%d.length);\n",
+ indent.c_str(), argIndex);
+ fprintf(out, "%s System.arraycopy("
+ "arg%d, 0, buff, pos + STRING_TYPE_OVERHEAD, arg%d.length);\n",
+ indent.c_str(), argIndex, argIndex);
+ fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + arg%d.length;\n",
+ indent.c_str(), argIndex);
+ break;
+ case JAVA_TYPE_ATTRIBUTION_CHAIN:
+ {
+ requiredHelpers |= JAVA_MODULE_REQUIRES_ATTRIBUTION;
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+
+ fprintf(out, "%s writeAttributionChain(buff, pos, %s, %s);\n", indent.c_str(),
+ uidName, tagName);
+ fprintf(out, "%s pos += attrSize;\n", indent.c_str());
+ break;
+ }
+ default:
+ // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIR.
+ fprintf(stderr,
+ "Object, Double, and KeyValuePairs are not supported in module logging");
+ return 1;
+ }
+ argIndex++;
+ }
+
+ fprintf(out, "%s StatsLog.writeRaw(buff, pos);\n", indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "\n");
+ }
+
+ write_java_helpers_for_q_schema_methods(out, attributionDecl, requiredHelpers, indent);
+
+ return 0;
+}
+
+void write_java_helpers_for_q_schema_methods(
+ FILE* out,
+ const AtomDecl &attributionDecl,
+ const int requiredHelpers,
+ const string& indent) {
+ fprintf(out, "\n");
+ fprintf(out, "%s// Helper methods for copying primitives\n", indent.c_str());
+ fprintf(out, "%sprivate static void copyInt(byte[] buff, int pos, int val) {\n",
+ indent.c_str());
+ fprintf(out, "%s buff[pos] = (byte) (val);\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 1] = (byte) (val >> 8);\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 2] = (byte) (val >> 16);\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 3] = (byte) (val >> 24);\n", indent.c_str());
+ fprintf(out, "%s return;\n", indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "\n");
+
+ fprintf(out, "%sprivate static void copyLong(byte[] buff, int pos, long val) {\n",
+ indent.c_str());
+ fprintf(out, "%s buff[pos] = (byte) (val);\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 1] = (byte) (val >> 8);\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 2] = (byte) (val >> 16);\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 3] = (byte) (val >> 24);\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 4] = (byte) (val >> 32);\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 5] = (byte) (val >> 40);\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 6] = (byte) (val >> 48);\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 7] = (byte) (val >> 56);\n", indent.c_str());
+ fprintf(out, "%s return;\n", indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "\n");
+
+ if (requiredHelpers & JAVA_MODULE_REQUIRES_FLOAT) {
+ fprintf(out, "%sprivate static void copyFloat(byte[] buff, int pos, float val) {\n",
+ indent.c_str());
+ fprintf(out, "%s copyInt(buff, pos, Float.floatToIntBits(val));\n", indent.c_str());
+ fprintf(out, "%s return;\n", indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "\n");
+ }
+
+ if (requiredHelpers & JAVA_MODULE_REQUIRES_ATTRIBUTION) {
+ fprintf(out, "%sprivate static void writeAttributionChain(byte[] buff, int pos",
+ indent.c_str());
+ for (auto chainField : attributionDecl.fields) {
+ fprintf(out, ", %s[] %s",
+ java_type_name(chainField.javaType), chainField.name.c_str());
+ }
+ fprintf(out, ") {\n");
+
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+
+ // Write the first list begin.
+ fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 1] = (byte) (%s.length);\n", indent.c_str(), tagName);
+ fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+
+ // Iterate through the attribution chain and write the nodes.
+ fprintf(out, "%s for (int i = 0; i < %s.length; i++) {\n", indent.c_str(), tagName);
+ // Write the list begin.
+ fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
+ fprintf(out, "%s buff[pos + 1] = %lu;\n",
+ indent.c_str(), attributionDecl.fields.size());
+ fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+
+ // Write the uid.
+ fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
+ fprintf(out, "%s copyInt(buff, pos + 1, %s[i]);\n", indent.c_str(), uidName);
+ fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
+
+ // Write the tag.
+ fprintf(out, "%s String %sStr = (%s[i] == null) ? \"\" : %s[i];\n",
+ indent.c_str(), tagName, tagName, tagName);
+ fprintf(out, "%s byte[] %sByte = "
+ "%sStr.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n",
+ indent.c_str(), tagName, tagName);
+ fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str());
+ fprintf(out, "%s copyInt(buff, pos + 1, %sByte.length);\n", indent.c_str(), tagName);
+ fprintf(out, "%s System.arraycopy("
+ "%sByte, 0, buff, pos + STRING_TYPE_OVERHEAD, %sByte.length);\n",
+ indent.c_str(), tagName, tagName);
+ fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + %sByte.length;\n",
+ indent.c_str(), tagName);
+ fprintf(out, "%s }\n", indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "\n");
+ }
+}
+
+#if defined(STATS_SCHEMA_LEGACY)
+static void write_java_method(
+ FILE* out,
+ const string& method_name,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl) {
+
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ vector<java_type_t> signature = signature_to_modules_it->first;
+ fprintf(out, " /** @hide */\n");
+ fprintf(out, " public static native int %s(int code", method_name.c_str());
+ int argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ fprintf(out, ", %s[] %s",
+ java_type_name(chainField.javaType), chainField.name.c_str());
+ }
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, ", SparseArray<Object> value_map");
+ } else {
+ fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ");\n");
+ fprintf(out, "\n");
+ }
+}
+
+int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+ fprintf(out, "package android.util;\n");
+ fprintf(out, "\n");
+ fprintf(out, "import android.os.WorkSource;\n");
+ fprintf(out, "import android.util.SparseArray;\n");
+ fprintf(out, "import java.util.ArrayList;\n");
+ fprintf(out, "\n");
+ fprintf(out, "\n");
+ fprintf(out, "/**\n");
+ fprintf(out, " * API For logging statistics events.\n");
+ fprintf(out, " * @hide\n");
+ fprintf(out, " */\n");
+ fprintf(out, "public class StatsLogInternal {\n");
+ write_java_atom_codes(out, atoms, DEFAULT_MODULE_NAME);
+
+ write_java_enum_values(out, atoms, DEFAULT_MODULE_NAME);
+
+ // Print write methods
+ fprintf(out, " // Write methods\n");
+ write_java_method(out, "write", atoms.signatures_to_modules, attributionDecl);
+ write_java_method(out, "write_non_chained", atoms.non_chained_signatures_to_modules,
+ attributionDecl);
+ write_java_work_source_methods(out, atoms.signatures_to_modules, DEFAULT_MODULE_NAME);
+
+ fprintf(out, "}\n");
+
+ return 0;
+}
+
+int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& javaClass,
+ const string& javaPackage) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+ fprintf(out, "package %s;\n", javaPackage.c_str());
+ fprintf(out, "\n");
+ fprintf(out, "import static java.nio.charset.StandardCharsets.UTF_8;\n");
+ fprintf(out, "\n");
+ fprintf(out, "import android.util.StatsLog;\n");
+ fprintf(out, "import android.os.SystemClock;\n");
+ fprintf(out, "\n");
+ fprintf(out, "import java.util.ArrayList;\n");
+ fprintf(out, "\n");
+ fprintf(out, "\n");
+ fprintf(out, "/**\n");
+ fprintf(out, " * Utility class for logging statistics events.\n");
+ fprintf(out, " */\n");
+ fprintf(out, "public class %s {\n", javaClass.c_str());
+
+ write_java_q_logging_constants(out, " ");
+
+ write_java_atom_codes(out, atoms, moduleName);
+
+ write_java_enum_values(out, atoms, moduleName);
+
+ int errors = 0;
+ // Print write methods
+ fprintf(out, " // Write methods\n");
+ errors += write_java_methods_q_schema(out, atoms.signatures_to_modules, attributionDecl,
+ moduleName, " ");
+ errors += write_java_non_chained_methods(out, atoms.non_chained_signatures_to_modules,
+ moduleName);
+
+ fprintf(out, "}\n");
+
+ return errors;
+}
+#endif
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h
new file mode 100644
index 0000000..96ac745
--- /dev/null
+++ b/tools/stats_log_api_gen/java_writer_q.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+void write_java_q_logging_constants(FILE* out, const string& indent);
+
+int write_java_methods_q_schema(
+ FILE* out,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl,
+ const string& moduleName,
+ const string& indent);
+
+void write_java_helpers_for_q_schema_methods(
+ FILE * out,
+ const AtomDecl &attributionDecl,
+ const int requiredHelpers,
+ const string& indent);
+
+#if defined(STATS_SCHEMA_LEGACY)
+int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl);
+
+int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
+ const AtomDecl &attributionDecl, const string& moduleName, const string& javaClass,
+ const string& javaPackage);
+#endif
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index f62fef0..00a3704 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -1,9 +1,17 @@
#include "Collation.h"
+#include "atoms_info_writer.h"
+#if !defined(STATS_SCHEMA_LEGACY)
+#include "java_writer.h"
+#endif
+#include "java_writer_q.h"
+#include "native_writer.h"
+#include "utils.h"
#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
+#include <map>
#include <set>
#include <vector>
@@ -12,1490 +20,19 @@
#include <stdlib.h>
#include <string.h>
-#include "android-base/strings.h"
-
using namespace google::protobuf;
using namespace std;
namespace android {
namespace stats_log_api_gen {
-int maxPushedAtomId = 2;
-
-const string DEFAULT_MODULE_NAME = "DEFAULT";
-const string DEFAULT_CPP_NAMESPACE = "android,util";
-const string DEFAULT_CPP_HEADER_IMPORT = "statslog.h";
-const string DEFAULT_JAVA_PACKAGE = "android.util";
-const string DEFAULT_JAVA_CLASS = "StatsLogInternal";
-
-const int JAVA_MODULE_REQUIRES_FLOAT = 0x01;
-const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
-
using android::os::statsd::Atom;
-/**
- * Turn lower and camel case into upper case with underscores.
- */
-static string
-make_constant_name(const string& str)
-{
- string result;
- const int N = str.size();
- bool underscore_next = false;
- for (int i=0; i<N; i++) {
- char c = str[i];
- if (c >= 'A' && c <= 'Z') {
- if (underscore_next) {
- result += '_';
- underscore_next = false;
- }
- } else if (c >= 'a' && c <= 'z') {
- c = 'A' + c - 'a';
- underscore_next = true;
- } else if (c == '_') {
- underscore_next = false;
- }
- result += c;
- }
- return result;
-}
-
-static const char*
-cpp_type_name(java_type_t type)
-{
- switch (type) {
- case JAVA_TYPE_BOOLEAN:
- return "bool";
- case JAVA_TYPE_INT:
- case JAVA_TYPE_ENUM:
- return "int32_t";
- case JAVA_TYPE_LONG:
- return "int64_t";
- case JAVA_TYPE_FLOAT:
- return "float";
- case JAVA_TYPE_DOUBLE:
- return "double";
- case JAVA_TYPE_STRING:
- return "char const*";
- case JAVA_TYPE_BYTE_ARRAY:
- return "const BytesField&";
- default:
- return "UNKNOWN";
- }
-}
-
-static const char*
-java_type_name(java_type_t type)
-{
- switch (type) {
- case JAVA_TYPE_BOOLEAN:
- return "boolean";
- case JAVA_TYPE_INT:
- case JAVA_TYPE_ENUM:
- return "int";
- case JAVA_TYPE_LONG:
- return "long";
- case JAVA_TYPE_FLOAT:
- return "float";
- case JAVA_TYPE_DOUBLE:
- return "double";
- case JAVA_TYPE_STRING:
- return "java.lang.String";
- case JAVA_TYPE_BYTE_ARRAY:
- return "byte[]";
- default:
- return "UNKNOWN";
- }
-}
-
-static bool atom_needed_for_module(const AtomDecl& atomDecl, const string& moduleName) {
- if (moduleName == DEFAULT_MODULE_NAME) {
- return true;
- }
- return atomDecl.hasModule && (moduleName == atomDecl.moduleName);
-}
-
-static bool signature_needed_for_module(const set<string>& modules, const string& moduleName) {
- if (moduleName == DEFAULT_MODULE_NAME) {
- return true;
- }
- return modules.find(moduleName) != modules.end();
-}
-
-static void write_atoms_info_cpp(FILE *out, const Atoms &atoms) {
- std::set<string> kTruncatingAtomNames = {"mobile_radio_power_state_changed",
- "audio_state_changed",
- "call_state_changed",
- "phone_signal_strength_changed",
- "mobile_bytes_transfer_by_fg_bg",
- "mobile_bytes_transfer"};
- fprintf(out,
- "const std::set<int> "
- "AtomsInfo::kTruncatingTimestampAtomBlackList = {\n");
- for (set<string>::const_iterator blacklistedAtom = kTruncatingAtomNames.begin();
- blacklistedAtom != kTruncatingAtomNames.end(); blacklistedAtom++) {
- fprintf(out, " %s,\n", make_constant_name(*blacklistedAtom).c_str());
- }
- fprintf(out, "};\n");
- fprintf(out, "\n");
-
- fprintf(out,
- "const std::set<int> AtomsInfo::kAtomsWithAttributionChain = {\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- for (vector<AtomField>::const_iterator field = atom->fields.begin();
- field != atom->fields.end(); field++) {
- if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- string constant = make_constant_name(atom->name);
- fprintf(out, " %s,\n", constant.c_str());
- break;
- }
- }
- }
-
- fprintf(out, "};\n");
- fprintf(out, "\n");
-
- fprintf(out,
- "const std::set<int> AtomsInfo::kWhitelistedAtoms = {\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- if (atom->whitelisted) {
- string constant = make_constant_name(atom->name);
- fprintf(out, " %s,\n", constant.c_str());
- }
- }
-
- fprintf(out, "};\n");
- fprintf(out, "\n");
-
- fprintf(out, "static std::map<int, int> getAtomUidField() {\n");
- fprintf(out, " std::map<int, int> uidField;\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- if (atom->uidField == 0) {
- continue;
- }
- fprintf(out,
- "\n // Adding uid field for atom "
- "(%d)%s\n",
- atom->code, atom->name.c_str());
- fprintf(out, " uidField[static_cast<int>(%s)] = %d;\n",
- make_constant_name(atom->name).c_str(), atom->uidField);
- }
-
- fprintf(out, " return uidField;\n");
- fprintf(out, "};\n");
-
- fprintf(out,
- "const std::map<int, int> AtomsInfo::kAtomsWithUidField = "
- "getAtomUidField();\n");
-
- fprintf(out,
- "static std::map<int, StateAtomFieldOptions> "
- "getStateAtomFieldOptions() {\n");
- fprintf(out, " std::map<int, StateAtomFieldOptions> options;\n");
- fprintf(out, " StateAtomFieldOptions opt;\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
- continue;
- }
- fprintf(out,
- "\n // Adding primary and exclusive fields for atom "
- "(%d)%s\n",
- atom->code, atom->name.c_str());
- fprintf(out, " opt.primaryFields.clear();\n");
- for (const auto& field : atom->primaryFields) {
- fprintf(out, " opt.primaryFields.push_back(%d);\n", field);
- }
-
- fprintf(out, " opt.exclusiveField = %d;\n", atom->exclusiveField);
- fprintf(out, " options[static_cast<int>(%s)] = opt;\n",
- make_constant_name(atom->name).c_str());
- }
-
- fprintf(out, " return options;\n");
- fprintf(out, "}\n");
-
- fprintf(out,
- "const std::map<int, StateAtomFieldOptions> "
- "AtomsInfo::kStateAtomsFieldOptions = "
- "getStateAtomFieldOptions();\n");
-
- fprintf(out,
- "static std::map<int, std::vector<int>> "
- "getBinaryFieldAtoms() {\n");
- fprintf(out, " std::map<int, std::vector<int>> options;\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- if (atom->binaryFields.size() == 0) {
- continue;
- }
- fprintf(out,
- "\n // Adding binary fields for atom "
- "(%d)%s\n",
- atom->code, atom->name.c_str());
-
- for (const auto& field : atom->binaryFields) {
- fprintf(out, " options[static_cast<int>(%s)].push_back(%d);\n",
- make_constant_name(atom->name).c_str(), field);
- }
- }
-
- fprintf(out, " return options;\n");
- fprintf(out, "}\n");
-
- fprintf(out,
- "const std::map<int, std::vector<int>> "
- "AtomsInfo::kBytesFieldAtoms = "
- "getBinaryFieldAtoms();\n");
-}
-
-// Writes namespaces for the cpp and header files, returning the number of namespaces written.
-void write_namespace(FILE* out, const string& cppNamespaces) {
- vector<string> cppNamespaceVec = android::base::Split(cppNamespaces, ",");
- for (string cppNamespace : cppNamespaceVec) {
- fprintf(out, "namespace %s {\n", cppNamespace.c_str());
- }
-}
-
-// Writes namespace closing brackets for cpp and header files.
-void write_closing_namespace(FILE* out, const string& cppNamespaces) {
- vector<string> cppNamespaceVec = android::base::Split(cppNamespaces, ",");
- for (auto it = cppNamespaceVec.rbegin(); it != cppNamespaceVec.rend(); ++it) {
- fprintf(out, "} // namespace %s\n", it->c_str());
- }
-}
-
-static int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& cppNamespace,
- const string& importHeader) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
-
- fprintf(out, "#include <mutex>\n");
- fprintf(out, "#include <chrono>\n");
- fprintf(out, "#include <thread>\n");
- fprintf(out, "#ifdef __ANDROID__\n");
- fprintf(out, "#include <cutils/properties.h>\n");
- fprintf(out, "#endif\n");
- fprintf(out, "#include <stats_event_list.h>\n");
- fprintf(out, "#include <log/log.h>\n");
- fprintf(out, "#include <%s>\n", importHeader.c_str());
- fprintf(out, "#include <utils/SystemClock.h>\n");
- fprintf(out, "\n");
-
- write_namespace(out, cppNamespace);
- fprintf(out, "// the single event tag id for all stats logs\n");
- fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
- fprintf(out, "#ifdef __ANDROID__\n");
- fprintf(out, "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
- fprintf(out, "#else\n");
- fprintf(out, "const static bool kStatsdEnabled = false;\n");
- fprintf(out, "#endif\n");
-
- // AtomsInfo is only used by statsd internally and is not needed for other modules.
- if (moduleName == DEFAULT_MODULE_NAME) {
- write_atoms_info_cpp(out, atoms);
- }
-
- fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
- fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
- fprintf(out, "static std::mutex mLogdRetryMutex;\n");
-
- // Print write methods
- fprintf(out, "\n");
- for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
- signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_to_modules_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "try_stats_write(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
- "const std::map<int, int64_t>& arg%d_2, "
- "const std::map<int, char const*>& arg%d_3, "
- "const std::map<int, float>& arg%d_4",
- argIndex, argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
- argIndex = 1;
- fprintf(out, " if (kStatsdEnabled) {\n");
- fprintf(out, " stats_event_list event(kStatsEventTag);\n");
- fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
- fprintf(out, " event << code;\n\n");
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (const auto &chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, " if (%s_length != %s.size()) {\n",
- attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
- fprintf(out, " return -EINVAL;\n");
- fprintf(out, " }\n");
- }
- }
- fprintf(out, "\n event.begin();\n");
- fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
- attributionDecl.fields.front().name.c_str());
- fprintf(out, " event.begin();\n");
- for (const auto &chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
- fprintf(out, " event << %s[i];\n", chainField.name.c_str());
- fprintf(out, " } else {\n");
- fprintf(out, " event << \"\";\n");
- fprintf(out, " }\n");
- } else {
- fprintf(out, " event << %s[i];\n", chainField.name.c_str());
- }
- }
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
- fprintf(out, " event.end();\n\n");
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, " event.begin();\n\n");
- fprintf(out, " for (const auto& it : arg%d_1) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " for (const auto& it : arg%d_2) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " for (const auto& it : arg%d_3) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " for (const auto& it : arg%d_4) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " event.end();\n\n");
- } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
- fprintf(out,
- " event.AppendCharArray(arg%d.arg, "
- "arg%d.arg_length);\n",
- argIndex, argIndex);
- } else {
- if (*arg == JAVA_TYPE_STRING) {
- fprintf(out, " if (arg%d == NULL) {\n", argIndex);
- fprintf(out, " arg%d = \"\";\n", argIndex);
- fprintf(out, " }\n");
- }
- fprintf(out, " event << arg%d;\n", argIndex);
- }
- argIndex++;
- }
-
- fprintf(out, " return event.write(LOG_ID_STATS);\n");
- fprintf(out, " } else {\n");
- fprintf(out, " return 1;\n");
- fprintf(out, " }\n");
- fprintf(out, "}\n");
- fprintf(out, "\n");
- }
-
- for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
- signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_to_modules_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "stats_write(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out,
- ", const std::map<int, int32_t>& arg%d_1, "
- "const std::map<int, int64_t>& arg%d_2, "
- "const std::map<int, char const*>& arg%d_3, "
- "const std::map<int, float>& arg%d_4",
- argIndex, argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
- fprintf(out, " int ret = 0;\n");
-
- fprintf(out, " for(int retry = 0; retry < 2; ++retry) {\n");
- fprintf(out, " ret = try_stats_write(code");
-
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", %s",
- chainField.name.c_str());
- } else {
- fprintf(out, ", %s, %s_length",
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex,
- argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
- fprintf(out, " if (ret >= 0) { break; }\n");
-
- fprintf(out, " {\n");
- fprintf(out, " std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
- fprintf(out, " if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
- "kMinRetryIntervalNs) break;\n");
- fprintf(out, " lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
- fprintf(out, " }\n");
- fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
- fprintf(out, " }\n");
- fprintf(out, " if (ret < 0) {\n");
- fprintf(out, " note_log_drop(ret, code);\n");
- fprintf(out, " }\n");
- fprintf(out, " return ret;\n");
- fprintf(out, "}\n");
- fprintf(out, "\n");
- }
-
- for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
- signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
- if (!signature_needed_for_module(signature_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "try_stats_write_non_chained(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
- argIndex = 1;
- fprintf(out, " if (kStatsdEnabled) {\n");
- fprintf(out, " stats_event_list event(kStatsEventTag);\n");
- fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
- fprintf(out, " event << code;\n\n");
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (argIndex == 1) {
- fprintf(out, " event.begin();\n\n");
- fprintf(out, " event.begin();\n");
- }
- if (*arg == JAVA_TYPE_STRING) {
- fprintf(out, " if (arg%d == NULL) {\n", argIndex);
- fprintf(out, " arg%d = \"\";\n", argIndex);
- fprintf(out, " }\n");
- }
- if (*arg == JAVA_TYPE_BYTE_ARRAY) {
- fprintf(out,
- " event.AppendCharArray(arg%d.arg, "
- "arg%d.arg_length);",
- argIndex, argIndex);
- } else {
- fprintf(out, " event << arg%d;\n", argIndex);
- }
- if (argIndex == 2) {
- fprintf(out, " event.end();\n\n");
- fprintf(out, " event.end();\n\n");
- }
- argIndex++;
- }
-
- fprintf(out, " return event.write(LOG_ID_STATS);\n");
- fprintf(out, " } else {\n");
- fprintf(out, " return 1;\n");
- fprintf(out, " }\n");
- fprintf(out, "}\n");
- fprintf(out, "\n");
- }
-
- for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
- signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
- if (!signature_needed_for_module(signature_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "stats_write_non_chained(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
-
- fprintf(out, " int ret = 0;\n");
- fprintf(out, " for(int retry = 0; retry < 2; ++retry) {\n");
- fprintf(out, " ret = try_stats_write_non_chained(code");
-
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- fprintf(out, ", arg%d", argIndex);
- argIndex++;
- }
- fprintf(out, ");\n");
- fprintf(out, " if (ret >= 0) { break; }\n");
-
- fprintf(out, " {\n");
- fprintf(out, " std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
- fprintf(out, " if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
- "kMinRetryIntervalNs) break;\n");
- fprintf(out, " lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
- fprintf(out, " }\n");
- fprintf(out, " if (ret < 0) {\n");
- fprintf(out, " note_log_drop(ret, code);\n");
- fprintf(out, " }\n");
- fprintf(out, " return ret;\n\n");
- fprintf(out, "}\n");
-
- fprintf(out, "\n");
- }
-
-
- // Print footer
- fprintf(out, "\n");
- write_closing_namespace(out, cppNamespace);
-
- return 0;
-}
-
-void build_non_chained_decl_map(const Atoms& atoms,
- std::map<int, set<AtomDecl>::const_iterator>* decl_map){
- for (set<AtomDecl>::const_iterator atom = atoms.non_chained_decls.begin();
- atom != atoms.non_chained_decls.end(); atom++) {
- decl_map->insert(std::make_pair(atom->code, atom));
- }
-}
-
-static void write_cpp_usage(
- FILE* out, const string& method_name, const string& atom_code_name,
- const AtomDecl& atom, const AtomDecl &attributionDecl) {
- fprintf(out, " * Usage: %s(StatsLog.%s", method_name.c_str(),
- atom_code_name.c_str());
-
- for (vector<AtomField>::const_iterator field = atom.fields.begin();
- field != atom.fields.end(); field++) {
- if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", const std::map<int, int32_t>& %s_int"
- ", const std::map<int, int64_t>& %s_long"
- ", const std::map<int, char const*>& %s_str"
- ", const std::map<int, float>& %s_float",
- field->name.c_str(),
- field->name.c_str(),
- field->name.c_str(),
- field->name.c_str());
- } else {
- fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
- }
- }
- fprintf(out, ");\n");
-}
-
-static void write_cpp_method_header(
- FILE* out,
- const string& method_name,
- const map<vector<java_type_t>, set<string>>& signatures_to_modules,
- const AtomDecl &attributionDecl, const string& moduleName) {
-
- for (auto signature_to_modules_it = signatures_to_modules.begin();
- signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
- // Skip if this signature is not needed for the module.
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
-
- vector<java_type_t> signature = signature_to_modules_it->first;
- fprintf(out, "int %s(int32_t code", method_name.c_str());
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s",
- cpp_type_name(chainField.javaType), chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
- "const std::map<int, int64_t>& arg%d_2, "
- "const std::map<int, char const*>& arg%d_3, "
- "const std::map<int, float>& arg%d_4",
- argIndex, argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
-
- }
-}
-
-static int
-write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& cppNamespace)
-{
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "#pragma once\n");
- fprintf(out, "\n");
- fprintf(out, "#include <stdint.h>\n");
- fprintf(out, "#include <vector>\n");
- fprintf(out, "#include <map>\n");
- fprintf(out, "#include <set>\n");
- fprintf(out, "\n");
-
- write_namespace(out, cppNamespace);
- fprintf(out, "\n");
- fprintf(out, "/*\n");
- fprintf(out, " * API For logging statistics events.\n");
- fprintf(out, " */\n");
- fprintf(out, "\n");
- fprintf(out, "/**\n");
- fprintf(out, " * Constants for atom codes.\n");
- fprintf(out, " */\n");
- fprintf(out, "enum {\n");
-
- std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
- build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
-
- size_t i = 0;
- // Print atom constants
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- // Skip if the atom is not needed for the module.
- if (!atom_needed_for_module(*atom, moduleName)) {
- continue;
- }
- string constant = make_constant_name(atom->name);
- fprintf(out, "\n");
- fprintf(out, " /**\n");
- fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
- write_cpp_usage(out, "stats_write", constant, *atom, attributionDecl);
-
- auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
- if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
- write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second,
- attributionDecl);
- }
- fprintf(out, " */\n");
- char const* const comma = (i == atoms.decls.size() - 1) ? "" : ",";
- fprintf(out, " %s = %d%s\n", constant.c_str(), atom->code, comma);
- if (atom->code < PULL_ATOM_START_ID && atom->code > maxPushedAtomId) {
- maxPushedAtomId = atom->code;
- }
- i++;
- }
- fprintf(out, "\n");
- fprintf(out, "};\n");
- fprintf(out, "\n");
-
- // Print constants for the enum values.
- fprintf(out, "//\n");
- fprintf(out, "// Constants for enum values\n");
- fprintf(out, "//\n\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- // Skip if the atom is not needed for the module.
- if (!atom_needed_for_module(*atom, moduleName)) {
- continue;
- }
-
- for (vector<AtomField>::const_iterator field = atom->fields.begin();
- field != atom->fields.end(); field++) {
- if (field->javaType == JAVA_TYPE_ENUM) {
- fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
- field->name.c_str());
- for (map<int, string>::const_iterator value = field->enumValues.begin();
- value != field->enumValues.end(); value++) {
- fprintf(out, "const int32_t %s__%s__%s = %d;\n",
- make_constant_name(atom->message).c_str(),
- make_constant_name(field->name).c_str(),
- make_constant_name(value->second).c_str(),
- value->first);
- }
- fprintf(out, "\n");
- }
- }
- }
-
- fprintf(out, "struct BytesField {\n");
- fprintf(out,
- " BytesField(char const* array, size_t len) : arg(array), "
- "arg_length(len) {}\n");
- fprintf(out, " char const* arg;\n");
- fprintf(out, " size_t arg_length;\n");
- fprintf(out, "};\n");
- fprintf(out, "\n");
-
- // This metadata is only used by statsd, which uses the default libstatslog.
- if (moduleName == DEFAULT_MODULE_NAME) {
-
- fprintf(out, "struct StateAtomFieldOptions {\n");
- fprintf(out, " std::vector<int> primaryFields;\n");
- fprintf(out, " int exclusiveField;\n");
- fprintf(out, "};\n");
- fprintf(out, "\n");
-
- fprintf(out, "struct AtomsInfo {\n");
- fprintf(out,
- " const static std::set<int> "
- "kTruncatingTimestampAtomBlackList;\n");
- fprintf(out, " const static std::map<int, int> kAtomsWithUidField;\n");
- fprintf(out,
- " const static std::set<int> kAtomsWithAttributionChain;\n");
- fprintf(out,
- " const static std::map<int, StateAtomFieldOptions> "
- "kStateAtomsFieldOptions;\n");
- fprintf(out,
- " const static std::map<int, std::vector<int>> "
- "kBytesFieldAtoms;");
- fprintf(out,
- " const static std::set<int> kWhitelistedAtoms;\n");
- fprintf(out, "};\n");
-
- fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n",
- maxPushedAtomId);
- }
-
- // Print write methods
- fprintf(out, "//\n");
- fprintf(out, "// Write methods\n");
- fprintf(out, "//\n");
- write_cpp_method_header(out, "stats_write", atoms.signatures_to_modules, attributionDecl,
- moduleName);
-
- fprintf(out, "//\n");
- fprintf(out, "// Write flattened methods\n");
- fprintf(out, "//\n");
- write_cpp_method_header(out, "stats_write_non_chained", atoms.non_chained_signatures_to_modules,
- attributionDecl, moduleName);
-
- fprintf(out, "\n");
- write_closing_namespace(out, cppNamespace);
-
- return 0;
-}
-
-static void write_java_usage(FILE* out, const string& method_name, const string& atom_code_name,
- const AtomDecl& atom) {
- fprintf(out, " * Usage: StatsLog.%s(StatsLog.%s",
- method_name.c_str(), atom_code_name.c_str());
- for (vector<AtomField>::const_iterator field = atom.fields.begin();
- field != atom.fields.end(); field++) {
- if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- fprintf(out, ", android.os.WorkSource workSource");
- } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", SparseArray<Object> value_map");
- } else if (field->javaType == JAVA_TYPE_BYTE_ARRAY) {
- fprintf(out, ", byte[] %s", field->name.c_str());
- } else {
- fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
- }
- }
- fprintf(out, ");<br>\n");
-}
-
-static void write_java_method(
- FILE* out,
- const string& method_name,
- const map<vector<java_type_t>, set<string>>& signatures_to_modules,
- const AtomDecl &attributionDecl) {
-
- for (auto signature_to_modules_it = signatures_to_modules.begin();
- signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
- vector<java_type_t> signature = signature_to_modules_it->first;
- fprintf(out, " /** @hide */\n");
- fprintf(out, " public static native int %s(int code", method_name.c_str());
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- fprintf(out, ", %s[] %s",
- java_type_name(chainField.javaType), chainField.name.c_str());
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", SparseArray<Object> value_map");
- } else {
- fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
- }
-}
-
-static void write_java_helpers_for_module(
- FILE * out,
- const AtomDecl &attributionDecl,
- const int requiredHelpers) {
- fprintf(out, " private static void copyInt(byte[] buff, int pos, int val) {\n");
- fprintf(out, " buff[pos] = (byte) (val);\n");
- fprintf(out, " buff[pos + 1] = (byte) (val >> 8);\n");
- fprintf(out, " buff[pos + 2] = (byte) (val >> 16);\n");
- fprintf(out, " buff[pos + 3] = (byte) (val >> 24);\n");
- fprintf(out, " return;\n");
- fprintf(out, " }\n");
- fprintf(out, "\n");
-
- fprintf(out, " private static void copyLong(byte[] buff, int pos, long val) {\n");
- fprintf(out, " buff[pos] = (byte) (val);\n");
- fprintf(out, " buff[pos + 1] = (byte) (val >> 8);\n");
- fprintf(out, " buff[pos + 2] = (byte) (val >> 16);\n");
- fprintf(out, " buff[pos + 3] = (byte) (val >> 24);\n");
- fprintf(out, " buff[pos + 4] = (byte) (val >> 32);\n");
- fprintf(out, " buff[pos + 5] = (byte) (val >> 40);\n");
- fprintf(out, " buff[pos + 6] = (byte) (val >> 48);\n");
- fprintf(out, " buff[pos + 7] = (byte) (val >> 56);\n");
- fprintf(out, " return;\n");
- fprintf(out, " }\n");
- fprintf(out, "\n");
-
- if (requiredHelpers & JAVA_MODULE_REQUIRES_FLOAT) {
- fprintf(out, " private static void copyFloat(byte[] buff, int pos, float val) {\n");
- fprintf(out, " copyInt(buff, pos, Float.floatToIntBits(val));\n");
- fprintf(out, " return;\n");
- fprintf(out, " }\n");
- fprintf(out, "\n");
- }
-
- if (requiredHelpers & JAVA_MODULE_REQUIRES_ATTRIBUTION) {
- fprintf(out, " private static void writeAttributionChain(byte[] buff, int pos");
- for (auto chainField : attributionDecl.fields) {
- fprintf(out, ", %s[] %s",
- java_type_name(chainField.javaType), chainField.name.c_str());
- }
- fprintf(out, ") {\n");
-
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
-
- // Write the first list begin.
- fprintf(out, " buff[pos] = LIST_TYPE;\n");
- fprintf(out, " buff[pos + 1] = (byte) (%s.length);\n", tagName);
- fprintf(out, " pos += LIST_TYPE_OVERHEAD;\n");
-
- // Iterate through the attribution chain and write the nodes.
- fprintf(out, " for (int i = 0; i < %s.length; i++) {\n", tagName);
- // Write the list begin.
- fprintf(out, " buff[pos] = LIST_TYPE;\n");
- fprintf(out, " buff[pos + 1] = %lu;\n", attributionDecl.fields.size());
- fprintf(out, " pos += LIST_TYPE_OVERHEAD;\n");
-
- // Write the uid.
- fprintf(out, " buff[pos] = INT_TYPE;\n");
- fprintf(out, " copyInt(buff, pos + 1, %s[i]);\n", uidName);
- fprintf(out, " pos += INT_TYPE_SIZE;\n");
-
- // Write the tag.
- fprintf(out, " String %sStr = (%s[i] == null) ? \"\" : %s[i];\n",
- tagName, tagName, tagName);
- fprintf(out, " byte[] %sByte = %sStr.getBytes(UTF_8);\n", tagName, tagName);
- fprintf(out, " buff[pos] = STRING_TYPE;\n");
- fprintf(out, " copyInt(buff, pos + 1, %sByte.length);\n", tagName);
- fprintf(out, " System.arraycopy("
- "%sByte, 0, buff, pos + STRING_TYPE_OVERHEAD, %sByte.length);\n",
- tagName, tagName);
- fprintf(out, " pos += STRING_TYPE_OVERHEAD + %sByte.length;\n", tagName);
- fprintf(out, " }\n");
- fprintf(out, " }\n");
- fprintf(out, "\n");
- }
-}
-
-
-static int write_java_non_chained_method_for_module(
- FILE* out,
- const map<vector<java_type_t>, set<string>>& signatures_to_modules,
- const string& moduleName
- ) {
- for (auto signature_to_modules_it = signatures_to_modules.begin();
- signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
- // Skip if this signature is not needed for the module.
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
-
- // Print method signature.
- vector<java_type_t> signature = signature_to_modules_it->first;
- fprintf(out, " public static void write_non_chained(int code");
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- // Non chained signatures should not have attribution chains.
- return 1;
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- // Module logging does not yet support key value pair.
- return 1;
- } else {
- fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ") {\n");
-
- fprintf(out, " write(code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- // First two args are uid and tag of attribution chain.
- if (argIndex == 1) {
- fprintf(out, ", new int[] {arg%d}", argIndex);
- } else if (argIndex == 2) {
- fprintf(out, ", new java.lang.String[] {arg%d}", argIndex);
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
- fprintf(out, " }\n");
- fprintf(out, "\n");
- }
- return 0;
-}
-
-static int write_java_method_for_module(
- FILE* out,
- const map<vector<java_type_t>, set<string>>& signatures_to_modules,
- const AtomDecl &attributionDecl,
- const string& moduleName,
- int* requiredHelpers
- ) {
-
- for (auto signature_to_modules_it = signatures_to_modules.begin();
- signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
- // Skip if this signature is not needed for the module.
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
-
- // Print method signature.
- vector<java_type_t> signature = signature_to_modules_it->first;
- fprintf(out, " public static void write(int code");
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- fprintf(out, ", %s[] %s",
- java_type_name(chainField.javaType), chainField.name.c_str());
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- // Module logging does not yet support key value pair.
- return 1;
- } else {
- fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ") {\n");
-
- // Calculate the size of the buffer.
- fprintf(out, " // Initial overhead of the list, timestamp, and atom tag.\n");
- fprintf(out, " int needed = LIST_TYPE_OVERHEAD + LONG_TYPE_SIZE + INT_TYPE_SIZE;\n");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- switch (*arg) {
- case JAVA_TYPE_BOOLEAN:
- case JAVA_TYPE_INT:
- case JAVA_TYPE_FLOAT:
- case JAVA_TYPE_ENUM:
- fprintf(out, " needed += INT_TYPE_SIZE;\n");
- break;
- case JAVA_TYPE_LONG:
- // Longs take 9 bytes, 1 for the type and 8 for the value.
- fprintf(out, " needed += LONG_TYPE_SIZE;\n");
- break;
- case JAVA_TYPE_STRING:
- // Strings take 5 metadata bytes + length of byte encoded string.
- fprintf(out, " if (arg%d == null) {\n", argIndex);
- fprintf(out, " arg%d = \"\";\n", argIndex);
- fprintf(out, " }\n");
- fprintf(out, " byte[] arg%dBytes= arg%d.getBytes(UTF_8);\n",
- argIndex, argIndex);
- fprintf(out, " needed += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n",
- argIndex);
- break;
- case JAVA_TYPE_BYTE_ARRAY:
- // Byte arrays take 5 metadata bytes + length of byte array.
- fprintf(out, " if (arg%d == null) {\n", argIndex);
- fprintf(out, " arg%d = new byte[0];\n", argIndex);
- fprintf(out, " }\n");
- fprintf(out, " needed += STRING_TYPE_OVERHEAD + arg%d.length;\n", argIndex);
- break;
- case JAVA_TYPE_ATTRIBUTION_CHAIN:
- {
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
- // Null checks on the params.
- fprintf(out, " if (%s == null) {\n", uidName);
- fprintf(out, " %s = new %s[0];\n", uidName,
- java_type_name(attributionDecl.fields.front().javaType));
- fprintf(out, " }\n");
- fprintf(out, " if (%s == null) {\n", tagName);
- fprintf(out, " %s = new %s[0];\n", tagName,
- java_type_name(attributionDecl.fields.back().javaType));
- fprintf(out, " }\n");
-
- // First check that the lengths of the uid and tag arrays are the same.
- fprintf(out, " if (%s.length != %s.length) {\n", uidName, tagName);
- fprintf(out, " return;\n");
- fprintf(out, " }\n");
- fprintf(out, " int attrSize = LIST_TYPE_OVERHEAD;\n");
- fprintf(out, " for (int i = 0; i < %s.length; i++) {\n", tagName);
- fprintf(out, " String str%d = (%s[i] == null) ? \"\" : %s[i];\n",
- argIndex, tagName, tagName);
- fprintf(out, " int str%dlen = str%d.getBytes(UTF_8).length;\n",
- argIndex, argIndex);
- fprintf(out,
- " attrSize += "
- "LIST_TYPE_OVERHEAD + INT_TYPE_SIZE + STRING_TYPE_OVERHEAD + str%dlen;\n",
- argIndex);
- fprintf(out, " }\n");
- fprintf(out, " needed += attrSize;\n");
- break;
- }
- default:
- // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIR.
- return 1;
- }
- argIndex++;
- }
-
- // Now we have the size that is needed. Check for overflow and return if needed.
- fprintf(out, " if (needed > MAX_EVENT_PAYLOAD) {\n");
- fprintf(out, " return;\n");
- fprintf(out, " }\n");
-
- // Create new buffer, and associated data types.
- fprintf(out, " byte[] buff = new byte[needed];\n");
- fprintf(out, " int pos = 0;\n");
-
- // Initialize the buffer with list data type.
- fprintf(out, " buff[pos] = LIST_TYPE;\n");
- fprintf(out, " buff[pos + 1] = %zu;\n", signature.size() + 2);
- fprintf(out, " pos += LIST_TYPE_OVERHEAD;\n");
-
- // Write timestamp.
- fprintf(out, " long elapsedRealtime = SystemClock.elapsedRealtimeNanos();\n");
- fprintf(out, " buff[pos] = LONG_TYPE;\n");
- fprintf(out, " copyLong(buff, pos + 1, elapsedRealtime);\n");
- fprintf(out, " pos += LONG_TYPE_SIZE;\n");
-
- // Write atom code.
- fprintf(out, " buff[pos] = INT_TYPE;\n");
- fprintf(out, " copyInt(buff, pos + 1, code);\n");
- fprintf(out, " pos += INT_TYPE_SIZE;\n");
-
- // Write the args.
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- switch (*arg) {
- case JAVA_TYPE_BOOLEAN:
- fprintf(out, " buff[pos] = INT_TYPE;\n");
- fprintf(out, " copyInt(buff, pos + 1, arg%d? 1 : 0);\n", argIndex);
- fprintf(out, " pos += INT_TYPE_SIZE;\n");
- break;
- case JAVA_TYPE_INT:
- case JAVA_TYPE_ENUM:
- fprintf(out, " buff[pos] = INT_TYPE;\n");
- fprintf(out, " copyInt(buff, pos + 1, arg%d);\n", argIndex);
- fprintf(out, " pos += INT_TYPE_SIZE;\n");
- break;
- case JAVA_TYPE_FLOAT:
- *requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT;
- fprintf(out, " buff[pos] = FLOAT_TYPE;\n");
- fprintf(out, " copyFloat(buff, pos + 1, arg%d);\n", argIndex);
- fprintf(out, " pos += FLOAT_TYPE_SIZE;\n");
- break;
- case JAVA_TYPE_LONG:
- fprintf(out, " buff[pos] = LONG_TYPE;\n");
- fprintf(out, " copyLong(buff, pos + 1, arg%d);\n", argIndex);
- fprintf(out, " pos += LONG_TYPE_SIZE;\n");
- break;
- case JAVA_TYPE_STRING:
- fprintf(out, " buff[pos] = STRING_TYPE;\n");
- fprintf(out, " copyInt(buff, pos + 1, arg%dBytes.length);\n", argIndex);
- fprintf(out, " System.arraycopy("
- "arg%dBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, arg%dBytes.length);\n",
- argIndex, argIndex);
- fprintf(out, " pos += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n",
- argIndex);
- break;
- case JAVA_TYPE_BYTE_ARRAY:
- fprintf(out, " buff[pos] = STRING_TYPE;\n");
- fprintf(out, " copyInt(buff, pos + 1, arg%d.length);\n", argIndex);
- fprintf(out, " System.arraycopy("
- "arg%d, 0, buff, pos + STRING_TYPE_OVERHEAD, arg%d.length);\n",
- argIndex, argIndex);
- fprintf(out, " pos += STRING_TYPE_OVERHEAD + arg%d.length;\n", argIndex);
- break;
- case JAVA_TYPE_ATTRIBUTION_CHAIN:
- {
- *requiredHelpers |= JAVA_MODULE_REQUIRES_ATTRIBUTION;
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
-
- fprintf(out, " writeAttributionChain(buff, pos, %s, %s);\n",
- uidName, tagName);
- fprintf(out, " pos += attrSize;\n");
- break;
- }
- default:
- // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIR.
- return 1;
- }
- argIndex++;
- }
-
- fprintf(out, " StatsLog.writeRaw(buff, pos);\n");
- fprintf(out, " }\n");
- fprintf(out, "\n");
- }
- return 0;
-}
-
-static void write_java_work_source_method(FILE* out,
- const map<vector<java_type_t>, set<string>>& signatures_to_modules,
- const string& moduleName) {
- fprintf(out, "\n // WorkSource methods.\n");
- for (auto signature_to_modules_it = signatures_to_modules.begin();
- signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
- // Skip if this signature is not needed for the module.
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_to_modules_it->first;
- // Determine if there is Attribution in this signature.
- int attributionArg = -1;
- int argIndexMax = 0;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- argIndexMax++;
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- if (attributionArg > -1) {
- fprintf(stderr, "An atom contains multiple AttributionNode fields.\n");
- fprintf(stderr, "This is not supported. Aborting WorkSource method writing.\n");
- fprintf(out, "\n// Invalid for WorkSource: more than one attribution chain.\n");
- return;
- }
- attributionArg = argIndexMax;
- }
- }
- if (attributionArg < 0) {
- continue;
- }
-
- // Method header (signature)
- if (moduleName == DEFAULT_MODULE_NAME) {
- fprintf(out, " /** @hide */\n");
- }
- fprintf(out, " public static void write(int code");
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- fprintf(out, ", WorkSource ws");
- } else {
- fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ") {\n");
-
- // write_non_chained() component. TODO: Remove when flat uids are no longer needed.
- fprintf(out, " for (int i = 0; i < ws.size(); ++i) {\n");
- fprintf(out, " write_non_chained(code");
- for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
- if (argIndex == attributionArg) {
- fprintf(out, ", ws.get(i), ws.getName(i)");
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- }
- fprintf(out, ");\n");
- fprintf(out, " }\n"); // close for-loop
-
- // write() component.
- fprintf(out, " ArrayList<WorkSource.WorkChain> workChains = ws.getWorkChains();\n");
- fprintf(out, " if (workChains != null) {\n");
- fprintf(out, " for (WorkSource.WorkChain wc : workChains) {\n");
- fprintf(out, " write(code");
- for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
- if (argIndex == attributionArg) {
- fprintf(out, ", wc.getUids(), wc.getTags()");
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- }
- fprintf(out, ");\n");
- fprintf(out, " }\n"); // close for-loop
- fprintf(out, " }\n"); // close if
- fprintf(out, " }\n"); // close method
- }
-}
-
-static void write_java_atom_codes(FILE* out, const Atoms& atoms, const string& moduleName) {
- fprintf(out, " // Constants for atom codes.\n");
-
- std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
- build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
-
- // Print constants for the atom codes.
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- // Skip if the atom is not needed for the module.
- if (!atom_needed_for_module(*atom, moduleName)) {
- continue;
- }
- string constant = make_constant_name(atom->name);
- fprintf(out, "\n");
- fprintf(out, " /**\n");
- fprintf(out, " * %s %s<br>\n", atom->message.c_str(), atom->name.c_str());
- write_java_usage(out, "write", constant, *atom);
- auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
- if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
- write_java_usage(out, "write_non_chained", constant, *non_chained_decl->second);
- }
- if (moduleName == DEFAULT_MODULE_NAME) {
- fprintf(out, " * @hide\n");
- }
- fprintf(out, " */\n");
- fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code);
- }
- fprintf(out, "\n");
-}
-
-static void write_java_enum_values(FILE* out, const Atoms& atoms, const string& moduleName) {
- fprintf(out, " // Constants for enum values.\n\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- // Skip if the atom is not needed for the module.
- if (!atom_needed_for_module(*atom, moduleName)) {
- continue;
- }
- for (vector<AtomField>::const_iterator field = atom->fields.begin();
- field != atom->fields.end(); field++) {
- if (field->javaType == JAVA_TYPE_ENUM) {
- fprintf(out, " // Values for %s.%s\n", atom->message.c_str(),
- field->name.c_str());
- for (map<int, string>::const_iterator value = field->enumValues.begin();
- value != field->enumValues.end(); value++) {
- if (moduleName == DEFAULT_MODULE_NAME) {
- fprintf(out, " /** @hide */\n");
- }
- fprintf(out, " public static final int %s__%s__%s = %d;\n",
- make_constant_name(atom->message).c_str(),
- make_constant_name(field->name).c_str(),
- make_constant_name(value->second).c_str(),
- value->first);
- }
- fprintf(out, "\n");
- }
- }
- }
-}
-
-static int
-write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
-{
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "package android.util;\n");
- fprintf(out, "\n");
- fprintf(out, "import android.os.WorkSource;\n");
- fprintf(out, "import android.util.SparseArray;\n");
- fprintf(out, "import java.util.ArrayList;\n");
- fprintf(out, "\n");
- fprintf(out, "\n");
- fprintf(out, "/**\n");
- fprintf(out, " * API For logging statistics events.\n");
- fprintf(out, " * @hide\n");
- fprintf(out, " */\n");
- fprintf(out, "public class StatsLogInternal {\n");
- write_java_atom_codes(out, atoms, DEFAULT_MODULE_NAME);
-
- write_java_enum_values(out, atoms, DEFAULT_MODULE_NAME);
-
- // Print write methods
- fprintf(out, " // Write methods\n");
- write_java_method(out, "write", atoms.signatures_to_modules, attributionDecl);
- write_java_method(out, "write_non_chained", atoms.non_chained_signatures_to_modules,
- attributionDecl);
- write_java_work_source_method(out, atoms.signatures_to_modules, DEFAULT_MODULE_NAME);
-
- fprintf(out, "}\n");
-
- return 0;
-}
-
-// TODO: Merge this with write_stats_log_java so that we can get rid of StatsLogInternal JNI.
-static int
-write_stats_log_java_for_module(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& javaClass, const string& javaPackage)
-{
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "package %s;\n", javaPackage.c_str());
- fprintf(out, "\n");
- fprintf(out, "import static java.nio.charset.StandardCharsets.UTF_8;\n");
- fprintf(out, "\n");
- fprintf(out, "import android.util.StatsLog;\n");
- fprintf(out, "import android.os.SystemClock;\n");
- fprintf(out, "\n");
- fprintf(out, "import java.util.ArrayList;\n");
- fprintf(out, "\n");
- fprintf(out, "\n");
- fprintf(out, "/**\n");
- fprintf(out, " * Utility class for logging statistics events.\n");
- fprintf(out, " */\n");
- fprintf(out, "public class %s {\n", javaClass.c_str());
-
- // TODO: ideally these match with the native values (and automatically change if they change).
- fprintf(out, " private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;\n");
- fprintf(out,
- " private static final int MAX_EVENT_PAYLOAD = LOGGER_ENTRY_MAX_PAYLOAD - 4;\n");
- // Value types. Must match with EventLog.java and log.h.
- fprintf(out, " private static final byte INT_TYPE = 0;\n");
- fprintf(out, " private static final byte LONG_TYPE = 1;\n");
- fprintf(out, " private static final byte STRING_TYPE = 2;\n");
- fprintf(out, " private static final byte LIST_TYPE = 3;\n");
- fprintf(out, " private static final byte FLOAT_TYPE = 4;\n");
-
- // Size of each value type.
- // Booleans, ints, floats, and enums take 5 bytes, 1 for the type and 4 for the value.
- fprintf(out, " private static final int INT_TYPE_SIZE = 5;\n");
- fprintf(out, " private static final int FLOAT_TYPE_SIZE = 5;\n");
- // Longs take 9 bytes, 1 for the type and 8 for the value.
- fprintf(out, " private static final int LONG_TYPE_SIZE = 9;\n");
- // Strings take 5 metadata bytes: 1 byte is for the type, 4 are for the length.
- fprintf(out, " private static final int STRING_TYPE_OVERHEAD = 5;\n");
- fprintf(out, " private static final int LIST_TYPE_OVERHEAD = 2;\n");
-
- write_java_atom_codes(out, atoms, moduleName);
-
- write_java_enum_values(out, atoms, moduleName);
-
- int errors = 0;
- int requiredHelpers = 0;
- // Print write methods
- fprintf(out, " // Write methods\n");
- errors += write_java_method_for_module(out, atoms.signatures_to_modules, attributionDecl,
- moduleName, &requiredHelpers);
- errors += write_java_non_chained_method_for_module(out, atoms.non_chained_signatures_to_modules,
- moduleName);
-
- fprintf(out, " // Helper methods for copying primitives\n");
- write_java_helpers_for_module(out, attributionDecl, requiredHelpers);
-
- fprintf(out, "}\n");
-
- return errors;
-}
-
+// Hide the JNI write helpers that are not used in the new schema.
+// TODO(b/145100015): Remove this and other JNI related functionality once StatsEvent migration is
+// complete.
+#if defined(STATS_SCHEMA_LEGACY)
+// JNI helpers.
static const char*
jni_type_name(java_type_t type)
{
@@ -1666,7 +203,7 @@
}
static int
-write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp_method_name,
+write_stats_log_jni_method(FILE* out, const string& java_method_name, const string& cpp_method_name,
const map<vector<java_type_t>, set<string>>& signatures_to_modules,
const AtomDecl &attributionDecl) {
// Print write methods
@@ -1882,40 +419,56 @@
jni_function_name(java_method_name, signature).c_str());
}
}
+#endif // JNI helpers.
static int
+#if defined(STATS_SCHEMA_LEGACY)
write_stats_log_jni(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl)
+#else
+// Write empty JNI file that doesn't contain any JNI methods.
+// TODO(b/145100015): remove this function and all JNI autogen code once StatsEvent migration is
+// complete.
+write_stats_log_jni(FILE* out)
+#endif
{
// Print prelude
fprintf(out, "// This file is autogenerated\n");
fprintf(out, "\n");
+#if defined(STATS_SCHEMA_LEGACY)
fprintf(out, "#include <statslog.h>\n");
fprintf(out, "\n");
fprintf(out, "#include <nativehelper/JNIHelp.h>\n");
fprintf(out, "#include <nativehelper/ScopedUtfChars.h>\n");
fprintf(out, "#include <utils/Vector.h>\n");
+#endif
fprintf(out, "#include \"core_jni_helpers.h\"\n");
fprintf(out, "#include \"jni.h\"\n");
fprintf(out, "\n");
+#if defined(STATS_SCHEMA_LEGACY)
fprintf(out, "#define UNUSED __attribute__((__unused__))\n");
fprintf(out, "\n");
+#endif
fprintf(out, "namespace android {\n");
fprintf(out, "\n");
- write_stats_log_jni(out, "write", "stats_write", atoms.signatures_to_modules, attributionDecl);
- write_stats_log_jni(out, "write_non_chained", "stats_write_non_chained",
+#if defined(STATS_SCHEMA_LEGACY)
+ write_stats_log_jni_method(out, "write", "stats_write", atoms.signatures_to_modules, attributionDecl);
+ write_stats_log_jni_method(out, "write_non_chained", "stats_write_non_chained",
atoms.non_chained_signatures_to_modules, attributionDecl);
+#endif
// Print registration function table
fprintf(out, "/*\n");
fprintf(out, " * JNI registration.\n");
fprintf(out, " */\n");
fprintf(out, "static const JNINativeMethod gRegisterMethods[] = {\n");
+#if defined(STATS_SCHEMA_LEGACY)
write_jni_registration(out, "write", atoms.signatures_to_modules, attributionDecl);
write_jni_registration(out, "write_non_chained", atoms.non_chained_signatures_to_modules,
attributionDecl);
+#endif
fprintf(out, "};\n");
fprintf(out, "\n");
@@ -1938,20 +491,28 @@
fprintf(stderr, "usage: stats-log-api-gen OPTIONS\n");
fprintf(stderr, "\n");
fprintf(stderr, "OPTIONS\n");
- fprintf(stderr, " --cpp FILENAME the header file to output\n");
- fprintf(stderr, " --header FILENAME the cpp file to output\n");
+ fprintf(stderr, " --cpp FILENAME the header file to output for write helpers\n");
+ fprintf(stderr, " --header FILENAME the cpp file to output for write helpers\n");
+ fprintf(stderr,
+ " --atomsInfoCpp FILENAME the header file to output for statsd metadata\n");
+ fprintf(stderr, " --atomsInfoHeader FILENAME the cpp file to output for statsd metadata\n");
fprintf(stderr, " --help this message\n");
fprintf(stderr, " --java FILENAME the java file to output\n");
fprintf(stderr, " --jni FILENAME the jni file to output\n");
fprintf(stderr, " --module NAME optional, module name to generate outputs for\n");
fprintf(stderr, " --namespace COMMA,SEP,NAMESPACE required for cpp/header with module\n");
fprintf(stderr, " comma separated namespace of the files\n");
- fprintf(stderr, " --importHeader NAME required for cpp/jni to say which header to import\n");
+ fprintf(stderr," --importHeader NAME required for cpp/jni to say which header to import "
+ "for write helpers\n");
+ fprintf(stderr," --atomsInfoImportHeader NAME required for cpp to say which header to import "
+ "for statsd metadata\n");
fprintf(stderr, " --javaPackage PACKAGE the package for the java file.\n");
fprintf(stderr, " required for java with module\n");
fprintf(stderr, " --javaClass CLASS the class name of the java class.\n");
fprintf(stderr, " Optional for Java with module.\n");
- fprintf(stderr, " Default is \"StatsLogInternal\"\n");}
+ fprintf(stderr, " Default is \"StatsLogInternal\"\n");
+ fprintf(stderr, " --supportQ Include support for Android Q.\n");
+}
/**
* Do the argument parsing and execute the tasks.
@@ -1963,12 +524,16 @@
string headerFilename;
string javaFilename;
string jniFilename;
+ string atomsInfoCppFilename;
+ string atomsInfoHeaderFilename;
string moduleName = DEFAULT_MODULE_NAME;
string cppNamespace = DEFAULT_CPP_NAMESPACE;
string cppHeaderImport = DEFAULT_CPP_HEADER_IMPORT;
+ string atomsInfoCppHeaderImport = DEFAULT_ATOMS_INFO_CPP_HEADER_IMPORT;
string javaPackage = DEFAULT_JAVA_PACKAGE;
string javaClass = DEFAULT_JAVA_CLASS;
+ bool supportQ = false;
int index = 1;
while (index < argc) {
@@ -2038,18 +603,50 @@
return 1;
}
javaClass = argv[index];
+ } else if (0 == strcmp("--atomsInfoHeader", argv[index])) {
+ index++;
+ if (index >= argc) {
+ print_usage();
+ return 1;
+ }
+ atomsInfoHeaderFilename = argv[index];
+ } else if (0 == strcmp("--atomsInfoCpp", argv[index])) {
+ index++;
+ if (index >= argc) {
+ print_usage();
+ return 1;
+ }
+ atomsInfoCppFilename = argv[index];
+ } else if (0 == strcmp("--atomsInfoImportHeader", argv[index])) {
+ index++;
+ if (index >= argc) {
+ print_usage();
+ return 1;
+ }
+ atomsInfoCppHeaderImport = argv[index];
+ } else if (0 == strcmp("--supportQ", argv[index])) {
+ supportQ = true;
}
+
index++;
}
if (cppFilename.size() == 0
&& headerFilename.size() == 0
&& javaFilename.size() == 0
- && jniFilename.size() == 0) {
+ && jniFilename.size() == 0
+ && atomsInfoHeaderFilename.size() == 0
+ && atomsInfoCppFilename.size() == 0) {
print_usage();
return 1;
}
+ if (DEFAULT_MODULE_NAME == moduleName && supportQ) {
+ // Support for Q schema is not needed for default module.
+ fprintf(stderr, "%s cannot support Q schema\n", moduleName.c_str());
+ return 1;
+ }
+
// Collate the parameters
Atoms atoms;
int errorCount = collate_atoms(Atom::descriptor(), &atoms);
@@ -2062,6 +659,30 @@
collate_atom(android::os::statsd::AttributionNode::descriptor(),
&attributionDecl, &attributionSignature);
+ // Write the atoms info .cpp file
+ if (atomsInfoCppFilename.size() != 0) {
+ FILE* out = fopen(atomsInfoCppFilename.c_str(), "w");
+ if (out == NULL) {
+ fprintf(stderr, "Unable to open file for write: %s\n", atomsInfoCppFilename.c_str());
+ return 1;
+ }
+ errorCount = android::stats_log_api_gen::write_atoms_info_cpp(
+ out, atoms, cppNamespace, atomsInfoCppHeaderImport, cppHeaderImport);
+ fclose(out);
+ }
+
+ // Write the atoms info .h file
+ if (atomsInfoHeaderFilename.size() != 0) {
+ FILE* out = fopen(atomsInfoHeaderFilename.c_str(), "w");
+ if (out == NULL) {
+ fprintf(stderr, "Unable to open file for write: %s\n", atomsInfoHeaderFilename.c_str());
+ return 1;
+ }
+ errorCount = android::stats_log_api_gen::write_atoms_info_header(out, atoms, cppNamespace);
+ fclose(out);
+ }
+
+
// Write the .cpp file
if (cppFilename.size() != 0) {
FILE* out = fopen(cppFilename.c_str(), "w");
@@ -2080,7 +701,7 @@
return 1;
}
errorCount = android::stats_log_api_gen::write_stats_log_cpp(
- out, atoms, attributionDecl, moduleName, cppNamespace, cppHeaderImport);
+ out, atoms, attributionDecl, moduleName, cppNamespace, cppHeaderImport, supportQ);
fclose(out);
}
@@ -2112,13 +733,25 @@
fprintf(stderr, "Must supply --javaPackage if supplying a specific module\n");
return 1;
}
+
+#if defined(STATS_SCHEMA_LEGACY)
if (moduleName == DEFAULT_MODULE_NAME) {
- errorCount = android::stats_log_api_gen::write_stats_log_java(
+ errorCount = android::stats_log_api_gen::write_stats_log_java_q(
out, atoms, attributionDecl);
} else {
- errorCount = android::stats_log_api_gen::write_stats_log_java_for_module(
+ errorCount = android::stats_log_api_gen::write_stats_log_java_q_for_module(
out, atoms, attributionDecl, moduleName, javaClass, javaPackage);
+
}
+#else
+ if (moduleName == DEFAULT_MODULE_NAME) {
+ javaClass = "StatsLogInternal";
+ javaPackage = "android.util";
+ }
+ errorCount = android::stats_log_api_gen::write_stats_log_java(
+ out, atoms, attributionDecl, moduleName, javaClass, javaPackage, supportQ);
+#endif
+
fclose(out);
}
@@ -2129,16 +762,22 @@
fprintf(stderr, "Unable to open file for write: %s\n", jniFilename.c_str());
return 1;
}
+
+#if defined(STATS_SCHEMA_LEGACY)
errorCount = android::stats_log_api_gen::write_stats_log_jni(
out, atoms, attributionDecl);
+#else
+ errorCount = android::stats_log_api_gen::write_stats_log_jni(out);
+#endif
+
fclose(out);
}
return errorCount;
}
-}
-}
+} // namespace stats_log_api_gen
+} // namespace android
/**
* Main.
diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp
new file mode 100644
index 0000000..c7a34fe
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer.cpp
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "native_writer.h"
+#include "native_writer_q.h"
+#include "utils.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+#if !defined(STATS_SCHEMA_LEGACY)
+static void write_native_key_value_pairs_for_type(FILE* out, const int argIndex,
+ const int typeIndex, const string& type, const string& valueFieldName) {
+ fprintf(out, " for (const auto& it : arg%d_%d) {\n", argIndex, typeIndex);
+ fprintf(out, " pairs.push_back("
+ "{ .key = it.first, .valueType = %s, .%s = it.second });\n",
+ type.c_str(), valueFieldName.c_str());
+ fprintf(out, " }\n");
+
+}
+
+static int write_native_stats_write_methods(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName, const bool supportQ) {
+ fprintf(out, "\n");
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
+
+ write_native_method_signature(out, "int stats_write", signature,
+ attributionDecl, " {");
+
+ int argIndex = 1;
+ if (supportQ) {
+ fprintf(out, " StatsEventCompat event;\n");
+ fprintf(out, " event.setAtomId(code);\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ switch (*arg) {
+ case JAVA_TYPE_ATTRIBUTION_CHAIN: {
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out, " event.writeAttributionChain(%s, %s_length, %s);\n",
+ uidName, uidName, tagName);
+ break;
+ }
+ case JAVA_TYPE_KEY_VALUE_PAIR:
+ fprintf(out, " event.writeKeyValuePairs("
+ "arg%d_1, arg%d_2, arg%d_3, arg%d_4);\n",
+ argIndex, argIndex, argIndex, argIndex);
+ break;
+ case JAVA_TYPE_BYTE_ARRAY:
+ fprintf(out, " event.writeByteArray(arg%d.arg, arg%d.arg_length);\n",
+ argIndex, argIndex);
+ break;
+ case JAVA_TYPE_BOOLEAN:
+ fprintf(out, " event.writeBool(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_INT: // Fall through.
+ case JAVA_TYPE_ENUM:
+ fprintf(out, " event.writeInt32(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_FLOAT:
+ fprintf(out, " event.writeFloat(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_LONG:
+ fprintf(out, " event.writeInt64(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_STRING:
+ fprintf(out, " event.writeString(arg%d);\n", argIndex);
+ break;
+ default:
+ // Unsupported types: OBJECT, DOUBLE.
+ fprintf(stderr, "Encountered unsupported type.");
+ return 1;
+ }
+ argIndex++;
+ }
+ fprintf(out, " return event.writeToSocket();\n");
+ } else {
+ fprintf(out, " struct stats_event* event = stats_event_obtain();\n");
+ fprintf(out, " stats_event_set_atom_id(event, code);\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ switch (*arg) {
+ case JAVA_TYPE_ATTRIBUTION_CHAIN: {
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out,
+ " stats_event_write_attribution_chain(event, "
+ "reinterpret_cast<const uint32_t*>(%s), %s.data(), "
+ "static_cast<uint8_t>(%s_length));\n",
+ uidName, tagName, uidName);
+ break;
+ }
+ case JAVA_TYPE_KEY_VALUE_PAIR:
+ fprintf(out, " std::vector<key_value_pair> pairs;\n");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 1, "INT32_TYPE", "int32Value");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 2, "INT64_TYPE", "int64Value");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 3, "STRING_TYPE", "stringValue");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 4, "FLOAT_TYPE", "floatValue");
+ fprintf(out,
+ " stats_event_write_key_value_pairs(event, pairs.data(), "
+ "static_cast<uint8_t>(pairs.size()));\n");
+ break;
+ case JAVA_TYPE_BYTE_ARRAY:
+ fprintf(out,
+ " stats_event_write_byte_array(event, "
+ "reinterpret_cast<const uint8_t*>(arg%d.arg), arg%d.arg_length);\n",
+ argIndex, argIndex);
+ break;
+ case JAVA_TYPE_BOOLEAN:
+ fprintf(out, " stats_event_write_bool(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_INT: // Fall through.
+ case JAVA_TYPE_ENUM:
+ fprintf(out, " stats_event_write_int32(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_FLOAT:
+ fprintf(out, " stats_event_write_float(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_LONG:
+ fprintf(out, " stats_event_write_int64(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_STRING:
+ fprintf(out, " stats_event_write_string8(event, arg%d);\n", argIndex);
+ break;
+ default:
+ // Unsupported types: OBJECT, DOUBLE.
+ fprintf(stderr, "Encountered unsupported type.");
+ return 1;
+ }
+ argIndex++;
+ }
+ fprintf(out, " const int ret = stats_event_write(event);\n");
+ fprintf(out, " stats_event_release(event);\n");
+ fprintf(out, " return ret;\n");
+ }
+ fprintf(out, "}\n\n");
+ }
+ return 0;
+}
+
+static void write_native_stats_write_non_chained_methods(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName) {
+ fprintf(out, "\n");
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
+
+ write_native_method_signature(out, "int stats_write_non_chained", signature,
+ attributionDecl, " {");
+
+ vector<java_type_t> newSignature;
+
+ // First two args form the attribution node so size goes down by 1.
+ newSignature.reserve(signature.size() - 1);
+
+ // First arg is Attribution Chain.
+ newSignature.push_back(JAVA_TYPE_ATTRIBUTION_CHAIN);
+
+ // Followed by the originial signature except the first 2 args.
+ newSignature.insert(newSignature.end(), signature.begin() + 2, signature.end());
+
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out, " const int32_t* %s = &arg1;\n", uidName);
+ fprintf(out, " const size_t %s_length = 1;\n", uidName);
+ fprintf(out, " const std::vector<char const*> %s(1, arg2);\n", tagName);
+ fprintf(out, " return ");
+ write_native_method_call(out, "stats_write", newSignature, attributionDecl, 2);
+
+ fprintf(out, "}\n\n");
+ }
+
+}
+#endif
+
+static void write_native_method_header(
+ FILE* out,
+ const string& methodName,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl, const string& moduleName) {
+
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ // Skip if this signature is not needed for the module.
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+
+ vector<java_type_t> signature = signature_to_modules_it->first;
+ write_native_method_signature(out, methodName, signature, attributionDecl, ";");
+ }
+}
+
+int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace,
+ const string& importHeader, const bool supportQ) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+
+ fprintf(out, "#include <%s>\n", importHeader.c_str());
+#if defined(STATS_SCHEMA_LEGACY)
+ (void)supportQ; // Workaround for unused parameter error.
+ write_native_cpp_includes_q(out);
+#else
+ if (supportQ) {
+ fprintf(out, "#include <StatsEventCompat.h>\n");
+ } else {
+ fprintf(out, "#include <stats_event.h>\n");
+ }
+#endif
+
+ fprintf(out, "\n");
+ write_namespace(out, cppNamespace);
+
+#if defined(STATS_SCHEMA_LEGACY)
+ write_native_stats_log_cpp_globals_q(out);
+ write_native_get_timestamp_ns_q(out);
+ write_native_try_stats_write_methods_q(out, atoms, attributionDecl, moduleName);
+ write_native_stats_write_methods_q(out, "int stats_write", atoms, attributionDecl, moduleName,
+ "try_stats_write");
+ write_native_try_stats_write_non_chained_methods_q(out, atoms, attributionDecl, moduleName);
+ write_native_stats_write_non_chained_methods_q(out, "int stats_write_non_chained", atoms,
+ attributionDecl, moduleName, "try_stats_write_non_chained");
+#else
+ write_native_stats_write_methods(out, atoms, attributionDecl, moduleName, supportQ);
+ write_native_stats_write_non_chained_methods(out, atoms, attributionDecl, moduleName);
+#endif
+
+ // Print footer
+ fprintf(out, "\n");
+ write_closing_namespace(out, cppNamespace);
+
+ return 0;
+}
+
+int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+ fprintf(out, "#pragma once\n");
+ fprintf(out, "\n");
+ fprintf(out, "#include <stdint.h>\n");
+ fprintf(out, "#include <vector>\n");
+ fprintf(out, "#include <map>\n");
+ fprintf(out, "#include <set>\n");
+ fprintf(out, "\n");
+
+ write_namespace(out, cppNamespace);
+ fprintf(out, "\n");
+ fprintf(out, "/*\n");
+ fprintf(out, " * API For logging statistics events.\n");
+ fprintf(out, " */\n");
+ fprintf(out, "\n");
+
+ write_native_atom_constants(out, atoms, attributionDecl, moduleName);
+
+ // Print constants for the enum values.
+ fprintf(out, "//\n");
+ fprintf(out, "// Constants for enum values\n");
+ fprintf(out, "//\n\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ // Skip if the atom is not needed for the module.
+ if (!atom_needed_for_module(*atom, moduleName)) {
+ continue;
+ }
+
+ for (vector<AtomField>::const_iterator field = atom->fields.begin();
+ field != atom->fields.end(); field++) {
+ if (field->javaType == JAVA_TYPE_ENUM) {
+ fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
+ field->name.c_str());
+ for (map<int, string>::const_iterator value = field->enumValues.begin();
+ value != field->enumValues.end(); value++) {
+ fprintf(out, "const int32_t %s__%s__%s = %d;\n",
+ make_constant_name(atom->message).c_str(),
+ make_constant_name(field->name).c_str(),
+ make_constant_name(value->second).c_str(),
+ value->first);
+ }
+ fprintf(out, "\n");
+ }
+ }
+ }
+
+ fprintf(out, "struct BytesField {\n");
+ fprintf(out,
+ " BytesField(char const* array, size_t len) : arg(array), "
+ "arg_length(len) {}\n");
+ fprintf(out, " char const* arg;\n");
+ fprintf(out, " size_t arg_length;\n");
+ fprintf(out, "};\n");
+ fprintf(out, "\n");
+
+ // Print write methods
+ fprintf(out, "//\n");
+ fprintf(out, "// Write methods\n");
+ fprintf(out, "//\n");
+ write_native_method_header(out, "int stats_write", atoms.signatures_to_modules, attributionDecl,
+ moduleName);
+
+ fprintf(out, "//\n");
+ fprintf(out, "// Write flattened methods\n");
+ fprintf(out, "//\n");
+ write_native_method_header(out, "int stats_write_non_chained",
+ atoms.non_chained_signatures_to_modules, attributionDecl, moduleName);
+
+ fprintf(out, "\n");
+ write_closing_namespace(out, cppNamespace);
+
+ return 0;
+}
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/native_writer.h b/tools/stats_log_api_gen/native_writer.h
new file mode 100644
index 0000000..aafa96e
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace, const string& importHeader,
+ const bool supportQ);
+
+int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace);
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/native_writer_q.cpp b/tools/stats_log_api_gen/native_writer_q.cpp
new file mode 100644
index 0000000..299873d
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer_q.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "native_writer_q.h"
+#include "utils.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+static void write_native_stats_write_body_q(FILE* out, const vector<java_type_t>& signature,
+ const AtomDecl& attributionDecl, const string& indent, const string& tryMethodName) {
+ fprintf(out, "%sint ret = 0;\n", indent.c_str());
+
+ fprintf(out, "%sfor(int retry = 0; retry < 2; ++retry) {\n", indent.c_str());
+ fprintf(out, "%s ret = ", indent.c_str());
+ write_native_method_call(out, tryMethodName, signature, attributionDecl);
+ fprintf(out, "%s if (ret >= 0) { break; }\n", indent.c_str());
+
+ fprintf(out, "%s {\n", indent.c_str());
+ fprintf(out, "%s std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n", indent.c_str());
+ fprintf(out, "%s if ((get_elapsed_realtime_ns() - lastRetryTimestampNs) <= "
+ "kMinRetryIntervalNs) break;\n", indent.c_str());
+ fprintf(out, "%s lastRetryTimestampNs = get_elapsed_realtime_ns();\n",
+ indent.c_str());
+ fprintf(out, "%s }\n", indent.c_str());
+ fprintf(out, "%s std::this_thread::sleep_for(std::chrono::milliseconds(10));\n",
+ indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "%sif (ret < 0) {\n", indent.c_str());
+ fprintf(out, "%s note_log_drop(ret, code);\n", indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "%sreturn ret;\n", indent.c_str());
+}
+
+void write_native_cpp_includes_q(FILE* out) {
+ fprintf(out, "#include <mutex>\n");
+ fprintf(out, "#include <chrono>\n");
+ fprintf(out, "#include <thread>\n");
+ fprintf(out, "#ifdef __ANDROID__\n");
+ fprintf(out, "#include <cutils/properties.h>\n");
+ fprintf(out, "#endif\n");
+ fprintf(out, "#include <stats_event_list.h>\n");
+ fprintf(out, "#include <log/log.h>\n");
+ fprintf(out, "#include <time.h>\n");
+}
+
+void write_native_get_timestamp_ns_q(FILE* out) {
+ fprintf(out, "\n");
+ fprintf(out, "static int64_t get_elapsed_realtime_ns() {\n");
+ fprintf(out, " struct timespec t;\n");
+ fprintf(out, " t.tv_sec = t.tv_nsec = 0;\n");
+ fprintf(out, " clock_gettime(CLOCK_BOOTTIME, &t);\n");
+ fprintf(out, " return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec;\n");
+ fprintf(out, "}\n");
+}
+
+void write_native_stats_log_cpp_globals_q(FILE* out) {
+ fprintf(out, "// the single event tag id for all stats logs\n");
+ fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
+ fprintf(out, "#ifdef __ANDROID__\n");
+ fprintf(out,
+ "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
+ fprintf(out, "#else\n");
+ fprintf(out, "const static bool kStatsdEnabled = false;\n");
+ fprintf(out, "#endif\n");
+
+ fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
+ fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
+ fprintf(out, "static std::mutex mLogdRetryMutex;\n");
+}
+
+void write_native_try_stats_write_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName) {
+ fprintf(out, "\n");
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
+
+ write_native_method_signature(out, "static int try_stats_write", signature,
+ attributionDecl, " {");
+
+ int argIndex = 1;
+ fprintf(out, " if (kStatsdEnabled) {\n");
+ fprintf(out, " stats_event_list event(kStatsEventTag);\n");
+ fprintf(out, " event << get_elapsed_realtime_ns();\n\n");
+ fprintf(out, " event << code;\n\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (const auto &chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, " if (%s_length != %s.size()) {\n",
+ attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
+ fprintf(out, " return -EINVAL;\n");
+ fprintf(out, " }\n");
+ }
+ }
+ fprintf(out, "\n event.begin();\n");
+ fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
+ attributionDecl.fields.front().name.c_str());
+ fprintf(out, " event.begin();\n");
+ for (const auto &chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
+ fprintf(out, " event << %s[i];\n", chainField.name.c_str());
+ fprintf(out, " } else {\n");
+ fprintf(out, " event << \"\";\n");
+ fprintf(out, " }\n");
+ } else {
+ fprintf(out, " event << %s[i];\n", chainField.name.c_str());
+ }
+ }
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+ fprintf(out, " event.end();\n\n");
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, " event.begin();\n\n");
+ fprintf(out, " for (const auto& it : arg%d_1) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " for (const auto& it : arg%d_2) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " for (const auto& it : arg%d_3) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " for (const auto& it : arg%d_4) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " event.end();\n\n");
+ } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out,
+ " event.AppendCharArray(arg%d.arg, "
+ "arg%d.arg_length);\n",
+ argIndex, argIndex);
+ } else {
+ if (*arg == JAVA_TYPE_STRING) {
+ fprintf(out, " if (arg%d == NULL) {\n", argIndex);
+ fprintf(out, " arg%d = \"\";\n", argIndex);
+ fprintf(out, " }\n");
+ }
+ fprintf(out, " event << arg%d;\n", argIndex);
+ }
+ argIndex++;
+ }
+
+ fprintf(out, " return event.write(LOG_ID_STATS);\n");
+ fprintf(out, " } else {\n");
+ fprintf(out, " return 1;\n");
+ fprintf(out, " }\n");
+ fprintf(out, "}\n");
+ fprintf(out, "\n");
+ }
+
+}
+
+void write_native_stats_write_methods_q(FILE* out, const string& methodName, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName, const string& tryMethodName) {
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end();
+ signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
+
+ write_native_method_signature(out, methodName, signature, attributionDecl, " {");
+
+ write_native_stats_write_body_q(out, signature, attributionDecl, " ", tryMethodName);
+ fprintf(out, "}\n\n");
+ }
+}
+
+void write_native_stats_write_non_chained_methods_q(FILE* out, const string& methodName,
+ const Atoms& atoms, const AtomDecl& attributionDecl, const string& moduleName,
+ const string& tryMethodName) {
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
+
+ write_native_method_signature(out, methodName, signature, attributionDecl, " {");
+
+ write_native_stats_write_body_q(out, signature, attributionDecl, " ", tryMethodName);
+ fprintf(out, "}\n\n");
+ }
+}
+
+void write_native_try_stats_write_non_chained_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName) {
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
+
+ write_native_method_signature(out, "static int try_stats_write_non_chained", signature,
+ attributionDecl, " {");
+
+ int argIndex = 1;
+ fprintf(out, " if (kStatsdEnabled) {\n");
+ fprintf(out, " stats_event_list event(kStatsEventTag);\n");
+ fprintf(out, " event << get_elapsed_realtime_ns();\n\n");
+ fprintf(out, " event << code;\n\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (argIndex == 1) {
+ fprintf(out, " event.begin();\n\n");
+ fprintf(out, " event.begin();\n");
+ }
+ if (*arg == JAVA_TYPE_STRING) {
+ fprintf(out, " if (arg%d == NULL) {\n", argIndex);
+ fprintf(out, " arg%d = \"\";\n", argIndex);
+ fprintf(out, " }\n");
+ }
+ if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out,
+ " event.AppendCharArray(arg%d.arg, "
+ "arg%d.arg_length);\n",
+ argIndex, argIndex);
+ } else {
+ fprintf(out, " event << arg%d;\n", argIndex);
+ }
+ if (argIndex == 2) {
+ fprintf(out, " event.end();\n\n");
+ fprintf(out, " event.end();\n\n");
+ }
+ argIndex++;
+ }
+
+ fprintf(out, " return event.write(LOG_ID_STATS);\n");
+ fprintf(out, " } else {\n");
+ fprintf(out, " return 1;\n");
+ fprintf(out, " }\n");
+ fprintf(out, "}\n");
+ fprintf(out, "\n");
+ }
+}
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/native_writer_q.h b/tools/stats_log_api_gen/native_writer_q.h
new file mode 100644
index 0000000..a2ab1ae
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer_q.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+void write_native_cpp_includes_q(FILE* out);
+
+void write_native_stats_log_cpp_globals_q(FILE* out);
+
+void write_native_try_stats_write_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName);
+
+void write_native_stats_write_methods_q(FILE* out, const string& methodName, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName, const string& tryMethodName);
+
+void write_native_try_stats_write_non_chained_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName);
+
+void write_native_stats_write_non_chained_methods_q(FILE* out, const string& methodName,
+ const Atoms& atoms, const AtomDecl& attributionDecl, const string& moduleName,
+ const string& tryMethodName);
+
+void write_native_get_timestamp_ns_q(FILE* out);
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/utils.cpp b/tools/stats_log_api_gen/utils.cpp
new file mode 100644
index 0000000..5b830ee
--- /dev/null
+++ b/tools/stats_log_api_gen/utils.cpp
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+
+#include "android-base/strings.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+static void build_non_chained_decl_map(const Atoms& atoms,
+ std::map<int, set<AtomDecl>::const_iterator>* decl_map) {
+ for (set<AtomDecl>::const_iterator atom = atoms.non_chained_decls.begin();
+ atom != atoms.non_chained_decls.end(); atom++) {
+ decl_map->insert(std::make_pair(atom->code, atom));
+ }
+}
+
+/**
+ * Turn lower and camel case into upper case with underscores.
+ */
+string make_constant_name(const string& str) {
+ string result;
+ const int N = str.size();
+ bool underscore_next = false;
+ for (int i=0; i<N; i++) {
+ char c = str[i];
+ if (c >= 'A' && c <= 'Z') {
+ if (underscore_next) {
+ result += '_';
+ underscore_next = false;
+ }
+ } else if (c >= 'a' && c <= 'z') {
+ c = 'A' + c - 'a';
+ underscore_next = true;
+ } else if (c == '_') {
+ underscore_next = false;
+ }
+ result += c;
+ }
+ return result;
+}
+
+const char* cpp_type_name(java_type_t type) {
+ switch (type) {
+ case JAVA_TYPE_BOOLEAN:
+ return "bool";
+ case JAVA_TYPE_INT:
+ case JAVA_TYPE_ENUM:
+ return "int32_t";
+ case JAVA_TYPE_LONG:
+ return "int64_t";
+ case JAVA_TYPE_FLOAT:
+ return "float";
+ case JAVA_TYPE_DOUBLE:
+ return "double";
+ case JAVA_TYPE_STRING:
+ return "char const*";
+ case JAVA_TYPE_BYTE_ARRAY:
+ return "const BytesField&";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+const char* java_type_name(java_type_t type) {
+ switch (type) {
+ case JAVA_TYPE_BOOLEAN:
+ return "boolean";
+ case JAVA_TYPE_INT:
+ case JAVA_TYPE_ENUM:
+ return "int";
+ case JAVA_TYPE_LONG:
+ return "long";
+ case JAVA_TYPE_FLOAT:
+ return "float";
+ case JAVA_TYPE_DOUBLE:
+ return "double";
+ case JAVA_TYPE_STRING:
+ return "java.lang.String";
+ case JAVA_TYPE_BYTE_ARRAY:
+ return "byte[]";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+bool atom_needed_for_module(const AtomDecl& atomDecl, const string& moduleName) {
+ if (moduleName == DEFAULT_MODULE_NAME) {
+ return true;
+ }
+ return atomDecl.hasModule && (moduleName == atomDecl.moduleName);
+}
+
+bool signature_needed_for_module(const set<string>& modules, const string& moduleName) {
+ if (moduleName == DEFAULT_MODULE_NAME) {
+ return true;
+ }
+ return modules.find(moduleName) != modules.end();
+}
+
+// Native
+// Writes namespaces for the cpp and header files, returning the number of namespaces written.
+void write_namespace(FILE* out, const string& cppNamespaces) {
+ vector<string> cppNamespaceVec = android::base::Split(cppNamespaces, ",");
+ for (string cppNamespace : cppNamespaceVec) {
+ fprintf(out, "namespace %s {\n", cppNamespace.c_str());
+ }
+}
+
+// Writes namespace closing brackets for cpp and header files.
+void write_closing_namespace(FILE* out, const string& cppNamespaces) {
+ vector<string> cppNamespaceVec = android::base::Split(cppNamespaces, ",");
+ for (auto it = cppNamespaceVec.rbegin(); it != cppNamespaceVec.rend(); ++it) {
+ fprintf(out, "} // namespace %s\n", it->c_str());
+ }
+}
+
+static void write_cpp_usage(
+ FILE* out, const string& method_name, const string& atom_code_name,
+ const AtomDecl& atom, const AtomDecl &attributionDecl) {
+ fprintf(out, " * Usage: %s(StatsLog.%s", method_name.c_str(),
+ atom_code_name.c_str());
+
+ for (vector<AtomField>::const_iterator field = atom.fields.begin();
+ field != atom.fields.end(); field++) {
+ if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, ", const std::vector<%s>& %s",
+ cpp_type_name(chainField.javaType),
+ chainField.name.c_str());
+ } else {
+ fprintf(out, ", const %s* %s, size_t %s_length",
+ cpp_type_name(chainField.javaType),
+ chainField.name.c_str(), chainField.name.c_str());
+ }
+ }
+ } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, ", const std::map<int, int32_t>& %s_int"
+ ", const std::map<int, int64_t>& %s_long"
+ ", const std::map<int, char const*>& %s_str"
+ ", const std::map<int, float>& %s_float",
+ field->name.c_str(),
+ field->name.c_str(),
+ field->name.c_str(),
+ field->name.c_str());
+ } else {
+ fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
+ }
+ }
+ fprintf(out, ");\n");
+}
+
+void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
+ const string& moduleName) {
+ fprintf(out, "/**\n");
+ fprintf(out, " * Constants for atom codes.\n");
+ fprintf(out, " */\n");
+ fprintf(out, "enum {\n");
+
+ std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
+ build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
+
+ size_t i = 0;
+ // Print atom constants
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ // Skip if the atom is not needed for the module.
+ if (!atom_needed_for_module(*atom, moduleName)) {
+ continue;
+ }
+ string constant = make_constant_name(atom->name);
+ fprintf(out, "\n");
+ fprintf(out, " /**\n");
+ fprintf(out, " * %s %s\n", atom->message.c_str(), atom->name.c_str());
+ write_cpp_usage(out, "stats_write", constant, *atom, attributionDecl);
+
+ auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
+ if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
+ write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second,
+ attributionDecl);
+ }
+ fprintf(out, " */\n");
+ char const* const comma = (i == atoms.decls.size() - 1) ? "" : ",";
+ fprintf(out, " %s = %d%s\n", constant.c_str(), atom->code, comma);
+ i++;
+ }
+ fprintf(out, "\n");
+ fprintf(out, "};\n");
+ fprintf(out, "\n");
+}
+
+void write_native_method_signature(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
+ const string& closer) {
+ fprintf(out, "%s(int32_t code", methodName.c_str());
+ int argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, ", const std::vector<%s>& %s",
+ cpp_type_name(chainField.javaType),
+ chainField.name.c_str());
+ } else {
+ fprintf(out, ", const %s* %s, size_t %s_length",
+ cpp_type_name(chainField.javaType),
+ chainField.name.c_str(), chainField.name.c_str());
+ }
+ }
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
+ "const std::map<int, int64_t>& arg%d_2, "
+ "const std::map<int, char const*>& arg%d_3, "
+ "const std::map<int, float>& arg%d_4",
+ argIndex, argIndex, argIndex, argIndex);
+ } else {
+ fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ")%s\n", closer.c_str());
+}
+
+void write_native_method_call(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl, int argIndex) {
+ fprintf(out, "%s(code", methodName.c_str());
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, ", %s",
+ chainField.name.c_str());
+ } else {
+ fprintf(out, ", %s, %s_length",
+ chainField.name.c_str(), chainField.name.c_str());
+ }
+ }
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex,
+ argIndex, argIndex, argIndex);
+ } else {
+ fprintf(out, ", arg%d", argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ");\n");
+}
+
+// Java
+void write_java_atom_codes(FILE* out, const Atoms& atoms, const string& moduleName) {
+ fprintf(out, " // Constants for atom codes.\n");
+
+ std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map;
+ build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
+
+ // Print constants for the atom codes.
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ // Skip if the atom is not needed for the module.
+ if (!atom_needed_for_module(*atom, moduleName)) {
+ continue;
+ }
+ string constant = make_constant_name(atom->name);
+ fprintf(out, "\n");
+ fprintf(out, " /**\n");
+ fprintf(out, " * %s %s<br>\n", atom->message.c_str(), atom->name.c_str());
+ write_java_usage(out, "write", constant, *atom);
+ auto non_chained_decl = atom_code_to_non_chained_decl_map.find(atom->code);
+ if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
+ write_java_usage(out, "write_non_chained", constant, *non_chained_decl->second);
+ }
+ if (moduleName == DEFAULT_MODULE_NAME) {
+ fprintf(out, " * @hide\n");
+ }
+ fprintf(out, " */\n");
+ fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code);
+ }
+ fprintf(out, "\n");
+}
+
+void write_java_enum_values(FILE* out, const Atoms& atoms, const string& moduleName) {
+ fprintf(out, " // Constants for enum values.\n\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ // Skip if the atom is not needed for the module.
+ if (!atom_needed_for_module(*atom, moduleName)) {
+ continue;
+ }
+ for (vector<AtomField>::const_iterator field = atom->fields.begin();
+ field != atom->fields.end(); field++) {
+ if (field->javaType == JAVA_TYPE_ENUM) {
+ fprintf(out, " // Values for %s.%s\n", atom->message.c_str(),
+ field->name.c_str());
+ for (map<int, string>::const_iterator value = field->enumValues.begin();
+ value != field->enumValues.end(); value++) {
+ if (moduleName == DEFAULT_MODULE_NAME) {
+ fprintf(out, " /** @hide */\n");
+ }
+ fprintf(out, " public static final int %s__%s__%s = %d;\n",
+ make_constant_name(atom->message).c_str(),
+ make_constant_name(field->name).c_str(),
+ make_constant_name(value->second).c_str(),
+ value->first);
+ }
+ fprintf(out, "\n");
+ }
+ }
+ }
+}
+
+void write_java_usage(FILE* out, const string& method_name, const string& atom_code_name,
+ const AtomDecl& atom) {
+ fprintf(out, " * Usage: StatsLog.%s(StatsLog.%s",
+ method_name.c_str(), atom_code_name.c_str());
+ for (vector<AtomField>::const_iterator field = atom.fields.begin();
+ field != atom.fields.end(); field++) {
+ if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ fprintf(out, ", android.os.WorkSource workSource");
+ } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, ", SparseArray<Object> value_map");
+ } else if (field->javaType == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out, ", byte[] %s", field->name.c_str());
+ } else {
+ fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
+ }
+ }
+ fprintf(out, ");<br>\n");
+}
+
+int write_java_non_chained_methods(
+ FILE* out,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const string& moduleName
+ ) {
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ // Skip if this signature is not needed for the module.
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+
+ // Print method signature.
+ if (DEFAULT_MODULE_NAME == moduleName) {
+ fprintf(out, " /** @hide */\n");
+ }
+ fprintf(out, " public static void write_non_chained(int code");
+ vector<java_type_t> signature = signature_to_modules_it->first;
+ int argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ // Non chained signatures should not have attribution chains.
+ return 1;
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ // Module logging does not yet support key value pair.
+ return 1;
+ } else {
+ fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ") {\n");
+
+ fprintf(out, " write(code");
+ argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ // First two args are uid and tag of attribution chain.
+ if (argIndex == 1) {
+ fprintf(out, ", new int[] {arg%d}", argIndex);
+ } else if (argIndex == 2) {
+ fprintf(out, ", new java.lang.String[] {arg%d}", argIndex);
+ } else {
+ fprintf(out, ", arg%d", argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ");\n");
+ fprintf(out, " }\n");
+ fprintf(out, "\n");
+ }
+ return 0;
+}
+
+int write_java_work_source_methods(
+ FILE* out,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const string& moduleName
+ ) {
+ fprintf(out, " // WorkSource methods.\n");
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ // Skip if this signature is not needed for the module.
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
+ // Determine if there is Attribution in this signature.
+ int attributionArg = -1;
+ int argIndexMax = 0;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ argIndexMax++;
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ if (attributionArg > -1) {
+ fprintf(stderr, "An atom contains multiple AttributionNode fields.\n");
+ fprintf(stderr, "This is not supported. Aborting WorkSource method writing.\n");
+ fprintf(out, "\n// Invalid for WorkSource: more than one attribution chain.\n");
+ return 1;
+ }
+ attributionArg = argIndexMax;
+ }
+ }
+ if (attributionArg < 0) {
+ continue;
+ }
+
+ fprintf(out, "\n");
+ // Method header (signature)
+ if (DEFAULT_MODULE_NAME == moduleName) {
+ fprintf(out, " /** @hide */\n");
+ }
+ fprintf(out, " public static void write(int code");
+ int argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ fprintf(out, ", WorkSource ws");
+ } else {
+ fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ") {\n");
+
+ // write_non_chained() component. TODO: Remove when flat uids are no longer needed.
+ fprintf(out, " for (int i = 0; i < ws.size(); ++i) {\n");
+ fprintf(out, " write_non_chained(code");
+ for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
+ if (argIndex == attributionArg) {
+ fprintf(out, ", ws.get(i), ws.getName(i)");
+ } else {
+ fprintf(out, ", arg%d", argIndex);
+ }
+ }
+ fprintf(out, ");\n");
+ fprintf(out, " }\n"); // close for-loop
+
+ // write() component.
+ fprintf(out, " ArrayList<WorkSource.WorkChain> workChains = ws.getWorkChains();\n");
+ fprintf(out, " if (workChains != null) {\n");
+ fprintf(out, " for (WorkSource.WorkChain wc : workChains) {\n");
+ fprintf(out, " write(code");
+ for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
+ if (argIndex == attributionArg) {
+ fprintf(out, ", wc.getUids(), wc.getTags()");
+ } else {
+ fprintf(out, ", arg%d", argIndex);
+ }
+ }
+ fprintf(out, ");\n");
+ fprintf(out, " }\n"); // close for-loop
+ fprintf(out, " }\n"); // close if
+ fprintf(out, " }\n"); // close method
+ }
+ return 0;
+}
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
new file mode 100644
index 0000000..50737a6
--- /dev/null
+++ b/tools/stats_log_api_gen/utils.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+const string DEFAULT_MODULE_NAME = "DEFAULT";
+const string DEFAULT_CPP_NAMESPACE = "android,util";
+const string DEFAULT_CPP_HEADER_IMPORT = "statslog.h";
+const string DEFAULT_ATOMS_INFO_CPP_HEADER_IMPORT = "atoms_info.h";
+const string DEFAULT_JAVA_PACKAGE = "android.util";
+const string DEFAULT_JAVA_CLASS = "StatsLogInternal";
+
+const int JAVA_MODULE_REQUIRES_FLOAT = 0x01;
+const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
+
+string make_constant_name(const string& str);
+
+const char* cpp_type_name(java_type_t type);
+
+const char* java_type_name(java_type_t type);
+
+bool atom_needed_for_module(const AtomDecl& atomDecl, const string& moduleName);
+
+bool signature_needed_for_module(const set<string>& modules, const string& moduleName);
+
+// Common Native helpers
+void write_namespace(FILE* out, const string& cppNamespaces);
+
+void write_closing_namespace(FILE* out, const string& cppNamespaces);
+
+void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
+ const string& moduleName);
+
+void write_native_method_signature(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
+ const string& closer);
+
+void write_native_method_call(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl, int argIndex = 1);
+
+// Common Java helpers.
+void write_java_atom_codes(FILE* out, const Atoms& atoms, const string& moduleName);
+
+void write_java_enum_values(FILE* out, const Atoms& atoms, const string& moduleName);
+
+void write_java_usage(FILE* out, const string& method_name, const string& atom_code_name,
+ const AtomDecl& atom);
+
+int write_java_non_chained_methods(FILE* out, const map<vector<java_type_t>,
+ set<string>>& signatures_to_modules,
+ const string& moduleName);
+
+int write_java_work_source_methods(
+ FILE* out,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const string& moduleName);
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index c0c0361..2901bd8 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -17,7 +17,7 @@
package android.net.wifi;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ed41642..933dded 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageManager;
import android.net.IpConfiguration;
import android.net.IpConfiguration.ProxySettings;
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 9d4b837..a9c2eb5 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -16,7 +16,7 @@
package android.net.wifi;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.security.Credentials;
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 0b55794..8bad71b 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -19,7 +19,7 @@
import android.annotation.IntRange;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkUtils;
import android.os.Build;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 671b3c7..f85bb5f 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -29,8 +29,8 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.net.ConnectivityManager;
diff --git a/wifi/java/android/net/wifi/WifiSsid.java b/wifi/java/android/net/wifi/WifiSsid.java
index f187e10..a591f31 100644
--- a/wifi/java/android/net/wifi/WifiSsid.java
+++ b/wifi/java/android/net/wifi/WifiSsid.java
@@ -16,7 +16,7 @@
package android.net.wifi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index c3cfb02..b0ea720 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.MacAddress;
import android.net.wifi.WpsInfo;
import android.os.Parcel;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index c5318a9..69aefcc 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -16,7 +16,7 @@
package android.net.wifi.p2p;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index acf06fb..ededf67 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -16,10 +16,9 @@
package android.net.wifi.p2p;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Parcelable;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
-import android.net.wifi.p2p.WifiP2pDevice;
+import android.os.Parcelable;
import android.text.TextUtils;
import java.util.ArrayList;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
index 4866bd4..b292da1 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -16,7 +16,7 @@
package android.net.wifi.p2p;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
index 62524d9..6068d3a 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
@@ -15,14 +15,14 @@
*/
package android.net.wifi.p2p;
-import java.util.Collection;
-import java.util.Map;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.LruCache;
+import java.util.Collection;
+import java.util.Map;
+
/**
* A class representing a Wi-Fi P2p group list
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index d37c4a2..eec4a00 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -23,7 +23,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.NetworkInfo;
import android.net.wifi.WpsInfo;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java b/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java
index 153e03c..d0fe92d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java
@@ -16,7 +16,7 @@
package android.net.wifi.p2p;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* A class representing a Wi-Fi p2p provisional discovery request/response
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
index 3caa280..7a5f909 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
@@ -16,10 +16,10 @@
package android.net.wifi.p2p;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
import java.util.Locale;
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
index e32c8e8..0de7ba6 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
@@ -16,7 +16,7 @@
package android.net.wifi.p2p.nsd;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.nsd.DnsSdTxtRecord;
import android.os.Build;
import android.text.TextUtils;
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
index db0bdb8..37b442b 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
@@ -16,7 +16,7 @@
package android.net.wifi.p2p.nsd;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
index 87528c4..68cbb88 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
@@ -16,7 +16,7 @@
package android.net.wifi.p2p.nsd;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Build;
import android.os.Parcel;