Merge "Camera: Fix OutputConfiguration equality check" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index f0e0c30..451175f 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -123,6 +123,11 @@
java_aconfig_library {
name: "android.nfc.flags-aconfig-java",
aconfig_declarations: "android.nfc.flags-aconfig",
+ min_sdk_version: "VanillaIceCream",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.nfcservices",
+ ],
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
@@ -147,6 +152,12 @@
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+rust_aconfig_library {
+ name: "libandroid_security_flags_rust",
+ crate_name: "android_security_flags",
+ aconfig_declarations: "android.security.flags-aconfig",
+}
+
// Package Manager
aconfig_declarations {
name: "android.content.pm.flags-aconfig",
diff --git a/Android.bp b/Android.bp
index ccff26f..0c08119 100644
--- a/Android.bp
+++ b/Android.bp
@@ -321,7 +321,6 @@
":installd_aidl",
":libaudioclient_aidl",
":libbinder_aidl",
- ":libbluetooth-binder-aidl",
":libcamera_client_aidl",
":libcamera_client_framework_aidl",
":libupdate_engine_aidl",
@@ -370,17 +369,12 @@
// TODO(b/120066492): remove default_television.xml when the build system
// propagates "required" properly.
"default_television.xml",
- "framework-platform-compat-config",
// TODO(b/120066492): remove gps_debug and protolog.conf.json when the build
// system propagates "required" properly.
"gps_debug.conf",
- "icu4j-platform-compat-config",
"protolog.conf.json.gz",
- "services-platform-compat-config",
- "TeleService-platform-compat-config",
- "documents-ui-compat-config",
- "calendar-provider-compat-config",
- "contacts-provider-platform-compat-config",
+ // any install dependencies should go into framework-minus-apex-install-dependencies
+ // rather than here to avoid bloating incremental build time
],
libs: [
"androidx.annotation_annotation",
@@ -415,21 +409,18 @@
],
}
-java_library {
- name: "framework-minus-apex",
+// Separated so framework-minus-apex-defaults can be used without the libs dependency
+java_defaults {
+ name: "framework-minus-apex-with-libs-defaults",
defaults: ["framework-minus-apex-defaults"],
- installable: true,
- // For backwards compatibility.
- stem: "framework",
- apex_available: ["//apex_available:platform"],
- visibility: [
- "//frameworks/base",
- // TODO(b/147128803) remove the below lines
- "//frameworks/base/apex/blobstore/framework",
- "//frameworks/base/apex/jobscheduler/framework",
- "//frameworks/base/packages/Tethering/tests/unit",
- "//packages/modules/Connectivity/Tethering/tests/unit",
+ libs: [
+ "framework-virtualization.stubs.module_lib",
+ "framework-location.impl",
],
+}
+
+java_defaults {
+ name: "framework-non-updatable-lint-defaults",
lint: {
extra_check_modules: ["AndroidFrameworkLintChecker"],
disabled_checks: ["ApiMightLeakAppVisibility"],
@@ -443,6 +434,43 @@
"UseOfCallerAwareMethodsWithClearedIdentity",
],
},
+}
+
+// we are unfortunately building the turbine jar twice, but more efficient and less complex
+// than generating a similar set of stubs with metalava
+java_library {
+ name: "framework-minus-apex-headers",
+ defaults: ["framework-minus-apex-defaults"],
+ installable: false,
+ // For backwards compatibility.
+ stem: "framework",
+ apex_available: ["//apex_available:platform"],
+ visibility: [
+ "//frameworks/base/location",
+ ],
+ compile_dex: false,
+ headers_only: true,
+}
+
+java_library {
+ name: "framework-minus-apex",
+ defaults: [
+ "framework-minus-apex-with-libs-defaults",
+ "framework-non-updatable-lint-defaults",
+ ],
+ installable: true,
+ // For backwards compatibility.
+ stem: "framework",
+ apex_available: ["//apex_available:platform"],
+ visibility: [
+ "//frameworks/base",
+ "//frameworks/base/location",
+ // TODO(b/147128803) remove the below lines
+ "//frameworks/base/apex/blobstore/framework",
+ "//frameworks/base/apex/jobscheduler/framework",
+ "//frameworks/base/packages/Tethering/tests/unit",
+ "//packages/modules/Connectivity/Tethering/tests/unit",
+ ],
errorprone: {
javacflags: [
"-Xep:AndroidFrameworkCompatChange:ERROR",
@@ -453,7 +481,7 @@
java_library {
name: "framework-minus-apex-intdefs",
- defaults: ["framework-minus-apex-defaults"],
+ defaults: ["framework-minus-apex-with-libs-defaults"],
plugins: ["intdef-annotation-processor"],
// Errorprone and android lint will already run on framework-minus-apex, don't rerun them on
@@ -481,6 +509,7 @@
installable: false, // this lib is a build-only library
static_libs: [
"app-compat-annotations",
+ "framework-location.impl",
"framework-minus-apex",
"framework-updatable-stubs-module_libs_api",
],
@@ -488,6 +517,20 @@
apex_available: ["//apex_available:platform"],
}
+java_library {
+ name: "framework-minus-apex-install-dependencies",
+ required: [
+ "framework-minus-apex",
+ "framework-platform-compat-config",
+ "services-platform-compat-config",
+ "icu4j-platform-compat-config",
+ "TeleService-platform-compat-config",
+ "documents-ui-compat-config",
+ "calendar-provider-compat-config",
+ "contacts-provider-platform-compat-config",
+ ],
+}
+
platform_compat_config {
name: "framework-platform-compat-config",
src: ":framework-minus-apex",
@@ -560,29 +603,6 @@
],
}
-// TODO(b/145644363): move this to under StubLibraries.bp or ApiDocs.bp
-metalava_framework_docs_args = "" +
- "--api-lint-ignore-prefix android.icu. " +
- "--api-lint-ignore-prefix java. " +
- "--api-lint-ignore-prefix junit. " +
- "--api-lint-ignore-prefix org. " +
- "--error NoSettingsProvider " +
- "--error UnhiddenSystemApi " +
- "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " +
- "--hide BroadcastBehavior " +
- "--hide CallbackInterface " +
- "--hide DeprecationMismatch " +
- "--hide HiddenSuperclass " +
- "--hide HiddenTypeParameter " +
- "--hide MissingPermission " +
- "--hide-package android.audio.policy.configuration.V7_0 " +
- "--hide-package com.android.server " +
- "--hide RequiresPermission " +
- "--hide SdkConstant " +
- "--hide Todo " +
- "--hide UnavailableSymbol " +
- "--manifest $(location :frameworks-base-core-AndroidManifest.xml) "
-
packages_to_document = [
"android",
"dalvik",
@@ -653,6 +673,29 @@
"android.hardware.vibrator-V1.3-java",
"framework-protos",
],
+ flags: [
+ "--api-lint-ignore-prefix android.icu.",
+ "--api-lint-ignore-prefix java.",
+ "--api-lint-ignore-prefix junit.",
+ "--api-lint-ignore-prefix org.",
+ "--error NoSettingsProvider",
+ "--error UnhiddenSystemApi",
+ "--error UnflaggedApi",
+ "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*",
+ "--hide BroadcastBehavior",
+ "--hide CallbackInterface",
+ "--hide DeprecationMismatch",
+ "--hide HiddenSuperclass",
+ "--hide HiddenTypeParameter",
+ "--hide MissingPermission",
+ "--hide RequiresPermission",
+ "--hide SdkConstant",
+ "--hide Todo",
+ "--hide UnavailableSymbol",
+ "--hide-package android.audio.policy.configuration.V7_0",
+ "--hide-package com.android.server",
+ "--manifest $(location :frameworks-base-core-AndroidManifest.xml)",
+ ],
filter_packages: packages_to_document,
high_mem: true, // Lots of sources => high memory use, see b/170701554
installable: false,
@@ -689,6 +732,97 @@
],
}
+// Defaults for the java_sdk_libraries of unbundled jars from framework.
+// java_sdk_libraries using these defaults should also add themselves to the
+// non_updatable_modules list in frameworks/base/api/api.go
+java_defaults {
+ name: "framework-non-updatable-unbundled-defaults",
+ defaults: ["framework-non-updatable-lint-defaults"],
+
+ sdk_version: "core_platform",
+
+ // Api scope settings
+ public: {
+ enabled: true,
+ sdk_version: "module_current",
+ libs: ["android_module_lib_stubs_current"],
+ },
+ system: {
+ enabled: true,
+ sdk_version: "module_current",
+ libs: ["android_module_lib_stubs_current"],
+ },
+ module_lib: {
+ enabled: true,
+ sdk_version: "module_current",
+ libs: ["android_module_lib_stubs_current"],
+ },
+ test: {
+ enabled: true,
+ sdk_version: "test_frameworks_core_current",
+ libs: ["android_test_frameworks_core_stubs_current"],
+ },
+
+ stub_only_libs: [
+ "framework-protos",
+ ],
+ impl_only_libs: [
+ "framework-minus-apex-headers", // full access to framework-minus-apex including hidden API
+ "framework-annotations-lib",
+ ],
+ visibility: ["//visibility:public"],
+ stubs_library_visibility: ["//visibility:public"],
+ stubs_source_visibility: ["//visibility:private"],
+ impl_library_visibility: [
+ ":__pkg__",
+ "//frameworks/base",
+ "//frameworks/base/api", // For framework-all
+ ],
+ defaults_visibility: [
+ "//frameworks/base/location",
+ ],
+ plugins: [
+ "error_prone_android_framework",
+ ],
+ errorprone: {
+ javacflags: [
+ "-Xep:AndroidFrameworkCompatChange:ERROR",
+ "-Xep:AndroidFrameworkUid:ERROR",
+ ],
+ },
+
+ // Include manual annotations in API txt files
+ merge_annotations_dirs: ["metalava-manual"],
+
+ // Use the source of annotations that affect metalava doc generation, since
+ // the relevant generation instructions are themselves in javadoc, which is
+ // not present in class files.
+ api_srcs: [":framework-metalava-annotations"],
+
+ // Framework modules are not generally shared libraries, i.e. they are not
+ // intended, and must not be allowed, to be used in a <uses-library> manifest
+ // entry.
+ shared_library: false,
+
+ // Prevent dependencies that do not specify an sdk_version from accessing the
+ // implementation library by default and force them to use stubs instead.
+ default_to_stubs: true,
+
+ // Subdirectory for the artifacts that are copied to the dist directory
+ dist_group: "android",
+
+ droiddoc_options: [
+ "--error UnhiddenSystemApi " +
+ "--hide CallbackInterface " +
+ "--hide HiddenTypedefConstant " +
+ "--hide RequiresPermission " +
+ "--enhance-documentation " +
+ "--hide-package com.android.server ",
+ ],
+
+ annotations_enabled: true,
+}
+
build = [
"AconfigFlags.bp",
"ProtoLibraries.bp",
diff --git a/ProtoLibraries.bp b/ProtoLibraries.bp
index 45bb161..e7adf20 100644
--- a/ProtoLibraries.bp
+++ b/ProtoLibraries.bp
@@ -77,6 +77,42 @@
output_extension: "proto.h",
}
+// ==== nfc framework java library ==============================
+gensrcs {
+ name: "framework-nfc-javastream-protos",
+
+ tools: [
+ "aprotoc",
+ "protoc-gen-javastream",
+ "soong_zip",
+ ],
+
+ cmd: "mkdir -p $(genDir)/$(in) " +
+ "&& $(location aprotoc) " +
+ " --plugin=$(location protoc-gen-javastream) " +
+ " --javastream_out=$(genDir)/$(in) " +
+ " -Iexternal/protobuf/src " +
+ " -I . " +
+ " $(in) " +
+ "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
+
+ srcs: [
+ "core/proto/android/app/pendingintent.proto",
+ "core/proto/android/content/component_name.proto",
+ "core/proto/android/content/intent.proto",
+ "core/proto/android/nfc/*.proto",
+ "core/proto/android/os/patternmatcher.proto",
+ "core/proto/android/os/persistablebundle.proto",
+ "core/proto/android/privacy.proto",
+ ],
+
+ data: [
+ ":libprotobuf-internal-protos",
+ ],
+
+ output_extension: "srcjar",
+}
+
// ==== java proto host library ==============================
java_library_host {
name: "platformprotos",
diff --git a/api/Android.bp b/api/Android.bp
index e9cc405..6986ac0 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -87,6 +87,7 @@
"framework-devicelock",
"framework-graphics",
"framework-healthfitness",
+ "framework-location",
"framework-media",
"framework-mediaprovider",
"framework-ondevicepersonalization",
diff --git a/api/ApiDocs.bp b/api/ApiDocs.bp
index e162100..5744bdf 100644
--- a/api/ApiDocs.bp
+++ b/api/ApiDocs.bp
@@ -72,7 +72,6 @@
"android-non-updatable-doc-stubs-defaults",
"module-classpath-stubs-defaults",
],
- args: metalava_framework_docs_args,
}
droidstubs {
@@ -81,8 +80,7 @@
"android-non-updatable-doc-stubs-defaults",
"module-classpath-stubs-defaults",
],
- args: metalava_framework_docs_args +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
+ flags: ["--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)"],
}
droidstubs {
@@ -91,9 +89,10 @@
"android-non-updatable-doc-stubs-defaults",
"module-classpath-stubs-defaults",
],
- args: metalava_framework_docs_args +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) " +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\) ",
+ flags: [
+ "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)",
+ "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\)",
+ ],
generate_stubs: false, // We're only using this module for the annotations.zip output, disable doc-stubs.
write_sdk_values: false,
}
@@ -104,10 +103,11 @@
"android-non-updatable-doc-stubs-defaults",
"module-classpath-stubs-defaults",
],
- args: metalava_framework_docs_args +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) " +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\) " +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\) ",
+ flags: [
+ "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)",
+ "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\)",
+ "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\)",
+ ],
generate_stubs: false, // We're only using this module for the annotations.zip output, disable doc-stubs.
write_sdk_values: false,
}
@@ -116,7 +116,6 @@
name: "framework-doc-stubs",
defaults: ["android-non-updatable-doc-stubs-defaults"],
srcs: [":all-modules-public-stubs-source"],
- args: metalava_framework_docs_args,
api_levels_module: "api_versions_public",
aidl: {
include_dirs: [
@@ -129,8 +128,7 @@
droidstubs {
name: "framework-doc-system-stubs",
defaults: ["framework-doc-stubs-sources-default"],
- args: metalava_framework_docs_args +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
+ flags: ["--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)"],
api_levels_module: "api_versions_system",
}
@@ -139,17 +137,6 @@
// using droiddoc
/////////////////////////////////////////////////////////////////////
-framework_docs_only_args = " -android -manifest $(location :frameworks-base-core-AndroidManifest.xml) " +
- "-metalavaApiSince " +
- "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
- "-overview $(location :frameworks-base-java-overview) " +
- // Federate Support Library references against local API file.
- "-federate SupportLib https://developer.android.com " +
- "-federationapi SupportLib $(location :current-support-api) " +
- // Federate Support Library references against local API file.
- "-federate AndroidX https://developer.android.com " +
- "-federationapi AndroidX $(location :current-androidx-api) "
-
doc_defaults {
name: "framework-docs-default",
sdk_version: "none",
@@ -169,6 +156,28 @@
resourcesdir: "docs/html/reference/images/",
resourcesoutdir: "reference/android/images/",
lint_baseline: "javadoc-lint-baseline",
+ flags: [
+ "-android",
+ "-manifest $(location :frameworks-base-core-AndroidManifest.xml)",
+ "-metalavaApiSince",
+ "-werror",
+ "-lerror",
+ "-overview $(location :frameworks-base-java-overview)",
+ // Federate Support Library references against local API file.
+ "-federate SupportLib https://developer.android.com",
+ "-federationapi SupportLib $(location :current-support-api)",
+ // Federate Support Library references against local API file.
+ "-federate AndroidX https://developer.android.com",
+ "-federationapi AndroidX $(location :current-androidx-api)",
+ // doclava contains checks for a few issues that are have been migrated to metalava.
+ // disable them in doclava, to avoid mistriggering or double triggering.
+ "-hide 111", // HIDDEN_SUPERCLASS
+ "-hide 113", // DEPRECATION_MISMATCH
+ "-hide 125", // REQUIRES_PERMISSION
+ "-hide 126", // BROADCAST_BEHAVIOR
+ "-hide 127", // SDK_CONSTANT
+ "-hide 128", // TODO
+ ],
hdf: [
"dac true",
"sdk.codename O",
@@ -204,7 +213,10 @@
],
compat_config: ":global-compat-config",
proofread_file: "offline-sdk-docs-proofread.txt",
- args: framework_docs_only_args + " -offlinemode -title \"Android SDK\"",
+ flags: [
+ "-offlinemode",
+ "-title \"Android SDK\"",
+ ],
static_doc_index_redirect: "docs/docs-preview-index.html",
}
@@ -221,7 +233,11 @@
"android.whichdoc offline",
],
proofread_file: "offline-sdk-referenceonly-docs-proofread.txt",
- args: framework_docs_only_args + " -offlinemode -title \"Android SDK\" -referenceonly",
+ flags: [
+ "-offlinemode",
+ "-title \"Android SDK\"",
+ "-referenceonly",
+ ],
static_doc_index_redirect: "docs/docs-documentation-redirect.html",
static_doc_properties: "docs/source.properties",
}
@@ -239,8 +255,14 @@
"android.whichdoc offline",
],
proofread_file: "offline-system-sdk-referenceonly-docs-proofread.txt",
- args: framework_docs_only_args + " -hide 101 -hide 104 -hide 108" +
- " -offlinemode -title \"Android System SDK\" -referenceonly",
+ flags: [
+ "-hide 101",
+ "-hide 104",
+ "-hide 108",
+ "-offlinemode",
+ "-title \"Android System SDK\"",
+ "-referenceonly",
+ ],
static_doc_index_redirect: "docs/docs-documentation-redirect.html",
static_doc_properties: "docs/source.properties",
}
@@ -256,22 +278,28 @@
"android.hasSamples true",
],
proofread_file: "ds-docs-proofread.txt",
- args: framework_docs_only_args +
- " -toroot / -yamlV2 -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -devsite -samplesdir development/samples/browseable ",
+ flags: [
+ " -toroot /",
+ "-yamlV2",
+ "-samplegroup Admin",
+ "-samplegroup Background",
+ "-samplegroup Connectivity",
+ "-samplegroup Content",
+ "-samplegroup Input",
+ "-samplegroup Media",
+ "-samplegroup Notification",
+ "-samplegroup RenderScript",
+ "-samplegroup Security",
+ "-samplegroup Sensors",
+ "-samplegroup System",
+ "-samplegroup Testing",
+ "-samplegroup UI",
+ "-samplegroup Views",
+ "-samplegroup Wearable",
+ "-devsite",
+ "-samplesdir",
+ "development/samples/browseable",
+ ],
}
droiddoc {
@@ -279,8 +307,11 @@
srcs: [
":framework-doc-stubs",
],
- args: "-noJdkLink -links https://kotlinlang.org/api/latest/jvm/stdlib/^external/dokka/package-list " +
+ flags: [
+ "-noJdkLink",
+ "-links https://kotlinlang.org/api/latest/jvm/stdlib/^external/dokka/package-list",
"-noStdlibLink",
+ ],
proofread_file: "ds-dokka-proofread.txt",
dokka_enabled: true,
}
@@ -333,11 +364,12 @@
hdf: [
"android.whichdoc online",
],
- args: framework_docs_only_args +
- " -staticonly " +
- " -toroot / " +
- " -devsite " +
- " -ignoreJdLinks ",
+ flags: [
+ "-staticonly",
+ "-toroot /",
+ "-devsite",
+ "-ignoreJdLinks",
+ ],
}
droiddoc {
@@ -349,8 +381,9 @@
hdf: [
"android.whichdoc online",
],
- args: framework_docs_only_args +
- " -toroot / " +
- " -atLinksNavtree " +
- " -navtreeonly ",
+ flags: [
+ "-toroot /",
+ "-atLinksNavtree",
+ "-navtreeonly",
+ ],
}
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp
index a410a58..d566552 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -36,7 +36,6 @@
"android-non-updatable-stubs-defaults",
"module-classpath-stubs-defaults",
],
- args: metalava_framework_docs_args,
check_api: {
current: {
api_file: ":non-updatable-current.txt",
@@ -50,6 +49,7 @@
api_lint: {
enabled: true,
new_since: ":android.api.public.latest",
+ baseline_file: ":non-updatable-lint-baseline.txt",
},
},
dists: [
@@ -69,19 +69,25 @@
api_surface: "public",
}
-priv_apps = " --show-annotation android.annotation.SystemApi\\(" +
- "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS" +
- "\\)"
+priv_apps = [
+ "--show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS" +
+ "\\)",
+]
-priv_apps_in_stubs = " --show-for-stub-purposes-annotation android.annotation.SystemApi\\(" +
- "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS" +
- "\\)"
+priv_apps_in_stubs = [
+ "--show-for-stub-purposes-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS" +
+ "\\)",
+]
-test = " --show-annotation android.annotation.TestApi"
+test = ["--show-annotation android.annotation.TestApi"]
-module_libs = " --show-annotation android.annotation.SystemApi\\(" +
- "client=android.annotation.SystemApi.Client.MODULE_LIBRARIES" +
- "\\)"
+module_libs = [
+ "--show-annotation android.annotation.SystemApi\\(" +
+ "client=android.annotation.SystemApi.Client.MODULE_LIBRARIES" +
+ "\\)",
+]
droidstubs {
name: "system-api-stubs-docs-non-updatable",
@@ -92,7 +98,7 @@
"android-non-updatable-stubs-defaults",
"module-classpath-stubs-defaults",
],
- args: metalava_framework_docs_args + priv_apps,
+ flags: priv_apps,
check_api: {
current: {
api_file: ":non-updatable-system-current.txt",
@@ -135,7 +141,7 @@
"android-non-updatable-stubs-defaults",
"module-classpath-stubs-defaults",
],
- args: metalava_framework_docs_args + test + priv_apps_in_stubs,
+ flags: test + priv_apps_in_stubs,
check_api: {
current: {
api_file: ":non-updatable-test-current.txt",
@@ -143,6 +149,7 @@
},
api_lint: {
enabled: true,
+ new_since: ":android.api.test.latest",
baseline_file: ":non-updatable-test-lint-baseline.txt",
},
},
@@ -184,7 +191,7 @@
"android-non-updatable-stubs-defaults",
"module-classpath-stubs-defaults",
],
- args: metalava_framework_docs_args + priv_apps_in_stubs + module_libs,
+ flags: priv_apps_in_stubs + module_libs,
check_api: {
current: {
api_file: ":non-updatable-module-lib-current.txt",
@@ -521,6 +528,21 @@
}
java_library {
+ name: "android_test_frameworks_core_stubs_current.from-source",
+ static_libs: [
+ "all-updatable-modules-system-stubs",
+ "android-non-updatable.stubs.test",
+ ],
+ defaults: [
+ "android.jar_defaults",
+ "android_stubs_dists_default",
+ ],
+ dist: {
+ dir: "apistubs/android/test-core",
+ },
+}
+
+java_library {
name: "android_module_lib_stubs_current.from-source",
defaults: [
"android.jar_defaults",
@@ -634,6 +656,7 @@
api_surface: "test",
api_contributions: [
"framework-virtualization.stubs.source.test.api.contribution",
+ "framework-location.stubs.source.test.api.contribution",
],
}
@@ -721,7 +744,9 @@
"android_stubs_current_contributions",
"android_system_stubs_current_contributions",
"android_test_frameworks_core_stubs_current_contributions",
- "stub-annotation-defaults",
+ ],
+ libs: [
+ "stub-annotations",
],
api_contributions: [
"api-stubs-docs-non-updatable.api.contribution",
@@ -952,7 +977,7 @@
merge_annotations_dirs: [
"metalava-manual",
],
- args: priv_apps,
+ flags: priv_apps,
}
java_library {
diff --git a/api/api.go b/api/api.go
index 692d38f..8df6dab 100644
--- a/api/api.go
+++ b/api/api.go
@@ -31,6 +31,7 @@
const conscrypt = "conscrypt.module.public.api"
const i18n = "i18n.module.public.api"
const virtualization = "framework-virtualization"
+const location = "framework-location"
var core_libraries_modules = []string{art, conscrypt, i18n}
@@ -42,7 +43,7 @@
// APIs.
// In addition, the modules in this list are allowed to contribute to test APIs
// stubs.
-var non_updatable_modules = []string{virtualization}
+var non_updatable_modules = []string{virtualization, location}
// The intention behind this soong plugin is to generate a number of "merged"
// API-related modules that would otherwise require a large amount of very
@@ -296,8 +297,10 @@
}
func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules []string) {
- // The user of this module compiles against the "core" SDK, so remove core libraries to avoid dupes.
+ // The user of this module compiles against the "core" SDK and against non-updatable modules,
+ // so remove to avoid dupes.
modules = removeAll(modules, core_libraries_modules)
+ modules = removeAll(modules, non_updatable_modules)
props := libraryProps{}
props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api")
props.Static_libs = transformArray(modules, "", ".stubs.module_lib")
@@ -393,6 +396,7 @@
"android_stubs_current",
"android_system_stubs_current",
"android_test_stubs_current",
+ "android_test_frameworks_core_stubs_current",
"android_module_lib_stubs_current",
"android_system_server_stubs_current",
}
diff --git a/cmds/svc/src/com/android/commands/svc/NfcCommand.java b/cmds/svc/src/com/android/commands/svc/NfcCommand.java
index 020ca33..ee2af12 100644
--- a/cmds/svc/src/com/android/commands/svc/NfcCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/NfcCommand.java
@@ -16,10 +16,11 @@
package com.android.commands.svc;
+import android.app.ActivityThread;
import android.content.Context;
-import android.nfc.INfcAdapter;
-import android.os.RemoteException;
-import android.os.ServiceManager;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcManager;
+import android.os.Looper;
public class NfcCommand extends Svc.Command {
@@ -42,27 +43,26 @@
@Override
public void run(String[] args) {
- INfcAdapter adapter = INfcAdapter.Stub.asInterface(
- ServiceManager.getService(Context.NFC_SERVICE));
-
+ Looper.prepareMainLooper();
+ ActivityThread.initializeMainlineModules();
+ Context context = ActivityThread.systemMain().getSystemContext();
+ NfcManager nfcManager = context.getSystemService(NfcManager.class);
+ if (nfcManager == null) {
+ System.err.println("Got a null NfcManager, is the system running?");
+ return;
+ }
+ NfcAdapter adapter = nfcManager.getDefaultAdapter();
if (adapter == null) {
System.err.println("Got a null NfcAdapter, is the system running?");
return;
}
-
- try {
- if (args.length == 2 && "enable".equals(args[1])) {
- adapter.enable();
- return;
- } else if (args.length == 2 && "disable".equals(args[1])) {
- adapter.disable(true);
- return;
- }
- } catch (RemoteException e) {
- System.err.println("NFC operation failed: " + e);
+ if (args.length == 2 && "enable".equals(args[1])) {
+ adapter.enable();
+ return;
+ } else if (args.length == 2 && "disable".equals(args[1])) {
+ adapter.disable(true);
return;
}
-
System.err.println(longHelp());
}
diff --git a/cmds/svc/src/com/android/commands/svc/OWNERS b/cmds/svc/src/com/android/commands/svc/OWNERS
new file mode 100644
index 0000000..d5a5d7b
--- /dev/null
+++ b/cmds/svc/src/com/android/commands/svc/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 48448
+per-file NfcCommand.java = file:platform/packages/apps/Nfc:/OWNERS
diff --git a/core/api/Android.bp b/core/api/Android.bp
index 71a2ca2..907916a 100644
--- a/core/api/Android.bp
+++ b/core/api/Android.bp
@@ -38,6 +38,11 @@
}
filegroup {
+ name: "non-updatable-lint-baseline.txt",
+ srcs: ["lint-baseline.txt"],
+}
+
+filegroup {
name: "non-updatable-system-current.txt",
srcs: ["system-current.txt"],
}
diff --git a/core/api/current.txt b/core/api/current.txt
index 7c1751f..fd4da0d 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -12737,7 +12737,7 @@
field public static final String FEATURE_TELEPHONY_RADIO_ACCESS = "android.hardware.telephony.radio.access";
field public static final String FEATURE_TELEPHONY_SUBSCRIPTION = "android.hardware.telephony.subscription";
field @Deprecated public static final String FEATURE_TELEVISION = "android.hardware.type.television";
- field public static final String FEATURE_THREAD_NETWORK = "android.hardware.thread_network";
+ field @FlaggedApi("com.android.net.thread.flags.thread_enabled") public static final String FEATURE_THREAD_NETWORK = "android.hardware.thread_network";
field public static final String FEATURE_TOUCHSCREEN = "android.hardware.touchscreen";
field public static final String FEATURE_TOUCHSCREEN_MULTITOUCH = "android.hardware.touchscreen.multitouch";
field public static final String FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT = "android.hardware.touchscreen.multitouch.distinct";
@@ -18375,12 +18375,12 @@
ctor @Deprecated public BiometricPrompt.CryptoObject(@NonNull android.security.identity.IdentityCredential);
ctor public BiometricPrompt.CryptoObject(@NonNull android.security.identity.PresentationSession);
ctor @FlaggedApi("android.hardware.biometrics.add_key_agreement_crypto_object") public BiometricPrompt.CryptoObject(@NonNull javax.crypto.KeyAgreement);
- method public javax.crypto.Cipher getCipher();
+ method @Nullable public javax.crypto.Cipher getCipher();
method @Deprecated @Nullable public android.security.identity.IdentityCredential getIdentityCredential();
method @FlaggedApi("android.hardware.biometrics.add_key_agreement_crypto_object") @Nullable public javax.crypto.KeyAgreement getKeyAgreement();
- method public javax.crypto.Mac getMac();
+ method @Nullable public javax.crypto.Mac getMac();
method @Nullable public android.security.identity.PresentationSession getPresentationSession();
- method public java.security.Signature getSignature();
+ method @Nullable public java.security.Signature getSignature();
}
}
@@ -33963,7 +33963,7 @@
field public static final String DISALLOW_MICROPHONE_TOGGLE = "disallow_microphone_toggle";
field public static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
- field public static final String DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO = "no_near_field_communication_radio";
+ field @FlaggedApi("android.nfc.enable_nfc_user_restriction") public static final String DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO = "no_near_field_communication_radio";
field public static final String DISALLOW_NETWORK_RESET = "no_network_reset";
field public static final String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
diff --git a/core/api/lint-baseline.txt b/core/api/lint-baseline.txt
new file mode 100644
index 0000000..f1c8279
--- /dev/null
+++ b/core/api/lint-baseline.txt
@@ -0,0 +1,7 @@
+// Baseline format: 1.0
+UnflaggedApi: android.content.pm.PackageManager#FEATURE_THREAD_NETWORK:
+ New API must be flagged with @FlaggedApi: field android.content.pm.PackageManager.FEATURE_THREAD_NETWORK
+UnflaggedApi: android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM:
+ New API must be flagged with @FlaggedApi: field android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM
+UnflaggedApi: android.os.UserManager#DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO:
+ New API must be flagged with @FlaggedApi: field android.os.UserManager.DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO
diff --git a/core/api/module-lib-lint-baseline.txt b/core/api/module-lib-lint-baseline.txt
index 27436ce..16b8c42 100644
--- a/core/api/module-lib-lint-baseline.txt
+++ b/core/api/module-lib-lint-baseline.txt
@@ -57,3 +57,11 @@
SAM-compatible parameters (such as parameter 1, "recipient", in android.os.IBinder.linkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.os.IBinder#unlinkToDeath(android.os.IBinder.DeathRecipient, int):
SAM-compatible parameters (such as parameter 1, "recipient", in android.os.IBinder.unlinkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+
+
+UnflaggedApi: android.app.Activity#isResumed():
+ New API must be flagged with @FlaggedApi: method android.app.Activity.isResumed()
+UnflaggedApi: android.content.Context#REMOTE_AUTH_SERVICE:
+ New API must be flagged with @FlaggedApi: field android.content.Context.REMOTE_AUTH_SERVICE
+UnflaggedApi: android.os.IpcDataCache#MODULE_TELEPHONY:
+ New API must be flagged with @FlaggedApi: field android.os.IpcDataCache.MODULE_TELEPHONY
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 64734f4..b6c9678 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3481,7 +3481,7 @@
field public static final String SYSTEM_CONFIG_SERVICE = "system_config";
field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
field public static final String TETHERING_SERVICE = "tethering";
- field public static final String THREAD_NETWORK_SERVICE = "thread_network";
+ field @FlaggedApi("com.android.net.thread.flags.thread_enabled") public static final String THREAD_NETWORK_SERVICE = "thread_network";
field public static final String TIME_MANAGER_SERVICE = "time_manager";
field public static final String TRANSLATION_MANAGER_SERVICE = "translation";
field public static final String UI_TRANSLATION_SERVICE = "ui_translation";
@@ -10251,6 +10251,7 @@
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean);
+ method @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setReaderMode(boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setTagIntentAppPreferenceForUser(int, @NonNull String, boolean);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 71c02dc..1e9e9be 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -226,6 +226,11 @@
SamShouldBeLast: android.webkit.WebChromeClient#onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams):
SAM-compatible parameters (such as parameter 2, "filePathCallback", in android.webkit.WebChromeClient.onShowFileChooser) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+
+UnflaggedApi: android.Manifest.permission#REGISTER_NSD_OFFLOAD_ENGINE:
+ New API must be flagged with @FlaggedApi: field android.Manifest.permission.REGISTER_NSD_OFFLOAD_ENGINE
+UnflaggedApi: android.content.Context#THREAD_NETWORK_SERVICE:
+ New API must be flagged with @FlaggedApi: field android.content.Context.THREAD_NETWORK_SERVICE
UnflaggedApi: android.nfc.cardemulation.AidGroup#CONTENTS_FILE_DESCRIPTOR:
New API must be flagged with @FlaggedApi: field android.nfc.cardemulation.AidGroup.CONTENTS_FILE_DESCRIPTOR
UnflaggedApi: android.nfc.cardemulation.AidGroup#PARCELABLE_WRITE_RETURN_VALUE:
@@ -238,3 +243,7 @@
New API must be flagged with @FlaggedApi: field android.nfc.cardemulation.NfcFServiceInfo.CONTENTS_FILE_DESCRIPTOR
UnflaggedApi: android.nfc.cardemulation.NfcFServiceInfo#PARCELABLE_WRITE_RETURN_VALUE:
New API must be flagged with @FlaggedApi: field android.nfc.cardemulation.NfcFServiceInfo.PARCELABLE_WRITE_RETURN_VALUE
+UnflaggedApi: android.telephony.mbms.vendor.MbmsDownloadServiceBase#DESCRIPTOR:
+ New API must be flagged with @FlaggedApi: field android.telephony.mbms.vendor.MbmsDownloadServiceBase.DESCRIPTOR
+UnflaggedApi: android.telephony.mbms.vendor.MbmsStreamingServiceBase#DESCRIPTOR:
+ New API must be flagged with @FlaggedApi: field android.telephony.mbms.vendor.MbmsStreamingServiceBase.DESCRIPTOR
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index 726871e..98f492f 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -145,6 +145,10 @@
Intent action constant name must be ACTION_FOO: SMS_CARRIER_PROVISION_ACTION
+KotlinKeyword: android.app.Notification#when:
+ Avoid field names that are Kotlin hard keywords ("when"); see https://android.github.io/kotlin-guides/interop.html#no-hard-keywords
+
+
KotlinOperator: android.os.PackageTagsList#contains(android.os.PackageTagsList):
Method can be invoked as a "in" operator from Kotlin: `contains` (this is usually desirable; just make sure it makes sense for this type of object)
KotlinOperator: android.util.SparseArrayMap#get(int, K):
@@ -965,16 +969,100 @@
Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause)
+SamShouldBeLast: android.animation.ValueAnimator#ofObject(android.animation.TypeEvaluator, java.lang.Object...):
+ SAM-compatible parameters (such as parameter 1, "evaluator", in android.animation.ValueAnimator.ofObject) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.Activity#convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions):
+ SAM-compatible parameters (such as parameter 1, "callback", in android.app.Activity.convertToTranslucent) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.app.ActivityManager.addOnUidImportanceListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.AlarmManager#set(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.app.AlarmManager.set) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.AlarmManager#set(int, long, long, long, android.app.AlarmManager.OnAlarmListener, android.os.Handler, android.os.WorkSource):
+ SAM-compatible parameters (such as parameter 5, "listener", in android.app.AlarmManager.set) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.AlarmManager#setExact(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.app.AlarmManager.setExact) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.AlarmManager#setWindow(int, long, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 5, "listener", in android.app.AlarmManager.setWindow) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.PendingIntent#send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler):
+ SAM-compatible parameters (such as parameter 4, "onFinished", in android.app.PendingIntent.send) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.PendingIntent#send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, String):
+ SAM-compatible parameters (such as parameter 4, "onFinished", in android.app.PendingIntent.send) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.PendingIntent#send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, String, android.os.Bundle):
+ SAM-compatible parameters (such as parameter 4, "onFinished", in android.app.PendingIntent.send) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.PendingIntent#send(int, android.app.PendingIntent.OnFinished, android.os.Handler):
+ SAM-compatible parameters (such as parameter 2, "onFinished", in android.app.PendingIntent.send) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.UiAutomation#executeAndWaitForEvent(Runnable, android.app.UiAutomation.AccessibilityEventFilter, long):
+ SAM-compatible parameters (such as parameter 2, "filter", in android.app.UiAutomation.executeAndWaitForEvent) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.app.WallpaperManager#addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.app.WallpaperManager.addOnColorsChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.content.pm.ActivityInfo#dump(android.util.Printer, String):
+ SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ActivityInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.content.pm.ApplicationInfo#dump(android.util.Printer, String):
+ SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ApplicationInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.content.pm.ComponentInfo#dumpBack(android.util.Printer, String):
+ SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ComponentInfo.dumpBack) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.content.pm.ComponentInfo#dumpFront(android.util.Printer, String):
+ SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ComponentInfo.dumpFront) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.content.pm.PackageItemInfo#dumpBack(android.util.Printer, String):
+ SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpBack) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.content.pm.PackageItemInfo#dumpFront(android.util.Printer, String):
+ SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpFront) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.database.sqlite.SQLiteCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]):
+ SAM-compatible parameters (such as parameter 1, "factory", in android.database.sqlite.SQLiteCursorDriver.query) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.database.sqlite.SQLiteDebug#dump(android.util.Printer, String[]):
SAM-compatible parameters (such as parameter 1, "printer", in android.database.sqlite.SQLiteDebug.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]):
SAM-compatible parameters (such as parameter 1, "factory", in android.database.sqlite.SQLiteDirectCursorDriver.query) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.graphics.drawable.AdaptiveIconDrawable#scheduleDrawable(android.graphics.drawable.Drawable, Runnable, long):
+ SAM-compatible parameters (such as parameter 2, "what", in android.graphics.drawable.AdaptiveIconDrawable.scheduleDrawable) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.graphics.drawable.Drawable#scheduleSelf(Runnable, long):
+ SAM-compatible parameters (such as parameter 1, "what", in android.graphics.drawable.Drawable.scheduleSelf) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.graphics.drawable.Drawable.Callback#scheduleDrawable(android.graphics.drawable.Drawable, Runnable, long):
+ SAM-compatible parameters (such as parameter 2, "what", in android.graphics.drawable.Drawable.Callback.scheduleDrawable) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.graphics.drawable.LayerDrawable#scheduleDrawable(android.graphics.drawable.Drawable, Runnable, long):
+ SAM-compatible parameters (such as parameter 2, "what", in android.graphics.drawable.LayerDrawable.scheduleDrawable) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioManager#abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes):
+ SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.abandonAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int):
+ SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.requestAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy):
+ SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.requestAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
+ SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.requestAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRecord.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRecord.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.MediaCas#setEventListener(android.media.MediaCas.EventListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaCas.setEventListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.os.Parcel#createFixedArray(Class<T>, java.util.function.Function<android.os.IBinder,S>, int...):
+ SAM-compatible parameters (such as parameter 2, "asInterface", in android.os.Parcel.createFixedArray) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.os.StrictMode.ViolationInfo#dump(android.util.Printer, String):
SAM-compatible parameters (such as parameter 1, "pw", in android.os.StrictMode.ViolationInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.permission.PermissionControllerManager#countPermissionApps(java.util.List<java.lang.String>, int, android.permission.PermissionControllerManager.OnCountPermissionAppsResultCallback, android.os.Handler):
SAM-compatible parameters (such as parameter 3, "callback", in android.permission.PermissionControllerManager.countPermissionApps) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler):
SAM-compatible parameters (such as parameter 2, "callback", in android.permission.PermissionControllerManager.getAppPermissions) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.security.KeyChain#choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, String[], java.security.Principal[], String, int, String):
+ SAM-compatible parameters (such as parameter 2, "response", in android.security.KeyChain.choosePrivateKeyAlias) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.security.KeyChain#choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, String[], java.security.Principal[], android.net.Uri, String):
+ SAM-compatible parameters (such as parameter 2, "response", in android.security.KeyChain.choosePrivateKeyAlias) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.service.autofill.CharSequenceTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
SAM-compatible parameters (such as parameter 1, "finder", in android.service.autofill.CharSequenceTransformation.apply) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.service.autofill.DateTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
@@ -987,8 +1075,24 @@
SAM-compatible parameters (such as parameter 2, "action", in android.view.Choreographer.postCallback) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long):
SAM-compatible parameters (such as parameter 2, "action", in android.view.Choreographer.postCallbackDelayed) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.view.Choreographer#postFrameCallbackDelayed(android.view.Choreographer.FrameCallback, long):
+ SAM-compatible parameters (such as parameter 1, "callback", in android.view.Choreographer.postFrameCallbackDelayed) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.view.Choreographer#removeCallbacks(int, Runnable, Object):
SAM-compatible parameters (such as parameter 2, "action", in android.view.Choreographer.removeCallbacks) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.view.View#postDelayed(Runnable, long):
+ SAM-compatible parameters (such as parameter 1, "action", in android.view.View.postDelayed) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.view.View#postOnAnimationDelayed(Runnable, long):
+ SAM-compatible parameters (such as parameter 1, "action", in android.view.View.postOnAnimationDelayed) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.view.View#scheduleDrawable(android.graphics.drawable.Drawable, Runnable, long):
+ SAM-compatible parameters (such as parameter 2, "what", in android.view.View.scheduleDrawable) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.view.Window#addOnFrameMetricsAvailableListener(android.view.Window.OnFrameMetricsAvailableListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.view.Window.addOnFrameMetricsAvailableListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.view.accessibility.AccessibilityManager#addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.view.accessibility.AccessibilityManager.addAccessibilityStateChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.view.accessibility.AccessibilityManager#addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.view.accessibility.AccessibilityManager.addTouchExplorationStateChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.view.inputmethod.InputMethodInfo#dump(android.util.Printer, String):
+ SAM-compatible parameters (such as parameter 1, "pw", in android.view.inputmethod.InputMethodInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
StaticUtils: android.os.health.HealthKeys:
@@ -1005,6 +1109,48 @@
Methods accepting `File` should also accept `FileDescriptor` or streams: method android.os.FileUtils.contains(java.io.File,java.io.File)
+UnflaggedApi: android.app.admin.DevicePolicyIdentifiers#PERMITTED_INPUT_METHODS_POLICY:
+ New API must be flagged with @FlaggedApi: field android.app.admin.DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY
+UnflaggedApi: android.app.admin.DevicePolicyIdentifiers#PERSONAL_APPS_SUSPENDED_POLICY:
+ New API must be flagged with @FlaggedApi: field android.app.admin.DevicePolicyIdentifiers.PERSONAL_APPS_SUSPENDED_POLICY
+UnflaggedApi: android.app.admin.DevicePolicyIdentifiers#SCREEN_CAPTURE_DISABLED_POLICY:
+ New API must be flagged with @FlaggedApi: field android.app.admin.DevicePolicyIdentifiers.SCREEN_CAPTURE_DISABLED_POLICY
+UnflaggedApi: android.media.soundtrigger.SoundTriggerInstrumentation#setInPhoneCallState(boolean):
+ New API must be flagged with @FlaggedApi: method android.media.soundtrigger.SoundTriggerInstrumentation.setInPhoneCallState(boolean)
+UnflaggedApi: android.media.soundtrigger.SoundTriggerManager#createManagerForModule(android.hardware.soundtrigger.SoundTrigger.ModuleProperties):
+ New API must be flagged with @FlaggedApi: method android.media.soundtrigger.SoundTriggerManager.createManagerForModule(android.hardware.soundtrigger.SoundTrigger.ModuleProperties)
+UnflaggedApi: android.media.soundtrigger.SoundTriggerManager#createManagerForTestModule():
+ New API must be flagged with @FlaggedApi: method android.media.soundtrigger.SoundTriggerManager.createManagerForTestModule()
+UnflaggedApi: android.media.soundtrigger.SoundTriggerManager#listModuleProperties():
+ New API must be flagged with @FlaggedApi: method android.media.soundtrigger.SoundTriggerManager.listModuleProperties()
+UnflaggedApi: android.media.soundtrigger.SoundTriggerManager#loadSoundModel(android.hardware.soundtrigger.SoundTrigger.SoundModel):
+ New API must be flagged with @FlaggedApi: method android.media.soundtrigger.SoundTriggerManager.loadSoundModel(android.hardware.soundtrigger.SoundTrigger.SoundModel)
+UnflaggedApi: android.media.soundtrigger.SoundTriggerManager.Model#getSoundModel():
+ New API must be flagged with @FlaggedApi: method android.media.soundtrigger.SoundTriggerManager.Model.getSoundModel()
+UnflaggedApi: android.os.BatteryManager#BATTERY_PLUGGED_ANY:
+ New API must be flagged with @FlaggedApi: field android.os.BatteryManager.BATTERY_PLUGGED_ANY
+UnflaggedApi: android.os.UserHandle#USER_CURRENT:
+ New API must be flagged with @FlaggedApi: field android.os.UserHandle.USER_CURRENT
+UnflaggedApi: android.os.UserManager#getAliveUsers():
+ New API must be flagged with @FlaggedApi: method android.os.UserManager.getAliveUsers()
+UnflaggedApi: android.os.UserManager#getUsers():
+ New API must be flagged with @FlaggedApi: method android.os.UserManager.getUsers()
+UnflaggedApi: android.telephony.ims.feature.MmTelFeature.MmTelCapabilities:
+ New API must be flagged with @FlaggedApi: class android.telephony.ims.feature.MmTelFeature.MmTelCapabilities
+UnflaggedApi: android.view.WindowManager.LayoutParams#preferredMaxDisplayRefreshRate:
+ New API must be flagged with @FlaggedApi: field android.view.WindowManager.LayoutParams.preferredMaxDisplayRefreshRate
+UnflaggedApi: android.view.WindowManager.LayoutParams#preferredMinDisplayRefreshRate:
+ New API must be flagged with @FlaggedApi: field android.view.WindowManager.LayoutParams.preferredMinDisplayRefreshRate
+UnflaggedApi: android.view.inputmethod.InputMethodManager#isCurrentRootView(android.view.View):
+ New API must be flagged with @FlaggedApi: method android.view.inputmethod.InputMethodManager.isCurrentRootView(android.view.View)
+UnflaggedApi: android.view.inputmethod.InsertModeGesture:
+ New API must be flagged with @FlaggedApi: class android.view.inputmethod.InsertModeGesture
+UnflaggedApi: android.window.WindowInfosListenerForTest.WindowInfo#displayId:
+ New API must be flagged with @FlaggedApi: field android.window.WindowInfosListenerForTest.WindowInfo.displayId
+UnflaggedApi: android.window.WindowInfosListenerForTest.WindowInfo#isVisible:
+ New API must be flagged with @FlaggedApi: field android.window.WindowInfosListenerForTest.WindowInfo.isVisible
+
+
UseIcu: android.hardware.soundtrigger.KeyphraseEnrollmentInfo#getKeyphraseMetadata(String, java.util.Locale) parameter #1:
Type `java.util.Locale` should be replaced with richer ICU type `android.icu.util.ULocale`
UseIcu: android.hardware.soundtrigger.KeyphraseEnrollmentInfo#getManageKeyphraseIntent(int, String, java.util.Locale) parameter #2:
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 70864d5..26b7581 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -14,6 +14,15 @@
hdrs: ["android/hardware/HardwareBuffer.aidl"],
}
+// TODO (b/303286040): Remove this once |ENABLE_NFC_MAINLINE_FLAG| is rolled out
+filegroup {
+ name: "framework-core-nfc-infcadapter-sources",
+ srcs: [
+ "android/nfc/INfcAdapter.aidl",
+ ],
+ visibility: ["//frameworks/base/services/core"],
+}
+
filegroup {
name: "framework-core-sources",
srcs: [
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index da5e40a..f3cc594 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -16111,11 +16111,6 @@
* Called by a profile owner of an organization-owned managed profile to suspend personal
* apps on the device. When personal apps are suspended the device can only be used for calls.
*
- * <p>When personal apps are suspended, an ongoing notification about that is shown to the user.
- * When the user taps the notification, system invokes {@link #ACTION_CHECK_POLICY_COMPLIANCE}
- * in the profile owner package. Profile owner implementation that uses personal apps suspension
- * must handle this intent.
- *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with
* @param suspended Whether personal apps should be suspended.
* @throws IllegalStateException if the profile owner doesn't have an activity that handles
diff --git a/core/java/android/app/contentsuggestions/OWNERS b/core/java/android/app/contentsuggestions/OWNERS
index cf54c2a..5f8de77 100644
--- a/core/java/android/app/contentsuggestions/OWNERS
+++ b/core/java/android/app/contentsuggestions/OWNERS
@@ -1,7 +1,4 @@
# Bug component: 643919
-augale@google.com
-joannechung@google.com
-markpun@google.com
-lpeter@google.com
-tymtsai@google.com
+hackz@google.com
+volnov@google.com
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 10857e5..3d43845 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -23,6 +23,7 @@
import android.annotation.ColorRes;
import android.annotation.DisplayContext;
import android.annotation.DrawableRes;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.LongDef;
import android.annotation.NonNull;
@@ -4766,6 +4767,7 @@
* @see android.net.thread.ThreadNetworkManager
* @hide
*/
+ @FlaggedApi("com.android.net.thread.flags.thread_enabled")
@SystemApi
public static final String THREAD_NETWORK_SERVICE = "thread_network";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 02650c6..f07a23f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -20,6 +20,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.CheckResult;
import android.annotation.DrawableRes;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.LongDef;
@@ -1449,6 +1450,7 @@
INSTALL_ALLOW_DOWNGRADE,
INSTALL_STAGED,
INSTALL_REQUEST_UPDATE_OWNERSHIP,
+ INSTALL_IGNORE_DEXOPT_PROFILE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InstallFlags {}
@@ -1674,6 +1676,18 @@
public static final int INSTALL_FROM_MANAGED_USER_OR_PROFILE = 1 << 26;
/**
+ * If set, all dexopt profiles are ignored by dexopt during the installation, including the
+ * profile in the DM file and the profile embedded in the APK file. If an invalid profile is
+ * provided during installation, no warning will be reported by {@code adb install}.
+ *
+ * This option does not affect later dexopt operations (e.g., background dexopt and manual `pm
+ * compile` invocations).
+ *
+ * @hide
+ */
+ public static final int INSTALL_IGNORE_DEXOPT_PROFILE = 1 << 28;
+
+ /**
* Flag parameter for {@link #installPackage} to force a non-staged update of an APEX. This is
* a development-only feature and should not be used on end user devices.
*
@@ -3638,6 +3652,7 @@
* The device is capable of communicating with other devices via
* <a href="https://www.threadgroup.org">Thread</a> networking protocol.
*/
+ @FlaggedApi("com.android.net.thread.flags.thread_enabled")
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_THREAD_NETWORK = "android.hardware.thread_network";
diff --git a/core/java/android/hardware/HardwareBuffer.aidl b/core/java/android/hardware/HardwareBuffer.aidl
index 1333f0d..a9742cb 100644
--- a/core/java/android/hardware/HardwareBuffer.aidl
+++ b/core/java/android/hardware/HardwareBuffer.aidl
@@ -16,4 +16,4 @@
package android.hardware;
-@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable HardwareBuffer ndk_header "android/hardware_buffer_aidl.h";
+@JavaOnlyStableParcelable @NdkOnlyStableParcelable @RustOnlyStableParcelable parcelable HardwareBuffer ndk_header "android/hardware_buffer_aidl.h" rust_type "nativewindow::HardwareBuffer";
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 294813d..35ae11c 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -786,7 +786,7 @@
* Get {@link Signature} object.
* @return {@link Signature} object or null if this doesn't contain one.
*/
- public Signature getSignature() {
+ public @Nullable Signature getSignature() {
return super.getSignature();
}
@@ -794,7 +794,7 @@
* Get {@link Cipher} object.
* @return {@link Cipher} object or null if this doesn't contain one.
*/
- public Cipher getCipher() {
+ public @Nullable Cipher getCipher() {
return super.getCipher();
}
@@ -802,7 +802,7 @@
* Get {@link Mac} object.
* @return {@link Mac} object or null if this doesn't contain one.
*/
- public Mac getMac() {
+ public @Nullable Mac getMac() {
return super.getMac();
}
diff --git a/core/java/android/hardware/biometrics/CryptoObject.java b/core/java/android/hardware/biometrics/CryptoObject.java
index 6ac1efb..39fbe83 100644
--- a/core/java/android/hardware/biometrics/CryptoObject.java
+++ b/core/java/android/hardware/biometrics/CryptoObject.java
@@ -20,6 +20,7 @@
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.security.identity.IdentityCredential;
import android.security.identity.PresentationSession;
import android.security.keystore2.AndroidKeyStoreProvider;
@@ -33,20 +34,35 @@
/**
* A wrapper class for the crypto objects supported by BiometricPrompt and FingerprintManager.
* Currently the framework supports {@link Signature}, {@link Cipher}, {@link Mac},
- * {@link IdentityCredential}, and {@link PresentationSession} objects.
+ * {@link KeyAgreement}, {@link IdentityCredential}, and {@link PresentationSession} objects.
* @hide
*/
public class CryptoObject {
private final Object mCrypto;
+ /**
+ * Create from a {@link Signature} object.
+ *
+ * @param signature a {@link Signature} object.
+ */
public CryptoObject(@NonNull Signature signature) {
mCrypto = signature;
}
+ /**
+ * Create from a {@link Cipher} object.
+ *
+ * @param cipher a {@link Cipher} object.
+ */
public CryptoObject(@NonNull Cipher cipher) {
mCrypto = cipher;
}
+ /**
+ * Create from a {@link Mac} object.
+ *
+ * @param mac a {@link Mac} object.
+ */
public CryptoObject(@NonNull Mac mac) {
mCrypto = mac;
}
@@ -62,10 +78,20 @@
mCrypto = credential;
}
+ /**
+ * Create from a {@link PresentationSession} object.
+ *
+ * @param session a {@link PresentationSession} object.
+ */
public CryptoObject(@NonNull PresentationSession session) {
mCrypto = session;
}
+ /**
+ * Create from a {@link KeyAgreement} object.
+ *
+ * @param keyAgreement a {@link KeyAgreement} object.
+ */
@FlaggedApi(FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT)
public CryptoObject(@NonNull KeyAgreement keyAgreement) {
mCrypto = keyAgreement;
@@ -75,7 +101,7 @@
* Get {@link Signature} object.
* @return {@link Signature} object or null if this doesn't contain one.
*/
- public Signature getSignature() {
+ public @Nullable Signature getSignature() {
return mCrypto instanceof Signature ? (Signature) mCrypto : null;
}
@@ -83,7 +109,7 @@
* Get {@link Cipher} object.
* @return {@link Cipher} object or null if this doesn't contain one.
*/
- public Cipher getCipher() {
+ public @Nullable Cipher getCipher() {
return mCrypto instanceof Cipher ? (Cipher) mCrypto : null;
}
@@ -91,7 +117,7 @@
* Get {@link Mac} object.
* @return {@link Mac} object or null if this doesn't contain one.
*/
- public Mac getMac() {
+ public @Nullable Mac getMac() {
return mCrypto instanceof Mac ? (Mac) mCrypto : null;
}
@@ -101,7 +127,7 @@
* @deprecated Use {@link PresentationSession} instead of {@link IdentityCredential}.
*/
@Deprecated
- public IdentityCredential getIdentityCredential() {
+ public @Nullable IdentityCredential getIdentityCredential() {
return mCrypto instanceof IdentityCredential ? (IdentityCredential) mCrypto : null;
}
@@ -109,16 +135,18 @@
* Get {@link PresentationSession} object.
* @return {@link PresentationSession} object or null if this doesn't contain one.
*/
- public PresentationSession getPresentationSession() {
+ public @Nullable PresentationSession getPresentationSession() {
return mCrypto instanceof PresentationSession ? (PresentationSession) mCrypto : null;
}
/**
- * Get {@link KeyAgreement} object.
+ * Get {@link KeyAgreement} object. A key-agreement protocol is a protocol whereby
+ * two or more parties can agree on a shared secret using public key cryptography.
+ *
* @return {@link KeyAgreement} object or null if this doesn't contain one.
*/
@FlaggedApi(FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT)
- public KeyAgreement getKeyAgreement() {
+ public @Nullable KeyAgreement getKeyAgreement() {
return mCrypto instanceof KeyAgreement ? (KeyAgreement) mCrypto : null;
}
diff --git a/core/java/android/hardware/hdmi/OWNERS b/core/java/android/hardware/hdmi/OWNERS
index 861e440..6952e5d 100644
--- a/core/java/android/hardware/hdmi/OWNERS
+++ b/core/java/android/hardware/hdmi/OWNERS
@@ -2,5 +2,4 @@
include /services/core/java/com/android/server/display/OWNERS
-marvinramin@google.com
-lcnathalie@google.com
+quxiangfang@google.com
diff --git a/core/java/android/nfc/Constants.java b/core/java/android/nfc/Constants.java
new file mode 100644
index 0000000..f768330
--- /dev/null
+++ b/core/java/android/nfc/Constants.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.nfc;
+
+/**
+ * @hide
+ * TODO(b/303286040): Holds @hide API constants. Formalize these APIs.
+ */
+public final class Constants {
+ private Constants() { }
+
+ public static final String SETTINGS_SECURE_NFC_PAYMENT_FOREGROUND = "nfc_payment_foreground";
+ public static final String SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
+ public static final String FEATURE_NFC_ANY = "android.hardware.nfc.any";
+}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 4658630..4a7bd3f 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -24,6 +24,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.app.Activity;
@@ -37,6 +38,7 @@
import android.nfc.tech.Ndef;
import android.nfc.tech.NfcA;
import android.nfc.tech.NfcF;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -1594,6 +1596,40 @@
mNfcActivityManager.disableReaderMode(activity);
}
+ // Flags arguments to NFC adapter to enable/disable NFC
+ private static final int DISABLE_POLLING_FLAGS = 0x1000;
+ private static final int ENABLE_POLLING_FLAGS = 0x0000;
+
+ /**
+ * Privileged API to enable disable reader polling.
+ * Note: Use with caution! The app is responsible for ensuring that the polling state is
+ * returned to normal.
+ *
+ * @see #enableReaderMode(Activity, ReaderCallback, int, Bundle) for more detailed
+ * documentation.
+ *
+ * @param enablePolling whether to enable or disable polling.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+ @SuppressLint("VisiblySynchronized")
+ public void setReaderMode(boolean enablePolling) {
+ synchronized (NfcAdapter.class) {
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ Binder token = new Binder();
+ int flags = enablePolling ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS;
+ try {
+ NfcAdapter.sService.setReaderMode(token, null, flags, null);
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ }
+ }
+
/**
* Manually invoke Android Beam to share data.
*
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
index 958669e..ae3e333 100644
--- a/core/java/android/nfc/cardemulation/AidGroup.java
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -34,6 +34,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import java.util.regex.Pattern;
/**********************************************************************
* This file is not a part of the NFC mainline module *
@@ -79,7 +80,7 @@
throw new IllegalArgumentException("Too many AIDs in AID group.");
}
for (String aid : aids) {
- if (!CardEmulation.isValidAid(aid)) {
+ if (!isValidAid(aid)) {
throw new IllegalArgumentException("AID " + aid + " is not a valid AID.");
}
}
@@ -264,4 +265,34 @@
return CardEmulation.CATEGORY_PAYMENT.equals(category) ||
CardEmulation.CATEGORY_OTHER.equals(category);
}
+
+ private static final Pattern AID_PATTERN = Pattern.compile("[0-9A-Fa-f]{10,32}\\*?\\#?");
+ /**
+ * Copied over from {@link CardEmulation#isValidAid(String)}
+ * @hide
+ */
+ private static boolean isValidAid(String aid) {
+ if (aid == null)
+ return false;
+
+ // If a prefix/subset AID, the total length must be odd (even # of AID chars + '*')
+ if ((aid.endsWith("*") || aid.endsWith("#")) && ((aid.length() % 2) == 0)) {
+ Log.e(TAG, "AID " + aid + " is not a valid AID.");
+ return false;
+ }
+
+ // If not a prefix/subset AID, the total length must be even (even # of AID chars)
+ if ((!(aid.endsWith("*") || aid.endsWith("#"))) && ((aid.length() % 2) != 0)) {
+ Log.e(TAG, "AID " + aid + " is not a valid AID.");
+ return false;
+ }
+
+ // Verify hex characters
+ if (!AID_PATTERN.matcher(aid).matches()) {
+ Log.e(TAG, "AID " + aid + " is not a valid AID.");
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 18ec914..665b753 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -52,6 +52,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.regex.Pattern;
/**
* Class holding APDU service info.
@@ -307,7 +308,7 @@
com.android.internal.R.styleable.AidFilter);
String aid = a.getString(com.android.internal.R.styleable.AidFilter_name).
toUpperCase();
- if (CardEmulation.isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
+ if (isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
currentGroup.getAids().add(aid);
} else {
Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
@@ -321,7 +322,7 @@
toUpperCase();
// Add wildcard char to indicate prefix
aid = aid.concat("*");
- if (CardEmulation.isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
+ if (isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
currentGroup.getAids().add(aid);
} else {
Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
@@ -335,7 +336,7 @@
toUpperCase();
// Add wildcard char to indicate suffix
aid = aid.concat("#");
- if (CardEmulation.isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
+ if (isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
currentGroup.getAids().add(aid);
} else {
Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
@@ -806,7 +807,7 @@
*/
@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
public void dumpDebug(@NonNull ProtoOutputStream proto) {
- Utils.dumpDebugComponentName(getComponent(), proto, ApduServiceInfoProto.COMPONENT_NAME);
+ getComponent().dumpDebug(proto, ApduServiceInfoProto.COMPONENT_NAME);
proto.write(ApduServiceInfoProto.DESCRIPTION, getDescription());
proto.write(ApduServiceInfoProto.ON_HOST, mOnHost);
if (!mOnHost) {
@@ -825,4 +826,34 @@
}
proto.write(ApduServiceInfoProto.SETTINGS_ACTIVITY_NAME, mSettingsActivityName);
}
+
+ private static final Pattern AID_PATTERN = Pattern.compile("[0-9A-Fa-f]{10,32}\\*?\\#?");
+ /**
+ * Copied over from {@link CardEmulation#isValidAid(String)}
+ * @hide
+ */
+ private static boolean isValidAid(String aid) {
+ if (aid == null)
+ return false;
+
+ // If a prefix/subset AID, the total length must be odd (even # of AID chars + '*')
+ if ((aid.endsWith("*") || aid.endsWith("#")) && ((aid.length() % 2) == 0)) {
+ Log.e(TAG, "AID " + aid + " is not a valid AID.");
+ return false;
+ }
+
+ // If not a prefix/subset AID, the total length must be even (even # of AID chars)
+ if ((!(aid.endsWith("*") || aid.endsWith("#"))) && ((aid.length() % 2) != 0)) {
+ Log.e(TAG, "AID " + aid + " is not a valid AID.");
+ return false;
+ }
+
+ // Verify hex characters
+ if (!AID_PATTERN.matcher(aid).matches()) {
+ Log.e(TAG, "AID " + aid + " is not a valid AID.");
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 4909b08..32c2a1b 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.nfc.Constants;
import android.nfc.INfcCardEmulation;
import android.nfc.NfcAdapter;
import android.os.RemoteException;
@@ -274,7 +275,7 @@
try {
preferForeground = Settings.Secure.getInt(
contextAsUser.getContentResolver(),
- Settings.Secure.NFC_PAYMENT_FOREGROUND) != 0;
+ Constants.SETTINGS_SECURE_NFC_PAYMENT_FOREGROUND) != 0;
} catch (SettingNotFoundException e) {
}
return preferForeground;
diff --git a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
index ec919e4..33bc169 100644
--- a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
@@ -173,7 +173,7 @@
com.android.internal.R.styleable.SystemCodeFilter);
systemCode = a.getString(
com.android.internal.R.styleable.SystemCodeFilter_name).toUpperCase();
- if (!NfcFCardEmulation.isValidSystemCode(systemCode) &&
+ if (!isValidSystemCode(systemCode) &&
!systemCode.equalsIgnoreCase("NULL")) {
Log.e(TAG, "Invalid System Code: " + systemCode);
systemCode = null;
@@ -187,7 +187,7 @@
com.android.internal.R.styleable.Nfcid2Filter_name).toUpperCase();
if (!nfcid2.equalsIgnoreCase("RANDOM") &&
!nfcid2.equalsIgnoreCase("NULL") &&
- !NfcFCardEmulation.isValidNfcid2(nfcid2)) {
+ !isValidNfcid2(nfcid2)) {
Log.e(TAG, "Invalid NFCID2: " + nfcid2);
nfcid2 = null;
}
@@ -436,10 +436,62 @@
*/
@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
public void dumpDebug(@NonNull ProtoOutputStream proto) {
- Utils.dumpDebugComponentName(getComponent(), proto, NfcFServiceInfoProto.COMPONENT_NAME);
+ getComponent().dumpDebug(proto, NfcFServiceInfoProto.COMPONENT_NAME);
proto.write(NfcFServiceInfoProto.DESCRIPTION, getDescription());
proto.write(NfcFServiceInfoProto.SYSTEM_CODE, getSystemCode());
proto.write(NfcFServiceInfoProto.NFCID2, getNfcid2());
proto.write(NfcFServiceInfoProto.T3T_PMM, getT3tPmm());
}
+
+ /**
+ * Copied over from {@link NfcFCardEmulation#isValidSystemCode(String)}
+ * @hide
+ */
+ private static boolean isValidSystemCode(String systemCode) {
+ if (systemCode == null) {
+ return false;
+ }
+ if (systemCode.length() != 4) {
+ Log.e(TAG, "System Code " + systemCode + " is not a valid System Code.");
+ return false;
+ }
+ // check if the value is between "4000" and "4FFF" (excluding "4*FF")
+ if (!systemCode.startsWith("4") || systemCode.toUpperCase().endsWith("FF")) {
+ Log.e(TAG, "System Code " + systemCode + " is not a valid System Code.");
+ return false;
+ }
+ try {
+ Integer.parseInt(systemCode, 16);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "System Code " + systemCode + " is not a valid System Code.");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Copied over from {@link NfcFCardEmulation#isValidNfcid2(String)}
+ * @hide
+ */
+ private static boolean isValidNfcid2(String nfcid2) {
+ if (nfcid2 == null) {
+ return false;
+ }
+ if (nfcid2.length() != 16) {
+ Log.e(TAG, "NFCID2 " + nfcid2 + " is not a valid NFCID2.");
+ return false;
+ }
+ // check if the the value starts with "02FE"
+ if (!nfcid2.toUpperCase().startsWith("02FE")) {
+ Log.e(TAG, "NFCID2 " + nfcid2 + " is not a valid NFCID2.");
+ return false;
+ }
+ try {
+ Long.parseLong(nfcid2, 16);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "NFCID2 " + nfcid2 + " is not a valid NFCID2.");
+ return false;
+ }
+ return true;
+ }
}
diff --git a/core/java/android/nfc/flags.aconfig b/core/java/android/nfc/flags.aconfig
index 55b0b42..cd50ace 100644
--- a/core/java/android/nfc/flags.aconfig
+++ b/core/java/android/nfc/flags.aconfig
@@ -13,3 +13,10 @@
description: "Flag for NFC reader option API changes"
bug: "291187960"
}
+
+flag {
+ name: "enable_nfc_user_restriction"
+ namespace: "nfc"
+ description: "Flag for NFC user restriction"
+ bug: "291187960"
+}
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 299e7f1..a07735e 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -125,7 +125,6 @@
private GameManager mGameManager;
private int mAngleOptInIndex = -1;
- private boolean mEnabledByGameMode = false;
private boolean mShouldUseAngle = false;
/**
@@ -179,23 +178,6 @@
}
/**
- * Query to determine if the Game Mode has enabled ANGLE.
- */
- private boolean isAngleEnabledByGameMode(Context context, String packageName) {
- try {
- final boolean gameModeEnabledAngle =
- (mGameManager != null) && mGameManager.isAngleEnabled(packageName);
- Log.v(TAG, "ANGLE GameManagerService for " + packageName + ": " + gameModeEnabledAngle);
- return gameModeEnabledAngle;
- } catch (SecurityException e) {
- Log.e(TAG, "Caught exception while querying GameManagerService if ANGLE is enabled "
- + "for package: " + packageName);
- }
-
- return false;
- }
-
- /**
* Query to determine the ANGLE driver choice.
*/
private String queryAngleChoice(Context context, Bundle coreSettings,
@@ -423,8 +405,7 @@
* 2) The per-application switch (i.e. Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS and
* Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES; which corresponds to the
* “angle_gl_driver_selection_pkgs” and “angle_gl_driver_selection_values” settings); if it
- * forces a choice;
- * 3) Use ANGLE if isAngleEnabledByGameMode() returns true;
+ * forces a choice.
*/
private String queryAngleChoiceInternal(Context context, Bundle bundle,
String packageName) {
@@ -458,18 +439,15 @@
Log.v(TAG, " angle_gl_driver_selection_pkgs=" + optInPackages);
Log.v(TAG, " angle_gl_driver_selection_values=" + optInValues);
- mEnabledByGameMode = isAngleEnabledByGameMode(context, packageName);
-
// Make sure we have good settings to use
- if (optInPackages.size() != optInValues.size()) {
+ if (optInPackages.size() == 0 || optInPackages.size() != optInValues.size()) {
Log.v(TAG,
"Global.Settings values are invalid: "
+ "number of packages: "
+ optInPackages.size() + ", "
+ "number of values: "
+ optInValues.size());
- return mEnabledByGameMode ? ANGLE_GL_DRIVER_CHOICE_ANGLE
- : ANGLE_GL_DRIVER_CHOICE_DEFAULT;
+ return ANGLE_GL_DRIVER_CHOICE_DEFAULT;
}
// See if this application is listed in the per-application settings list
@@ -477,8 +455,7 @@
if (pkgIndex < 0) {
Log.v(TAG, packageName + " is not listed in per-application setting");
- return mEnabledByGameMode ? ANGLE_GL_DRIVER_CHOICE_ANGLE
- : ANGLE_GL_DRIVER_CHOICE_DEFAULT;
+ return ANGLE_GL_DRIVER_CHOICE_DEFAULT;
}
mAngleOptInIndex = pkgIndex;
@@ -492,12 +469,9 @@
return ANGLE_GL_DRIVER_CHOICE_ANGLE;
} else if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE)) {
return ANGLE_GL_DRIVER_CHOICE_NATIVE;
- } else {
- // The user either chose default or an invalid value; go with the default driver or what
- // the game mode indicates
- return mEnabledByGameMode ? ANGLE_GL_DRIVER_CHOICE_ANGLE
- : ANGLE_GL_DRIVER_CHOICE_DEFAULT;
}
+ // The user either chose default or an invalid value; go with the default driver.
+ return ANGLE_GL_DRIVER_CHOICE_DEFAULT;
}
/**
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 180735b..90a4071 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -2372,14 +2372,14 @@
}
/** Assume locked until we hear otherwise */
- private static volatile boolean sUserKeyUnlocked = false;
+ private static volatile boolean sCeStorageUnlocked = false;
- private static boolean isUserKeyUnlocked(int userId) {
+ private static boolean isCeStorageUnlocked(int userId) {
final IStorageManager storage = IStorageManager.Stub
.asInterface(ServiceManager.getService("mount"));
if (storage != null) {
try {
- return storage.isUserKeyUnlocked(userId);
+ return storage.isCeStorageUnlocked(userId);
} catch (RemoteException ignored) {
}
}
@@ -2392,13 +2392,13 @@
// since any relocking of that user will always result in our
// process being killed to release any CE FDs we're holding onto.
if (userId == UserHandle.myUserId()) {
- if (sUserKeyUnlocked) {
+ if (sCeStorageUnlocked) {
return;
- } else if (isUserKeyUnlocked(userId)) {
- sUserKeyUnlocked = true;
+ } else if (isCeStorageUnlocked(userId)) {
+ sCeStorageUnlocked = true;
return;
}
- } else if (isUserKeyUnlocked(userId)) {
+ } else if (isCeStorageUnlocked(userId)) {
return;
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 159394b..bbfd593 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -23,6 +23,7 @@
import android.accounts.AccountManager;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -58,6 +59,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.location.LocationManager;
+import android.nfc.Flags;
import android.provider.Settings;
import android.util.AndroidException;
import android.util.ArraySet;
@@ -1831,6 +1833,7 @@
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
*/
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_USER_RESTRICTION)
public static final String DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO =
"no_near_field_communication_radio";
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index bc52744..25b2aa7 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -134,20 +134,20 @@
@EnforcePermission("MOUNT_UNMOUNT_FILESYSTEMS")
void setDebugFlags(int flags, int mask) = 60;
@EnforcePermission("STORAGE_INTERNAL")
- void createUserKey(int userId, int serialNumber, boolean ephemeral) = 61;
+ void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) = 61;
@EnforcePermission("STORAGE_INTERNAL")
- void destroyUserKey(int userId) = 62;
+ void destroyUserStorageKeys(int userId) = 62;
@EnforcePermission("STORAGE_INTERNAL")
- void unlockUserKey(int userId, int serialNumber, in byte[] secret) = 63;
+ void unlockCeStorage(int userId, int serialNumber, in byte[] secret) = 63;
@EnforcePermission("STORAGE_INTERNAL")
- void lockUserKey(int userId) = 64;
- boolean isUserKeyUnlocked(int userId) = 65;
+ void lockCeStorage(int userId) = 64;
+ boolean isCeStorageUnlocked(int userId) = 65;
@EnforcePermission("STORAGE_INTERNAL")
void prepareUserStorage(in String volumeUuid, int userId, int serialNumber, int flags) = 66;
@EnforcePermission("STORAGE_INTERNAL")
void destroyUserStorage(in String volumeUuid, int userId, int flags) = 67;
@EnforcePermission("STORAGE_INTERNAL")
- void setUserKeyProtection(int userId, in byte[] secret) = 70;
+ void setCeStorageProtection(int userId, in byte[] secret) = 70;
@EnforcePermission("MOUNT_FORMAT_FILESYSTEMS")
void fstrim(int flags, IVoldTaskListener listener) = 72;
AppFuseMount mountProxyFileDescriptorBridge() = 73;
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 80dd488..8e72e13 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1580,28 +1580,64 @@
DEFAULT_FULL_THRESHOLD_BYTES);
}
- /** {@hide} */
- public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
+ /**
+ * Creates the keys for a user's credential-encrypted (CE) and device-encrypted (DE) storage.
+ * <p>
+ * This creates the user's CE key and DE key for internal storage, then adds them to the kernel.
+ * Then, if the user is not ephemeral, this stores the DE key (encrypted) on flash. (The CE key
+ * is not stored until {@link IStorageManager#setCeStorageProtection()}.)
+ * <p>
+ * This does not create the CE and DE directories themselves. For that, see {@link
+ * #prepareUserStorage()}.
+ * <p>
+ * This is only intended to be called by UserManagerService, as part of creating a user.
+ *
+ * @param userId ID of the user
+ * @param serialNumber serial number of the user
+ * @param ephemeral whether the user is ephemeral
+ * @throws RuntimeException on error. The user's keys already existing is considered an error.
+ * @hide
+ */
+ public void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) {
try {
- mStorageManager.createUserKey(userId, serialNumber, ephemeral);
+ mStorageManager.createUserStorageKeys(userId, serialNumber, ephemeral);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
- /** {@hide} */
- public void destroyUserKey(int userId) {
+ /**
+ * Destroys the keys for a user's credential-encrypted (CE) and device-encrypted (DE) storage.
+ * <p>
+ * This evicts the keys from the kernel (if present), which "locks" the corresponding
+ * directories. Then, this deletes the encrypted keys from flash. This operates on all the
+ * user's CE and DE keys, for both internal and adoptable storage.
+ * <p>
+ * This does not destroy the CE and DE directories themselves. For that, see {@link
+ * #destroyUserStorage()}.
+ * <p>
+ * This is only intended to be called by UserManagerService, as part of removing a user.
+ *
+ * @param userId ID of the user
+ * @throws RuntimeException on error. On error, as many things as possible are still destroyed.
+ * @hide
+ */
+ public void destroyUserStorageKeys(int userId) {
try {
- mStorageManager.destroyUserKey(userId);
+ mStorageManager.destroyUserStorageKeys(userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
- /** {@hide} */
- public void lockUserKey(int userId) {
+ /**
+ * Locks the user's credential-encrypted (CE) storage.
+ *
+ * @hide
+ */
+ public void lockCeStorage(int userId) {
try {
- mStorageManager.lockUserKey(userId);
+ mStorageManager.lockCeStorage(userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1628,17 +1664,26 @@
/** {@hide} */
@TestApi
public static boolean isUserKeyUnlocked(int userId) {
+ return isCeStorageUnlocked(userId);
+ }
+
+ /**
+ * Returns true if the user's credential-encrypted (CE) storage is unlocked.
+ *
+ * @hide
+ */
+ public static boolean isCeStorageUnlocked(int userId) {
if (sStorageManager == null) {
sStorageManager = IStorageManager.Stub
.asInterface(ServiceManager.getService("mount"));
}
if (sStorageManager == null) {
- Slog.w(TAG, "Early during boot, assuming locked");
+ Slog.w(TAG, "Early during boot, assuming CE storage is locked");
return false;
}
final long token = Binder.clearCallingIdentity();
try {
- return sStorageManager.isUserKeyUnlocked(userId);
+ return sStorageManager.isCeStorageUnlocked(userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bcd8c7d..2f86efe 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9926,6 +9926,13 @@
public static final String SPATIAL_AUDIO_ENABLED = "spatial_audio_enabled";
/**
+ * Internal collection of audio device inventory items
+ * The device item stored are {@link com.android.server.audio.AdiDeviceState}
+ * @hide
+ */
+ public static final String AUDIO_DEVICE_INVENTORY = "audio_device_inventory";
+
+ /**
* Indicates whether notification display on the lock screen is enabled.
* <p>
* Type: int (0 for false, 1 for true)
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index b6c2b83..5aa3097 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -12,4 +12,5 @@
namespace: "hardware_backed_security"
description: "Fix bugs in behavior of UnlockedDeviceRequired keystore keys"
bug: "296464083"
+ is_fixed_read_only: true
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index a3e2706..8d11672 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1934,15 +1934,21 @@
}
/**
- * Unlocks the credential-encrypted storage for the given user if the user is not secured, i.e.
- * doesn't have an LSKF.
+ * If the user is not secured, ie doesn't have an LSKF, then decrypt the user's synthetic
+ * password and use it to unlock various cryptographic keys associated with the user. This
+ * primarily includes unlocking the user's credential-encrypted (CE) storage. It also includes
+ * deriving or decrypting the vendor auth secret and sending it to the AuthSecret HAL.
* <p>
- * Whether the storage has been unlocked can be determined by
- * {@link StorageManager#isUserKeyUnlocked()}.
- *
+ * These tasks would normally be done when the LSKF is verified. This method is where these
+ * tasks are done when the user doesn't have an LSKF. It's called when the user is started.
+ * <p>
+ * Except on permission denied, this method doesn't throw an exception on failure. However, the
+ * last thing that it does is unlock CE storage, and whether CE storage has been successfully
+ * unlocked can be determined by {@link StorageManager#isCeStorageUnlocked()}.
+ * <p>
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
*
- * @param userId the ID of the user whose storage to unlock
+ * @param userId the ID of the user whose keys to unlock
*/
public void unlockUserKeyIfUnsecured(@UserIdInt int userId) {
try {
diff --git a/core/proto/android/nfc/Android.bp b/core/proto/android/nfc/Android.bp
deleted file mode 100644
index 6a62c91..0000000
--- a/core/proto/android/nfc/Android.bp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-filegroup {
- name: "srcs_nfc_proto",
- srcs: [
- "*.proto",
- ],
-}
-
-// Will be statically linked by `framework-nfc`.
-java_library {
- name: "nfc-proto-java-gen",
- installable: false,
- proto: {
- type: "stream",
- include_dirs: [
- "external/protobuf/src",
- ],
- },
- srcs: [
- ":srcs_nfc_proto",
- ],
- sdk_version: "current",
- min_sdk_version: "current",
-}
diff --git a/core/proto/android/service/OWNERS b/core/proto/android/service/OWNERS
index 70cb50f..7a19155 100644
--- a/core/proto/android/service/OWNERS
+++ b/core/proto/android/service/OWNERS
@@ -1 +1,2 @@
per-file sensor_service.proto = arthuri@google.com, bduddie@google.com, stange@google.com
+per-file package.proto = file:platform/frameworks/base:/PACKAGE_MANAGER_OWNERS
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index e27cd97..31092536 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -439,8 +439,10 @@
key usage 0x0c0173 MEDIA_AUDIO_TRACK
key usage 0x0c019C PROFILE_SWITCH
key usage 0x0c01A2 ALL_APPS
-key usage 0x0d0044 STYLUS_BUTTON_PRIMARY
-key usage 0x0d005a STYLUS_BUTTON_SECONDARY
+# TODO(b/297094448): Add stylus button mappings as a fallback when we have a way to determine
+# if a device can actually report it.
+# key usage 0x0d0044 STYLUS_BUTTON_PRIMARY
+# key usage 0x0d005a STYLUS_BUTTON_SECONDARY
# Joystick and game controller axes.
# Axes that are not mapped will be assigned generic axis numbers by the input subsystem.
diff --git a/location/Android.bp b/location/Android.bp
index ead46e9..46dca74 100644
--- a/location/Android.bp
+++ b/location/Android.bp
@@ -15,10 +15,27 @@
],
}
-java_library {
- name: "framework-location.stubs.module_lib",
+java_sdk_library {
+ name: "framework-location",
srcs: [
":framework-location-nonupdatable-sources",
],
- sdk_version: "core_platform",
+ defaults: ["framework-non-updatable-unbundled-defaults"],
+ permitted_packages: [
+ "android.location",
+ "com.android.internal.location",
+ ],
+ libs: [
+ "app-compat-annotations",
+ "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
+ ],
+ hidden_api_packages: [
+ "com.android.internal.location",
+ ],
+ aidl: {
+ include_dirs: [
+ "frameworks/base/location/java",
+ "frameworks/base/core/java",
+ ],
+ },
}
diff --git a/location/api/current.txt b/location/api/current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/location/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/location/api/module-lib-current.txt b/location/api/module-lib-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/location/api/module-lib-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/location/api/module-lib-removed.txt b/location/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/location/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/location/api/removed.txt b/location/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/location/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/location/api/system-current.txt b/location/api/system-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/location/api/system-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/location/api/system-removed.txt b/location/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/location/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/location/api/test-current.txt b/location/api/test-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/location/api/test-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/location/api/test-removed.txt b/location/api/test-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/location/api/test-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/nfc-extras/OWNERS b/nfc-extras/OWNERS
new file mode 100644
index 0000000..35e9713
--- /dev/null
+++ b/nfc-extras/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 48448
+include platform/packages/apps/Nfc:/OWNERS
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index ffed804..fe8386e 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -16,6 +16,8 @@
package com.android.nfc_extras;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.HashMap;
import android.content.Context;
@@ -30,6 +32,8 @@
*
* There is a 1-1 relationship between an {@link NfcAdapterExtras} object and
* a {@link NfcAdapter} object.
+ *
+ * TODO(b/303286040): Deprecate this API surface since this is no longer supported (see ag/443092)
*/
public final class NfcAdapterExtras {
private static final String TAG = "NfcAdapterExtras";
@@ -72,15 +76,40 @@
private final NfcAdapter mAdapter;
final String mPackageName;
+ private static INfcAdapterExtras
+ getNfcAdapterExtrasInterfaceFromNfcAdapter(NfcAdapter adapter) {
+ try {
+ Method method = NfcAdapter.class.getDeclaredMethod("getNfcAdapterExtrasInterface");
+ method.setAccessible(true);
+ return (INfcAdapterExtras) method.invoke(adapter);
+ } catch (SecurityException | NoSuchMethodException | IllegalArgumentException
+ | IllegalAccessException | IllegalAccessError | InvocationTargetException e) {
+ Log.e(TAG, "Unable to get context from NfcAdapter");
+ }
+ return null;
+ }
+
/** get service handles */
private static void initService(NfcAdapter adapter) {
- final INfcAdapterExtras service = adapter.getNfcAdapterExtrasInterface();
+ final INfcAdapterExtras service = getNfcAdapterExtrasInterfaceFromNfcAdapter(adapter);
if (service != null) {
// Leave stale rather than receive a null value.
sService = service;
}
}
+ private static Context getContextFromNfcAdapter(NfcAdapter adapter) {
+ try {
+ Method method = NfcAdapter.class.getDeclaredMethod("getContext");
+ method.setAccessible(true);
+ return (Context) method.invoke(adapter);
+ } catch (SecurityException | NoSuchMethodException | IllegalArgumentException
+ | IllegalAccessException | IllegalAccessError | InvocationTargetException e) {
+ Log.e(TAG, "Unable to get context from NfcAdapter");
+ }
+ return null;
+ }
+
/**
* Get the {@link NfcAdapterExtras} for the given {@link NfcAdapter}.
*
@@ -91,7 +120,7 @@
* @return the {@link NfcAdapterExtras} object for the given {@link NfcAdapter}
*/
public static NfcAdapterExtras get(NfcAdapter adapter) {
- Context context = adapter.getContext();
+ Context context = getContextFromNfcAdapter(adapter);
if (context == null) {
throw new UnsupportedOperationException(
"You must pass a context to your NfcAdapter to use the NFC extras APIs");
@@ -112,7 +141,7 @@
private NfcAdapterExtras(NfcAdapter adapter) {
mAdapter = adapter;
- mPackageName = adapter.getContext().getPackageName();
+ mPackageName = getContextFromNfcAdapter(adapter).getPackageName();
mEmbeddedEe = new NfcExecutionEnvironment(this);
mRouteOnWhenScreenOn = new CardEmulationRoute(CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON,
mEmbeddedEe);
@@ -156,12 +185,24 @@
}
}
+ private static void attemptDeadServiceRecoveryOnNfcAdapter(NfcAdapter adapter, Exception e) {
+ try {
+ Method method = NfcAdapter.class.getDeclaredMethod(
+ "attemptDeadServiceRecovery", Exception.class);
+ method.setAccessible(true);
+ method.invoke(adapter, e);
+ } catch (SecurityException | NoSuchMethodException | IllegalArgumentException
+ | IllegalAccessException | IllegalAccessError | InvocationTargetException ex) {
+ Log.e(TAG, "Unable to attempt dead service recovery on NfcAdapter");
+ }
+ }
+
/**
* NFC service dead - attempt best effort recovery
*/
void attemptDeadServiceRecovery(Exception e) {
Log.e(TAG, "NFC Adapter Extras dead - attempting to recover");
- mAdapter.attemptDeadServiceRecovery(e);
+ attemptDeadServiceRecoveryOnNfcAdapter(mAdapter, e);
initService(mAdapter);
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
index 3505cfb..74f04e0 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallFailed.java
@@ -33,8 +33,6 @@
import androidx.annotation.Nullable;
-import java.io.File;
-
/**
* Installation failed: Return status code to the caller or display failure UI to user
*/
@@ -101,14 +99,8 @@
// Set header icon and title
PackageUtil.AppSnippet as;
PackageManager pm = getPackageManager();
-
- if ("package".equals(packageURI.getScheme())) {
- as = new PackageUtil.AppSnippet(pm.getApplicationLabel(appInfo),
- pm.getApplicationIcon(appInfo));
- } else {
- final File sourceFile = new File(packageURI.getPath());
- as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
- }
+ as = intent.getParcelableExtra(PackageInstallerActivity.EXTRA_APP_SNIPPET,
+ PackageUtil.AppSnippet.class);
// Store label for dialog
mLabel = as.label;
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
index 7bea339..1088ace 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
@@ -16,6 +16,7 @@
package com.android.packageinstaller;
+import static com.android.packageinstaller.PackageInstallerActivity.EXTRA_APP_SNIPPET;
import static com.android.packageinstaller.PackageInstallerActivity.EXTRA_STAGED_SESSION_ID;
import android.app.PendingIntent;
@@ -86,7 +87,8 @@
// ContentResolver.SCHEME_FILE
// STAGED_SESSION_ID extra contains an ID of a previously staged install session.
final File sourceFile = new File(mPackageURI.getPath());
- PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
+ PackageUtil.AppSnippet as = getIntent()
+ .getParcelableExtra(EXTRA_APP_SNIPPET, PackageUtil.AppSnippet.class);
mAlert.setIcon(as.icon);
mAlert.setTitle(as.label);
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
index 73c03a5..579fb7b 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallSuccess.java
@@ -23,7 +23,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
@@ -31,7 +30,6 @@
import androidx.annotation.Nullable;
-import java.io.File;
import java.util.List;
/**
@@ -66,18 +64,8 @@
ApplicationInfo appInfo =
intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mAppPackageName = appInfo.packageName;
- Uri packageURI = intent.getData();
-
- // Set header icon and title
- PackageManager pm = getPackageManager();
-
- if ("package".equals(packageURI.getScheme())) {
- mAppSnippet = new PackageUtil.AppSnippet(pm.getApplicationLabel(appInfo),
- pm.getApplicationIcon(appInfo));
- } else {
- File sourceFile = new File(packageURI.getPath());
- mAppSnippet = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
- }
+ mAppSnippet = intent.getParcelableExtra(PackageInstallerActivity.EXTRA_APP_SNIPPET,
+ PackageUtil.AppSnippet.class);
mLaunchIntent = getPackageManager().getLaunchIntentForPackage(mAppPackageName);
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 38d5d3a..1e20168 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -81,6 +81,7 @@
static final String EXTRA_CALLING_ATTRIBUTION_TAG = "EXTRA_CALLING_ATTRIBUTION_TAG";
static final String EXTRA_ORIGINAL_SOURCE_INFO = "EXTRA_ORIGINAL_SOURCE_INFO";
static final String EXTRA_STAGED_SESSION_ID = "EXTRA_STAGED_SESSION_ID";
+ static final String EXTRA_APP_SNIPPET = "EXTRA_APP_SNIPPET";
private static final String ALLOW_UNKNOWN_SOURCES_KEY =
PackageInstallerActivity.class.getName() + "ALLOW_UNKNOWN_SOURCES_KEY";
@@ -595,7 +596,7 @@
CharSequence label = mPm.getApplicationLabel(mPkgInfo.applicationInfo);
if (mLocalLOGV) Log.i(TAG, "creating snippet for " + label);
mAppSnippet = new PackageUtil.AppSnippet(label,
- mPm.getApplicationIcon(mPkgInfo.applicationInfo));
+ mPm.getApplicationIcon(mPkgInfo.applicationInfo), getBaseContext());
} break;
case ContentResolver.SCHEME_FILE: {
@@ -633,7 +634,7 @@
mPkgInfo = generateStubPackageInfo(info.getAppPackageName());
mAppSnippet = new PackageUtil.AppSnippet(info.getAppLabel(),
info.getAppIcon() != null ? new BitmapDrawable(getResources(), info.getAppIcon())
- : getPackageManager().getDefaultActivityIcon());
+ : getPackageManager().getDefaultActivityIcon(), getBaseContext());
return true;
}
@@ -693,6 +694,9 @@
if (stagedSessionId > 0) {
newIntent.putExtra(EXTRA_STAGED_SESSION_ID, stagedSessionId);
}
+ if (mAppSnippet != null) {
+ newIntent.putExtra(EXTRA_APP_SNIPPET, mAppSnippet);
+ }
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
if (mLocalLOGV) Log.i(TAG, "downloaded app uri=" + mPackageURI);
startActivity(newIntent);
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
index ff0e5fb..f6f7acc 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
@@ -18,6 +18,7 @@
package com.android.packageinstaller;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
@@ -27,8 +28,13 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.UserHandle;
import android.util.Log;
import android.view.View;
@@ -115,18 +121,75 @@
icon);
}
- static final class AppSnippet {
+ static final class AppSnippet implements Parcelable {
@NonNull public CharSequence label;
@Nullable public Drawable icon;
- public AppSnippet(@NonNull CharSequence label, @Nullable Drawable icon) {
+ public int iconSize;
+
+ public AppSnippet(@NonNull CharSequence label, @Nullable Drawable icon, Context context) {
this.label = label;
this.icon = icon;
+ final ActivityManager am = context.getSystemService(ActivityManager.class);
+ this.iconSize = am.getLauncherLargeIconSize();
+ }
+
+ private AppSnippet(Parcel in) {
+ label = in.readString();
+ Bitmap bmp = in.readParcelable(getClass().getClassLoader(), Bitmap.class);
+ icon = new BitmapDrawable(Resources.getSystem(), bmp);
+ iconSize = in.readInt();
}
@Override
public String toString() {
return "AppSnippet[" + label + (icon != null ? "(has" : "(no ") + " icon)]";
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(label.toString());
+ Bitmap bmp = getBitmapFromDrawable(icon);
+ dest.writeParcelable(bmp, 0);
+ dest.writeInt(iconSize);
+ }
+
+ private Bitmap getBitmapFromDrawable(Drawable drawable) {
+ // Create an empty bitmap with the dimensions of our drawable
+ final Bitmap bmp = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+ drawable.getIntrinsicHeight(),
+ Bitmap.Config.ARGB_8888);
+ // Associate it with a canvas. This canvas will draw the icon on the bitmap
+ final Canvas canvas = new Canvas(bmp);
+ // Draw the drawable in the canvas. The canvas will ultimately paint the drawable in the
+ // bitmap held within
+ drawable.draw(canvas);
+
+ // Scale it down if the icon is too large
+ if ((bmp.getWidth() > iconSize * 2) || (bmp.getHeight() > iconSize * 2)) {
+ Bitmap scaledBitmap = Bitmap.createScaledBitmap(bmp, iconSize, iconSize, true);
+ if (scaledBitmap != bmp) {
+ bmp.recycle();
+ }
+ return scaledBitmap;
+ }
+
+ return bmp;
+ }
+
+ public static final Parcelable.Creator<AppSnippet> CREATOR = new Parcelable.Creator<>() {
+ public AppSnippet createFromParcel(Parcel in) {
+ return new AppSnippet(in);
+ }
+
+ public AppSnippet[] newArray(int size) {
+ return new AppSnippet[size];
+ }
+ };
}
/**
@@ -171,7 +234,7 @@
} catch (OutOfMemoryError e) {
Log.i(LOG_TAG, "Could not load app icon", e);
}
- return new PackageUtil.AppSnippet(label, icon);
+ return new PackageUtil.AppSnippet(label, icon, pContext);
}
/**
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 57585e5..618f7ed 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -712,6 +712,7 @@
Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
Settings.Secure.AUTOMATIC_STORAGE_MANAGER_TURNED_OFF_BY_POLICY,
+ Settings.Secure.AUDIO_DEVICE_INVENTORY, // setting not controllable by user
Settings.Secure.BACKUP_AUTO_RESTORE,
Settings.Secure.BACKUP_ENABLED,
Settings.Secure.BACKUP_PROVISIONED,
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 8f329b3..34545cf 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -36,6 +36,7 @@
hwwang@google.com
hyunyoungs@google.com
ikateryna@google.com
+iyz@google.com
jaggies@google.com
jamesoleary@google.com
jbolinger@google.com
@@ -54,10 +55,12 @@
kozynski@google.com
kprevas@google.com
lusilva@google.com
+liuyining@google.com
lynhan@google.com
madym@google.com
mankoff@google.com
mateuszc@google.com
+matiashe@google.com
mgalhardo@google.com
michaelmikhil@google.com
michschn@google.com
@@ -94,6 +97,7 @@
tsuji@google.com
twickham@google.com
vadimt@google.com
+valiiftime@google.com
vanjan@google.com
victortulias@google.com
winsonc@google.com
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index d9fe949..b9ee63a 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -62,7 +62,8 @@
<com.android.systemui.statusbar.LightRevealScrim
android:id="@+id/light_reveal_scrim"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent"
+ sysui:ignoreRightInset="true" />
<include layout="@layout/status_bar_expanded"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/OWNERS
new file mode 100644
index 0000000..7f5384d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+include /packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS
\ No newline at end of file
diff --git a/services/Android.bp b/services/Android.bp
index 66181f5..3a0428e 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -235,12 +235,14 @@
stubs_defaults {
name: "services-stubs-default",
installable: false,
- args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\)" +
- " --hide-annotation android.annotation.Hide" +
- " --hide InternalClasses" + // com.android.* classes are okay in this interface
+ flags: [
+ "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\)",
+ "--hide-annotation android.annotation.Hide",
+ "--hide InternalClasses", // com.android.* classes are okay in this interface
// TODO: remove the --hide options below
- " --hide DeprecationMismatch" +
- " --hide HiddenTypedefConstant",
+ "--hide DeprecationMismatch",
+ "--hide HiddenTypedefConstant",
+ ],
visibility: ["//frameworks/base:__subpackages__"],
filter_packages: ["com.android."],
}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 9ac30f3..22f8570 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -130,6 +130,7 @@
"android.hardware.light-V2.0-java",
"android.hardware.gnss-V2-java",
"android.hardware.vibrator-V2-java",
+ "android.nfc.flags-aconfig-java",
"app-compat-annotations",
"framework-tethering.stubs.module_lib",
"service-art.stubs.system_server",
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 7142828..61584b7 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -377,15 +377,14 @@
private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_STORAGE);
/**
- * mLocalUnlockedUsers affects the return value of isUserUnlocked. If
- * any value in the array changes, then the binder cache for
- * isUserUnlocked must be invalidated. When adding mutating methods to
- * WatchedLockedUsers, be sure to invalidate the cache in the new
- * methods.
+ * mCeUnlockedUsers affects the return value of {@link UserManager#isUserUnlocked}. If any
+ * value in the array changes, then the binder cache for {@link UserManager#isUserUnlocked} must
+ * be invalidated. When adding mutating methods to this class, be sure to invalidate the cache
+ * in the new methods.
*/
- private static class WatchedLockedUsers {
+ private static class WatchedUnlockedUsers {
private int[] users = EmptyArray.INT;
- public WatchedLockedUsers() {
+ public WatchedUnlockedUsers() {
invalidateIsUserUnlockedCache();
}
public void append(int userId) {
@@ -417,10 +416,14 @@
}
}
- /** Set of users that we know are unlocked. */
+ /** Set of users whose CE storage is unlocked. */
@GuardedBy("mLock")
- private WatchedLockedUsers mLocalUnlockedUsers = new WatchedLockedUsers();
- /** Set of users that system knows are unlocked. */
+ private WatchedUnlockedUsers mCeUnlockedUsers = new WatchedUnlockedUsers();
+
+ /**
+ * Set of users that are in the RUNNING_UNLOCKED state. This differs from {@link
+ * mCeUnlockedUsers} in that a user can be stopped but still have its CE storage unlocked.
+ */
@GuardedBy("mLock")
private int[] mSystemUnlockedUsers = EmptyArray.INT;
@@ -1135,11 +1138,10 @@
}
}
- // If vold knows that some users have their storage unlocked already (which
- // can happen after a "userspace reboot"), then add those users to
- // mLocalUnlockedUsers. Do this right away and don't wait until
- // PHASE_BOOT_COMPLETED, since the system may unlock users before then.
- private void restoreLocalUnlockedUsers() {
+ // If vold knows that some users have their CE storage unlocked already (which can happen after
+ // a "userspace reboot"), then add those users to mCeUnlockedUsers. Do this right away and
+ // don't wait until PHASE_BOOT_COMPLETED, since the system may unlock users before then.
+ private void restoreCeUnlockedUsers() {
final int[] userIds;
try {
userIds = mVold.getUnlockedUsers();
@@ -1155,7 +1157,7 @@
// reconnecting to vold after it crashed and was restarted, in
// which case things will be the other way around --- we'll know
// about the unlocked users but vold won't.
- mLocalUnlockedUsers.appendAll(userIds);
+ mCeUnlockedUsers.appendAll(userIds);
}
}
}
@@ -2062,7 +2064,7 @@
connectVold();
}, DateUtils.SECOND_IN_MILLIS);
} else {
- restoreLocalUnlockedUsers();
+ restoreCeUnlockedUsers();
onDaemonConnected();
}
}
@@ -2982,7 +2984,7 @@
// We need all the users unlocked to move their primary storage
users = mContext.getSystemService(UserManager.class).getUsers();
for (UserInfo user : users) {
- if (StorageManager.isFileEncrypted() && !isUserKeyUnlocked(user.id)) {
+ if (StorageManager.isFileEncrypted() && !isCeStorageUnlocked(user.id)) {
Slog.w(TAG, "Failing move due to locked user " + user.id);
onMoveStatusLocked(PackageManager.MOVE_FAILED_LOCKED_USER);
return;
@@ -3206,15 +3208,15 @@
@android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL)
@Override
- public void createUserKey(int userId, int serialNumber, boolean ephemeral) {
+ public void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) {
- super.createUserKey_enforcePermission();
+ super.createUserStorageKeys_enforcePermission();
try {
- mVold.createUserKey(userId, serialNumber, ephemeral);
- // New keys are always unlocked.
+ mVold.createUserStorageKeys(userId, serialNumber, ephemeral);
+ // Since the user's CE key was just created, the user's CE storage is now unlocked.
synchronized (mLock) {
- mLocalUnlockedUsers.append(userId);
+ mCeUnlockedUsers.append(userId);
}
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -3223,15 +3225,15 @@
@android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL)
@Override
- public void destroyUserKey(int userId) {
+ public void destroyUserStorageKeys(int userId) {
- super.destroyUserKey_enforcePermission();
+ super.destroyUserStorageKeys_enforcePermission();
try {
- mVold.destroyUserKey(userId);
- // Destroying a key also locks it.
+ mVold.destroyUserStorageKeys(userId);
+ // Since the user's CE key was just destroyed, the user's CE storage is now locked.
synchronized (mLock) {
- mLocalUnlockedUsers.remove(userId);
+ mCeUnlockedUsers.remove(userId);
}
} catch (Exception e) {
Slog.wtf(TAG, e);
@@ -3241,60 +3243,60 @@
/* Only for use by LockSettingsService */
@android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL)
@Override
- public void setUserKeyProtection(@UserIdInt int userId, byte[] secret) throws RemoteException {
- super.setUserKeyProtection_enforcePermission();
+ public void setCeStorageProtection(@UserIdInt int userId, byte[] secret)
+ throws RemoteException {
+ super.setCeStorageProtection_enforcePermission();
- mVold.setUserKeyProtection(userId, HexDump.toHexString(secret));
+ mVold.setCeStorageProtection(userId, HexDump.toHexString(secret));
}
/* Only for use by LockSettingsService */
@android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL)
@Override
- public void unlockUserKey(@UserIdInt int userId, int serialNumber, byte[] secret)
- throws RemoteException {
- super.unlockUserKey_enforcePermission();
+ public void unlockCeStorage(@UserIdInt int userId, int serialNumber, byte[] secret)
+ throws RemoteException {
+ super.unlockCeStorage_enforcePermission();
if (StorageManager.isFileEncrypted()) {
- mVold.unlockUserKey(userId, serialNumber, HexDump.toHexString(secret));
+ mVold.unlockCeStorage(userId, serialNumber, HexDump.toHexString(secret));
}
synchronized (mLock) {
- mLocalUnlockedUsers.append(userId);
+ mCeUnlockedUsers.append(userId);
}
}
@android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL)
@Override
- public void lockUserKey(int userId) {
- // Do not lock user 0 data for headless system user
- super.lockUserKey_enforcePermission();
+ public void lockCeStorage(int userId) {
+ super.lockCeStorage_enforcePermission();
+ // Never lock the CE storage of a headless system user.
if (userId == UserHandle.USER_SYSTEM
&& UserManager.isHeadlessSystemUserMode()) {
throw new IllegalArgumentException("Headless system user data cannot be locked..");
}
-
- if (!isUserKeyUnlocked(userId)) {
+ if (!isCeStorageUnlocked(userId)) {
Slog.d(TAG, "User " + userId + "'s CE storage is already locked");
return;
}
try {
- mVold.lockUserKey(userId);
+ mVold.lockCeStorage(userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
return;
}
synchronized (mLock) {
- mLocalUnlockedUsers.remove(userId);
+ mCeUnlockedUsers.remove(userId);
}
}
@Override
- public boolean isUserKeyUnlocked(int userId) {
+ public boolean isCeStorageUnlocked(int userId) {
synchronized (mLock) {
- return mLocalUnlockedUsers.contains(userId);
+ return mCeUnlockedUsers.contains(userId);
}
}
@@ -3679,8 +3681,8 @@
final int userId = UserHandle.getUserId(callingUid);
final String propertyName = "sys.user." + userId + ".ce_available";
- // Ignore requests to create directories while storage is locked
- if (!isUserKeyUnlocked(userId)) {
+ // Ignore requests to create directories while CE storage is locked
+ if (!isCeStorageUnlocked(userId)) {
throw new IllegalStateException("Failed to prepare " + appPath);
}
@@ -3806,15 +3808,15 @@
final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);
final boolean userIsDemo;
- final boolean userKeyUnlocked;
final boolean storagePermission;
+ final boolean ceStorageUnlocked;
final long token = Binder.clearCallingIdentity();
try {
userIsDemo = LocalServices.getService(UserManagerInternal.class)
.getUserInfo(userId).isDemo();
storagePermission = mStorageManagerInternal.hasExternalStorage(callingUid,
callingPackage);
- userKeyUnlocked = isUserKeyUnlocked(userId);
+ ceStorageUnlocked = isCeStorageUnlocked(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -3874,7 +3876,7 @@
} else if (!systemUserUnlocked) {
reportUnmounted = true;
Slog.w(TAG, "Reporting " + volId + " unmounted due to system locked");
- } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
+ } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !ceStorageUnlocked) {
reportUnmounted = true;
Slog.w(TAG, "Reporting " + volId + "unmounted due to " + userId + " locked");
} else if (!storagePermission && !realState) {
@@ -4678,7 +4680,7 @@
}
pw.println();
- pw.println("Local unlocked users: " + mLocalUnlockedUsers);
+ pw.println("CE unlocked users: " + mCeUnlockedUsers);
pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e6df1d9..e74371e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2249,7 +2249,7 @@
return;
}
// TODO(b/148767783): should we check all profiles under user0?
- UserspaceRebootLogger.logEventAsync(StorageManager.isUserKeyUnlocked(userId),
+ UserspaceRebootLogger.logEventAsync(StorageManager.isCeStorageUnlocked(userId),
BackgroundThread.getExecutor());
}
@@ -4564,7 +4564,7 @@
// We carefully use the same state that PackageManager uses for
// filtering, since we use this flag to decide if we need to install
// providers when user is unlocked later
- app.setUnlocked(StorageManager.isUserKeyUnlocked(app.userId));
+ app.setUnlocked(StorageManager.isCeStorageUnlocked(app.userId));
}
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 76a994e..6eb2961 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -639,8 +639,8 @@
mInjector.getUserJourneyLogger()
.logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_UNLOCKING_USER,
EVENT_STATE_BEGIN);
- // If the user key hasn't been unlocked yet, we cannot proceed.
- if (!StorageManager.isUserKeyUnlocked(userId)) return false;
+ // If the user's CE storage hasn't been unlocked yet, we cannot proceed.
+ if (!StorageManager.isCeStorageUnlocked(userId)) return false;
synchronized (mLock) {
// Do not proceed if unexpected state or a stale user
if (mStartedUsers.get(userId) != uss || uss.state != STATE_RUNNING_LOCKED) {
@@ -655,8 +655,8 @@
// Call onBeforeUnlockUser on a worker thread that allows disk I/O
FgThread.getHandler().post(() -> {
- if (!StorageManager.isUserKeyUnlocked(userId)) {
- Slogf.w(TAG, "User key got locked unexpectedly, leaving user locked.");
+ if (!StorageManager.isCeStorageUnlocked(userId)) {
+ Slogf.w(TAG, "User's CE storage got locked unexpectedly, leaving user locked.");
return;
}
@@ -690,8 +690,8 @@
private void finishUserUnlocked(final UserState uss) {
final int userId = uss.mHandle.getIdentifier();
EventLog.writeEvent(EventLogTags.UC_FINISH_USER_UNLOCKED, userId);
- // Only keep marching forward if user is actually unlocked
- if (!StorageManager.isUserKeyUnlocked(userId)) return;
+ // Only keep marching forward if the user's CE storage is unlocked.
+ if (!StorageManager.isCeStorageUnlocked(userId)) return;
synchronized (mLock) {
// Bail if we ended up with a stale user
if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
@@ -777,8 +777,8 @@
if (userInfo == null) {
return;
}
- // Only keep marching forward if user is actually unlocked
- if (!StorageManager.isUserKeyUnlocked(userId)) return;
+ // Only keep marching forward if the user's CE storage is unlocked.
+ if (!StorageManager.isCeStorageUnlocked(userId)) return;
// Remember that we logged in
mInjector.getUserManager().onUserLoggedIn(userId);
@@ -1256,7 +1256,7 @@
}
try {
Slogf.i(TAG, "Locking CE storage for user #" + userId);
- mInjector.getStorageManager().lockUserKey(userId);
+ mInjector.getStorageManager().lockCeStorage(userId);
} catch (RemoteException re) {
throw re.rethrowAsRuntimeException();
}
@@ -1874,8 +1874,8 @@
}
UserState uss;
- if (!StorageManager.isUserKeyUnlocked(userId)) {
- // We always want to try to unlock the user key, even if the user is not started yet.
+ if (!StorageManager.isCeStorageUnlocked(userId)) {
+ // We always want to try to unlock CE storage, even if the user is not started yet.
mLockPatternUtils.unlockUserKeyIfUnsecured(userId);
}
synchronized (mLock) {
@@ -2662,10 +2662,10 @@
case UserState.STATE_RUNNING_UNLOCKING:
case UserState.STATE_RUNNING_UNLOCKED:
return true;
- // In the stopping/shutdown state return unlock state of the user key
+ // In the stopping/shutdown state, return unlock state of the user's CE storage.
case UserState.STATE_STOPPING:
case UserState.STATE_SHUTDOWN:
- return StorageManager.isUserKeyUnlocked(userId);
+ return StorageManager.isCeStorageUnlocked(userId);
default:
return false;
}
@@ -2674,10 +2674,10 @@
switch (state.state) {
case UserState.STATE_RUNNING_UNLOCKED:
return true;
- // In the stopping/shutdown state return unlock state of the user key
+ // In the stopping/shutdown state, return unlock state of the user's CE storage.
case UserState.STATE_STOPPING:
case UserState.STATE_SHUTDOWN:
- return StorageManager.isUserKeyUnlocked(userId);
+ return StorageManager.isCeStorageUnlocked(userId);
default:
return false;
}
diff --git a/services/core/java/com/android/server/audio/AdiDeviceState.java b/services/core/java/com/android/server/audio/AdiDeviceState.java
new file mode 100644
index 0000000..a466235
--- /dev/null
+++ b/services/core/java/com/android/server/audio/AdiDeviceState.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.audio;
+
+import static android.media.AudioSystem.DEVICE_NONE;
+import static android.media.AudioSystem.isBluetoothDevice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.Objects;
+
+/**
+ * Class representing all devices that were previously or are currently connected. Data is
+ * persisted in {@link android.provider.Settings.Secure}
+ */
+/*package*/ final class AdiDeviceState {
+ private static final String TAG = "AS.AdiDeviceState";
+
+ private static final String SETTING_FIELD_SEPARATOR = ",";
+
+ @AudioDeviceInfo.AudioDeviceType
+ private final int mDeviceType;
+
+ private final int mInternalDeviceType;
+ @NonNull
+ private final String mDeviceAddress;
+ private boolean mSAEnabled;
+ private boolean mHasHeadTracker = false;
+ private boolean mHeadTrackerEnabled;
+
+ /**
+ * Constructor
+ *
+ * @param deviceType external audio device type
+ * @param internalDeviceType if not set pass {@link DEVICE_NONE}, in this case the
+ * default conversion of the external type will be used
+ * @param address must be non-null for wireless devices
+ * @throws NullPointerException if a null address is passed for a wireless device
+ */
+ AdiDeviceState(@AudioDeviceInfo.AudioDeviceType int deviceType,
+ int internalDeviceType,
+ @Nullable String address) {
+ mDeviceType = deviceType;
+ if (internalDeviceType != DEVICE_NONE) {
+ mInternalDeviceType = internalDeviceType;
+ } else {
+ mInternalDeviceType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(deviceType);
+
+ }
+ mDeviceAddress = isBluetoothDevice(mInternalDeviceType) ? Objects.requireNonNull(
+ address) : "";
+ }
+
+ @AudioDeviceInfo.AudioDeviceType
+ public int getDeviceType() {
+ return mDeviceType;
+ }
+
+ public int getInternalDeviceType() {
+ return mInternalDeviceType;
+ }
+
+ @NonNull
+ public String getDeviceAddress() {
+ return mDeviceAddress;
+ }
+
+ public void setSAEnabled(boolean sAEnabled) {
+ mSAEnabled = sAEnabled;
+ }
+
+ public boolean isSAEnabled() {
+ return mSAEnabled;
+ }
+
+ public void setHeadTrackerEnabled(boolean headTrackerEnabled) {
+ mHeadTrackerEnabled = headTrackerEnabled;
+ }
+
+ public boolean isHeadTrackerEnabled() {
+ return mHeadTrackerEnabled;
+ }
+
+ public void setHasHeadTracker(boolean hasHeadTracker) {
+ mHasHeadTracker = hasHeadTracker;
+ }
+
+
+ public boolean hasHeadTracker() {
+ return mHasHeadTracker;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ // type check and cast
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final AdiDeviceState sads = (AdiDeviceState) obj;
+ return mDeviceType == sads.mDeviceType
+ && mInternalDeviceType == sads.mInternalDeviceType
+ && mDeviceAddress.equals(sads.mDeviceAddress) // NonNull
+ && mSAEnabled == sads.mSAEnabled
+ && mHasHeadTracker == sads.mHasHeadTracker
+ && mHeadTrackerEnabled == sads.mHeadTrackerEnabled;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mDeviceType, mInternalDeviceType, mDeviceAddress, mSAEnabled,
+ mHasHeadTracker, mHeadTrackerEnabled);
+ }
+
+ @Override
+ public String toString() {
+ return "type: " + mDeviceType + "internal type: " + mInternalDeviceType
+ + " addr: " + mDeviceAddress + " enabled: " + mSAEnabled
+ + " HT: " + mHasHeadTracker + " HTenabled: " + mHeadTrackerEnabled;
+ }
+
+ public String toPersistableString() {
+ return (new StringBuilder().append(mDeviceType)
+ .append(SETTING_FIELD_SEPARATOR).append(mDeviceAddress)
+ .append(SETTING_FIELD_SEPARATOR).append(mSAEnabled ? "1" : "0")
+ .append(SETTING_FIELD_SEPARATOR).append(mHasHeadTracker ? "1" : "0")
+ .append(SETTING_FIELD_SEPARATOR).append(mHeadTrackerEnabled ? "1" : "0")
+ .append(SETTING_FIELD_SEPARATOR).append(mInternalDeviceType)
+ .toString());
+ }
+
+ /**
+ * Gets the max size (including separators) when persisting the elements with
+ * {@link AdiDeviceState#toPersistableString()}.
+ */
+ public static int getPeristedMaxSize() {
+ return 36; /* (mDeviceType)2 + (mDeviceAddress)17 + (mInternalDeviceType)9 + (mSAEnabled)1
+ + (mHasHeadTracker)1 + (mHasHeadTrackerEnabled)1
+ + (SETTINGS_FIELD_SEPARATOR)5 */
+ }
+
+ @Nullable
+ public static AdiDeviceState fromPersistedString(@Nullable String persistedString) {
+ if (persistedString == null) {
+ return null;
+ }
+ if (persistedString.isEmpty()) {
+ return null;
+ }
+ String[] fields = TextUtils.split(persistedString, SETTING_FIELD_SEPARATOR);
+ // we may have 5 fields for the legacy AdiDeviceState and 6 containing the internal
+ // device type
+ if (fields.length != 5 && fields.length != 6) {
+ // expecting all fields, fewer may mean corruption, ignore those settings
+ return null;
+ }
+ try {
+ final int deviceType = Integer.parseInt(fields[0]);
+ int internalDeviceType = -1;
+ if (fields.length == 6) {
+ internalDeviceType = Integer.parseInt(fields[5]);
+ }
+ final AdiDeviceState deviceState = new AdiDeviceState(deviceType,
+ internalDeviceType, fields[1]);
+ deviceState.setHasHeadTracker(Integer.parseInt(fields[2]) == 1);
+ deviceState.setHasHeadTracker(Integer.parseInt(fields[3]) == 1);
+ deviceState.setHeadTrackerEnabled(Integer.parseInt(fields[4]) == 1);
+ return deviceState;
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "unable to parse setting for AdiDeviceState: " + persistedString, e);
+ return null;
+ }
+ }
+
+ public AudioDeviceAttributes getAudioDeviceAttributes() {
+ return new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
+ mDeviceType, mDeviceAddress);
+ }
+
+}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 4f45c0d..85fc803 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -50,6 +50,7 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.PrintWriterPrinter;
@@ -69,8 +70,11 @@
import java.util.concurrent.atomic.AtomicBoolean;
-/** @hide */
-/*package*/ final class AudioDeviceBroker {
+/**
+ * @hide
+ * (non final for mocking/spying)
+ */
+public class AudioDeviceBroker {
private static final String TAG = "AS.AudioDeviceBroker";
@@ -1850,6 +1854,9 @@
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
BtHelper.onNotifyPreferredAudioProfileApplied(btDevice);
} break;
+ case MSG_PERSIST_AUDIO_DEVICE_SETTINGS:
+ onPersistAudioDeviceSettings();
+ break;
default:
Log.wtf(TAG, "Invalid message " + msg.what);
}
@@ -1927,6 +1934,8 @@
private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 52;
+ private static final int MSG_PERSIST_AUDIO_DEVICE_SETTINGS = 54;
+
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
@@ -2344,4 +2353,95 @@
info.getId(),
null /*mixerAttributes*/);
}
+
+ /**
+ * post a message to persist the audio device settings.
+ * Message is delayed by 1s on purpose in case of successive changes in quick succession (at
+ * init time for instance)
+ * Note this method is made public to work around a Mockito bug where it needs to be public
+ * in order to be mocked by a test a the same package
+ * (see https://code.google.com/archive/p/mockito/issues/127)
+ */
+ public void persistAudioDeviceSettings() {
+ sendMsg(MSG_PERSIST_AUDIO_DEVICE_SETTINGS, SENDMSG_REPLACE, /*delay*/ 1000);
+ }
+
+ void onPersistAudioDeviceSettings() {
+ final String deviceSettings = mDeviceInventory.getDeviceSettings();
+ Log.v(TAG, "saving audio device settings: " + deviceSettings);
+ final SettingsAdapter settings = mAudioService.getSettings();
+ boolean res = settings.putSecureStringForUser(mAudioService.getContentResolver(),
+ Settings.Secure.AUDIO_DEVICE_INVENTORY,
+ deviceSettings, UserHandle.USER_CURRENT);
+ if (!res) {
+ Log.e(TAG, "error saving audio device settings: " + deviceSettings);
+ }
+ }
+
+ void onReadAudioDeviceSettings() {
+ final SettingsAdapter settingsAdapter = mAudioService.getSettings();
+ final ContentResolver contentResolver = mAudioService.getContentResolver();
+ String settings = settingsAdapter.getSecureStringForUser(contentResolver,
+ Settings.Secure.AUDIO_DEVICE_INVENTORY, UserHandle.USER_CURRENT);
+ if (settings == null) {
+ Log.i(TAG, "reading spatial audio device settings from legacy key"
+ + Settings.Secure.SPATIAL_AUDIO_ENABLED);
+ // legacy string format for key SPATIAL_AUDIO_ENABLED has the same order of fields like
+ // the strings for key AUDIO_DEVICE_INVENTORY. This will ensure to construct valid
+ // device settings when calling {@link #setDeviceSettings()}
+ settings = settingsAdapter.getSecureStringForUser(contentResolver,
+ Settings.Secure.SPATIAL_AUDIO_ENABLED, UserHandle.USER_CURRENT);
+ if (settings == null) {
+ Log.i(TAG, "no spatial audio device settings stored with legacy key");
+ } else if (!settings.equals("")) {
+ // Delete old key value and update the new key
+ if (!settingsAdapter.putSecureStringForUser(contentResolver,
+ Settings.Secure.SPATIAL_AUDIO_ENABLED,
+ /*value=*/"",
+ UserHandle.USER_CURRENT)) {
+ Log.w(TAG, "cannot erase the legacy audio device settings with key "
+ + Settings.Secure.SPATIAL_AUDIO_ENABLED);
+ }
+ if (!settingsAdapter.putSecureStringForUser(contentResolver,
+ Settings.Secure.AUDIO_DEVICE_INVENTORY,
+ settings,
+ UserHandle.USER_CURRENT)) {
+ Log.e(TAG, "error updating the new audio device settings with key "
+ + Settings.Secure.AUDIO_DEVICE_INVENTORY);
+ }
+ }
+ }
+
+ if (settings != null && !settings.equals("")) {
+ setDeviceSettings(settings);
+ }
+ }
+
+ void setDeviceSettings(String settings) {
+ mDeviceInventory.setDeviceSettings(settings);
+ }
+
+ /** Test only method. */
+ String getDeviceSettings() {
+ return mDeviceInventory.getDeviceSettings();
+ }
+
+ List<AdiDeviceState> getImmutableDeviceInventory() {
+ return mDeviceInventory.getImmutableDeviceInventory();
+ }
+
+ void addDeviceStateToInventory(AdiDeviceState deviceState) {
+ mDeviceInventory.addDeviceStateToInventory(deviceState);
+ }
+
+ AdiDeviceState findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada,
+ int canonicalType) {
+ return mDeviceInventory.findDeviceStateForAudioDeviceAttributes(ada, canonicalType);
+ }
+
+ //------------------------------------------------
+ // for testing purposes only
+ void clearDeviceInventory() {
+ mDeviceInventory.clearDeviceInventory();
+ }
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 0c7f11f..b4ab14f 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -15,6 +15,8 @@
*/
package com.android.server.audio;
+import static android.media.AudioSystem.isBluetoothDevice;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.bluetooth.BluetoothAdapter;
@@ -78,12 +80,51 @@
private static final String TAG = "AS.AudioDeviceInventory";
+ private static final String SETTING_DEVICE_SEPARATOR_CHAR = "|";
+ private static final String SETTING_DEVICE_SEPARATOR = "\\|";
+
// lock to synchronize all access to mConnectedDevices and mApmConnectedDevices
private final Object mDevicesLock = new Object();
//Audio Analytics ids.
private static final String mMetricsId = "audio.device.";
+ private final Object mDeviceInventoryLock = new Object();
+ @GuardedBy("mDeviceCatalogLock")
+ private final ArrayList<AdiDeviceState> mDeviceInventory = new ArrayList<>(0);
+ List<AdiDeviceState> getImmutableDeviceInventory() {
+ synchronized (mDeviceInventoryLock) {
+ return List.copyOf(mDeviceInventory);
+ }
+ }
+
+ void addDeviceStateToInventory(AdiDeviceState deviceState) {
+ synchronized (mDeviceInventoryLock) {
+ mDeviceInventory.add(deviceState);
+ }
+ }
+
+ AdiDeviceState findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada,
+ int canonicalDeviceType) {
+ final boolean isWireless = isBluetoothDevice(ada.getInternalType());
+ synchronized (mDeviceInventoryLock) {
+ for (AdiDeviceState deviceSetting : mDeviceInventory) {
+ if (deviceSetting.getDeviceType() == canonicalDeviceType
+ && (!isWireless || ada.getAddress().equals(
+ deviceSetting.getDeviceAddress()))) {
+ return deviceSetting;
+ }
+ }
+ }
+ return null;
+ }
+
+ void clearDeviceInventory() {
+ synchronized (mDeviceInventoryLock) {
+ mDeviceInventory.clear();
+ }
+ }
+
// List of connected devices
// Key for map created from DeviceInfo.makeDeviceListKey()
@GuardedBy("mDevicesLock")
@@ -341,6 +382,12 @@
mAppliedPresetRolesInt.forEach((key, devices) -> {
pw.println(" " + prefix + "preset: " + key.first
+ " role:" + key.second + " devices:" + devices); });
+ pw.println("\ndevices:\n");
+ synchronized (mDeviceInventoryLock) {
+ for (AdiDeviceState device : mDeviceInventory) {
+ pw.println("\t" + device + "\n");
+ }
+ }
}
//------------------------------------------------------------
@@ -1198,7 +1245,7 @@
AudioDeviceInfo device = Stream.of(connectedDevices)
.filter(d -> d.getInternalType() == ada.getInternalType())
- .filter(d -> (!AudioSystem.isBluetoothDevice(d.getInternalType())
+ .filter(d -> (!isBluetoothDevice(d.getInternalType())
|| (d.getAddress().equals(ada.getAddress()))))
.findFirst()
.orElse(null);
@@ -1619,7 +1666,7 @@
}
for (DeviceInfo di : mConnectedDevices.values()) {
- if (!AudioSystem.isBluetoothDevice(di.mDeviceType)) {
+ if (!isBluetoothDevice(di.mDeviceType)) {
continue;
}
AudioDeviceAttributes ada =
@@ -1733,7 +1780,7 @@
}
HashSet<String> processedAddresses = new HashSet<>(0);
for (DeviceInfo di : mConnectedDevices.values()) {
- if (!AudioSystem.isBluetoothDevice(di.mDeviceType)
+ if (!isBluetoothDevice(di.mDeviceType)
|| processedAddresses.contains(di.mDeviceAddress)) {
continue;
}
@@ -1743,7 +1790,7 @@
+ di.mDeviceAddress + ", preferredProfiles: " + preferredProfiles);
}
for (DeviceInfo di2 : mConnectedDevices.values()) {
- if (!AudioSystem.isBluetoothDevice(di2.mDeviceType)
+ if (!isBluetoothDevice(di2.mDeviceType)
|| !di.mDeviceAddress.equals(di2.mDeviceAddress)) {
continue;
}
@@ -2359,6 +2406,40 @@
}
}
+ /*package*/ String getDeviceSettings() {
+ int deviceCatalogSize = 0;
+ synchronized (mDeviceInventoryLock) {
+ deviceCatalogSize = mDeviceInventory.size();
+ }
+ final StringBuilder settingsBuilder = new StringBuilder(
+ deviceCatalogSize * AdiDeviceState.getPeristedMaxSize());
+
+ synchronized (mDeviceInventoryLock) {
+ for (int i = 0; i < mDeviceInventory.size(); i++) {
+ settingsBuilder.append(mDeviceInventory.get(i).toPersistableString());
+ if (i != mDeviceInventory.size() - 1) {
+ settingsBuilder.append(SETTING_DEVICE_SEPARATOR_CHAR);
+ }
+ }
+ }
+ return settingsBuilder.toString();
+ }
+
+ /*package*/ void setDeviceSettings(String settings) {
+ clearDeviceInventory();
+ String[] devSettings = TextUtils.split(Objects.requireNonNull(settings),
+ SETTING_DEVICE_SEPARATOR);
+ // small list, not worth overhead of Arrays.stream(devSettings)
+ for (String setting : devSettings) {
+ AdiDeviceState devState = AdiDeviceState.fromPersistedString(setting);
+ // Note if the device is not compatible with spatialization mode or the device
+ // type is not canonical, it will be ignored in {@link SpatializerHelper}.
+ if (devState != null) {
+ addDeviceStateToInventory(devState);
+ }
+ }
+ }
+
//----------------------------------------------------------
// For tests only
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index f313e16..71424b1 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -382,7 +382,6 @@
private static final int MSG_DISPATCH_AUDIO_MODE = 40;
private static final int MSG_ROUTING_UPDATED = 41;
private static final int MSG_INIT_HEADTRACKING_SENSORS = 42;
- private static final int MSG_PERSIST_SPATIAL_AUDIO_DEVICE_SETTINGS = 43;
private static final int MSG_ADD_ASSISTANT_SERVICE_UID = 44;
private static final int MSG_REMOVE_ASSISTANT_SERVICE_UID = 45;
private static final int MSG_UPDATE_ACTIVE_ASSISTANT_SERVICE_UID = 46;
@@ -1022,6 +1021,8 @@
mAudioPolicy = audioPolicy;
mPlatformType = AudioSystem.getPlatformType(context);
+ mDeviceBroker = new AudioDeviceBroker(mContext, this, mAudioSystem);
+
mIsSingleVolume = AudioSystem.isSingleVolume(context);
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
@@ -1034,13 +1035,14 @@
mSfxHelper = new SoundEffectsHelper(mContext, playerBase -> ignorePlayerLogs(playerBase));
- final boolean binauralEnabledDefault = SystemProperties.getBoolean(
+ boolean binauralEnabledDefault = SystemProperties.getBoolean(
"ro.audio.spatializer_binaural_enabled_default", true);
- final boolean transauralEnabledDefault = SystemProperties.getBoolean(
+ boolean transauralEnabledDefault = SystemProperties.getBoolean(
"ro.audio.spatializer_transaural_enabled_default", true);
- final boolean headTrackingEnabledDefault = mContext.getResources().getBoolean(
+ boolean headTrackingEnabledDefault = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_spatial_audio_head_tracking_enabled_default);
- mSpatializerHelper = new SpatializerHelper(this, mAudioSystem,
+
+ mSpatializerHelper = new SpatializerHelper(this, mAudioSystem, mDeviceBroker,
binauralEnabledDefault, transauralEnabledDefault, headTrackingEnabledDefault);
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
@@ -1208,8 +1210,6 @@
mUseFixedVolume = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useFixedVolume);
- mDeviceBroker = new AudioDeviceBroker(mContext, this, mAudioSystem);
-
mRecordMonitor = new RecordingActivityMonitor(mContext);
mRecordMonitor.registerRecordingCallback(mVoiceRecordingActivityMonitor, true);
@@ -6573,6 +6573,10 @@
return mContentResolver;
}
+ /*package*/ SettingsAdapter getSettings() {
+ return mSettings;
+ }
+
///////////////////////////////////////////////////////////////////////////
// Internal methods
///////////////////////////////////////////////////////////////////////////
@@ -9215,10 +9219,6 @@
mSpatializerHelper.onInitSensors();
break;
- case MSG_PERSIST_SPATIAL_AUDIO_DEVICE_SETTINGS:
- onPersistSpatialAudioDeviceSettings();
- break;
-
case MSG_RESET_SPATIALIZER:
mSpatializerHelper.reset(/* featureEnabled */ mHasSpatializerEffect);
break;
@@ -10275,41 +10275,11 @@
}
void onInitSpatializer() {
- final String settings = mSettings.getSecureStringForUser(mContentResolver,
- Settings.Secure.SPATIAL_AUDIO_ENABLED, UserHandle.USER_CURRENT);
- if (settings == null) {
- Log.e(TAG, "error reading spatial audio device settings");
- }
- mSpatializerHelper.init(/*effectExpected*/ mHasSpatializerEffect, settings);
+ mDeviceBroker.onReadAudioDeviceSettings();
+ mSpatializerHelper.init(/*effectExpected*/ mHasSpatializerEffect);
mSpatializerHelper.setFeatureEnabled(mHasSpatializerEffect);
}
- /**
- * post a message to persist the spatial audio device settings.
- * Message is delayed by 1s on purpose in case of successive changes in quick succession (at
- * init time for instance)
- * Note this method is made public to work around a Mockito bug where it needs to be public
- * in order to be mocked by a test a the same package
- * (see https://code.google.com/archive/p/mockito/issues/127)
- */
- public void persistSpatialAudioDeviceSettings() {
- sendMsg(mAudioHandler,
- MSG_PERSIST_SPATIAL_AUDIO_DEVICE_SETTINGS,
- SENDMSG_REPLACE, /*arg1*/ 0, /*arg2*/ 0, TAG,
- /*delay*/ 1000);
- }
-
- void onPersistSpatialAudioDeviceSettings() {
- final String settings = mSpatializerHelper.getSADeviceSettings();
- Log.v(TAG, "saving spatial audio device settings: " + settings);
- boolean res = mSettings.putSecureStringForUser(mContentResolver,
- Settings.Secure.SPATIAL_AUDIO_ENABLED,
- settings, UserHandle.USER_CURRENT);
- if (!res) {
- Log.e(TAG, "error saving spatial audio device settings: " + settings);
- }
- }
-
//==========================================================================================
// camera sound is forced if any of the resources corresponding to one active SIM
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 462c938..969dd60 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -16,6 +16,8 @@
package com.android.server.audio;
+import static android.media.AudioSystem.isBluetoothDevice;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -47,13 +49,13 @@
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.utils.EventLogger;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
-import java.util.Objects;
import java.util.UUID;
/**
@@ -73,11 +75,12 @@
private final @NonNull AudioSystemAdapter mASA;
private final @NonNull AudioService mAudioService;
+ private final @NonNull AudioDeviceBroker mDeviceBroker;
private @Nullable SensorManager mSensorManager;
//------------------------------------------------------------
- private static final SparseIntArray SPAT_MODE_FOR_DEVICE_TYPE = new SparseIntArray(14) {
+ /*package*/ static final SparseIntArray SPAT_MODE_FOR_DEVICE_TYPE = new SparseIntArray(14) {
{
append(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, SpatializationMode.SPATIALIZER_TRANSAURAL);
append(AudioDeviceInfo.TYPE_WIRED_HEADSET, SpatializationMode.SPATIALIZER_BINAURAL);
@@ -98,13 +101,6 @@
}
};
- private static final int[] WIRELESS_TYPES = { AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
- AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
- AudioDeviceInfo.TYPE_BLE_HEADSET,
- AudioDeviceInfo.TYPE_BLE_SPEAKER,
- AudioDeviceInfo.TYPE_BLE_BROADCAST
- };
-
// Spatializer state machine
/*package*/ static final int STATE_UNINITIALIZED = 0;
/*package*/ static final int STATE_NOT_SUPPORTED = 1;
@@ -114,10 +110,15 @@
/*package*/ static final int STATE_DISABLED_AVAILABLE = 6;
private int mState = STATE_UNINITIALIZED;
+ @VisibleForTesting boolean mBinauralEnabledDefault;
+ @VisibleForTesting boolean mTransauralEnabledDefault;
+ @VisibleForTesting boolean mHeadTrackingEnabledDefault;
+
private boolean mFeatureEnabled = false;
/** current level as reported by native Spatializer in callback */
private int mSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
private int mCapableSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
+
private boolean mTransauralSupported = false;
private boolean mBinauralSupported = false;
private boolean mIsHeadTrackingSupported = false;
@@ -160,31 +161,21 @@
*/
private final ArrayList<Integer> mSACapableDeviceTypes = new ArrayList<>(0);
- /**
- * List of devices where Spatial Audio is possible. Each device can be enabled or disabled
- * (== user choice to use or not)
- */
- @GuardedBy("this")
- private final ArrayList<SADeviceState> mSADevices = new ArrayList<>(0);
-
//------------------------------------------------------
// initialization
- @SuppressWarnings("StaticAssignmentInConstructor")
SpatializerHelper(@NonNull AudioService mother, @NonNull AudioSystemAdapter asa,
- boolean binauralEnabledDefault,
- boolean transauralEnabledDefault,
- boolean headTrackingEnabledDefault) {
+ @NonNull AudioDeviceBroker deviceBroker, boolean binauralEnabledDefault,
+ boolean transauralEnabledDefault, boolean headTrackingEnabledDefault) {
mAudioService = mother;
mASA = asa;
- // "StaticAssignmentInConstructor" warning is suppressed as the SpatializerHelper being
- // constructed here is the factory for SADeviceState, thus SADeviceState and its
- // private static field sHeadTrackingEnabledDefault should never be accessed directly.
- SADeviceState.sBinauralEnabledDefault = binauralEnabledDefault;
- SADeviceState.sTransauralEnabledDefault = transauralEnabledDefault;
- SADeviceState.sHeadTrackingEnabledDefault = headTrackingEnabledDefault;
+ mDeviceBroker = deviceBroker;
+
+ mBinauralEnabledDefault = binauralEnabledDefault;
+ mTransauralEnabledDefault = transauralEnabledDefault;
+ mHeadTrackingEnabledDefault = headTrackingEnabledDefault;
}
- synchronized void init(boolean effectExpected, @Nullable String settings) {
+ synchronized void init(boolean effectExpected) {
loglogi("init effectExpected=" + effectExpected);
if (!effectExpected) {
loglogi("init(): setting state to STATE_NOT_SUPPORTED due to effect not expected");
@@ -288,10 +279,11 @@
}
}
- // When initialized from AudioService, the settings string will be non-null.
- // Saved settings need to be applied after spatialization support is initialized above.
- if (settings != null) {
- setSADeviceSettings(settings);
+ // Log the saved device states that are compatible with SA
+ for (AdiDeviceState deviceState : mDeviceBroker.getImmutableDeviceInventory()) {
+ if (isSADevice(deviceState)) {
+ logDeviceState(deviceState, "setSADeviceSettings");
+ }
}
// for both transaural / binaural, we are not forcing enablement as the init() method
@@ -331,7 +323,7 @@
mState = STATE_UNINITIALIZED;
mSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
mActualHeadTrackingMode = Spatializer.HEAD_TRACKING_MODE_UNSUPPORTED;
- init(true, null /* settings */);
+ init(/*effectExpected=*/true);
setSpatializerEnabledInt(featureEnabled);
}
@@ -372,7 +364,7 @@
final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
// is media routed to a new device?
- if (isWireless(currentDevice.getType())) {
+ if (isBluetoothDevice(currentDevice.getInternalType())) {
addWirelessDeviceIfNew(currentDevice);
}
@@ -520,8 +512,8 @@
synchronized @NonNull List<AudioDeviceAttributes> getCompatibleAudioDevices() {
// build unionOf(mCompatibleAudioDevices, mEnabledDevice) - mDisabledAudioDevices
ArrayList<AudioDeviceAttributes> compatList = new ArrayList<>();
- for (SADeviceState deviceState : mSADevices) {
- if (deviceState.mEnabled) {
+ for (AdiDeviceState deviceState : mDeviceBroker.getImmutableDeviceInventory()) {
+ if (deviceState.isSAEnabled() && isSADevice(deviceState)) {
compatList.add(deviceState.getAudioDeviceAttributes());
}
}
@@ -548,31 +540,50 @@
return;
}
loglogi("addCompatibleAudioDevice: dev=" + ada);
- final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
- SADeviceState deviceUpdated = null; // non-null on update.
+ final AdiDeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
+ initSAState(deviceState);
+ AdiDeviceState updatedDevice = null; // non-null on update.
if (deviceState != null) {
- if (forceEnable && !deviceState.mEnabled) {
- deviceUpdated = deviceState;
- deviceUpdated.mEnabled = true;
+ if (forceEnable && !deviceState.isSAEnabled()) {
+ updatedDevice = deviceState;
+ updatedDevice.setSAEnabled(true);
}
} else {
// When adding, force the device type to be a canonical one.
- final int canonicalDeviceType = getCanonicalDeviceType(ada.getType());
+ final int canonicalDeviceType = getCanonicalDeviceType(ada.getType(),
+ ada.getInternalType());
if (canonicalDeviceType == AudioDeviceInfo.TYPE_UNKNOWN) {
Log.e(TAG, "addCompatibleAudioDevice with incompatible AudioDeviceAttributes "
+ ada);
return;
}
- deviceUpdated = new SADeviceState(canonicalDeviceType, ada.getAddress());
- mSADevices.add(deviceUpdated);
+ updatedDevice = new AdiDeviceState(canonicalDeviceType, ada.getInternalType(),
+ ada.getAddress());
+ initSAState(updatedDevice);
+ mDeviceBroker.addDeviceStateToInventory(updatedDevice);
}
- if (deviceUpdated != null) {
+ if (updatedDevice != null) {
onRoutingUpdated();
- mAudioService.persistSpatialAudioDeviceSettings();
- logDeviceState(deviceUpdated, "addCompatibleAudioDevice");
+ mDeviceBroker.persistAudioDeviceSettings();
+ logDeviceState(updatedDevice, "addCompatibleAudioDevice");
}
}
+ private void initSAState(AdiDeviceState device) {
+ if (device == null) {
+ return;
+ }
+
+ int spatMode = SPAT_MODE_FOR_DEVICE_TYPE.get(device.getDeviceType(),
+ Integer.MIN_VALUE);
+ device.setSAEnabled(spatMode == SpatializationMode.SPATIALIZER_BINAURAL
+ ? mBinauralEnabledDefault
+ : spatMode == SpatializationMode.SPATIALIZER_TRANSAURAL
+ ? mTransauralEnabledDefault
+ : false);
+ device.setHeadTrackerEnabled(mHeadTrackingEnabledDefault);
+ }
+
private static final String METRICS_DEVICE_PREFIX = "audio.spatializer.device.";
// Device logging is accomplished in the Java Audio Service level.
@@ -580,29 +591,30 @@
//
// There may be different devices with the same device type (aliasing).
// We always send the full device state info on each change.
- private void logDeviceState(SADeviceState deviceState, String event) {
+ static void logDeviceState(AdiDeviceState deviceState, String event) {
final int deviceType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(
- deviceState.mDeviceType);
+ deviceState.getDeviceType());
final String deviceName = AudioSystem.getDeviceName(deviceType);
new MediaMetrics.Item(METRICS_DEVICE_PREFIX + deviceName)
- .set(MediaMetrics.Property.ADDRESS, deviceState.mDeviceAddress)
- .set(MediaMetrics.Property.ENABLED, deviceState.mEnabled ? "true" : "false")
- .set(MediaMetrics.Property.EVENT, TextUtils.emptyIfNull(event))
- .set(MediaMetrics.Property.HAS_HEAD_TRACKER,
- deviceState.mHasHeadTracker ? "true" : "false") // this may be updated later.
- .set(MediaMetrics.Property.HEAD_TRACKER_ENABLED,
- deviceState.mHeadTrackerEnabled ? "true" : "false")
- .record();
+ .set(MediaMetrics.Property.ADDRESS, deviceState.getDeviceAddress())
+ .set(MediaMetrics.Property.ENABLED, deviceState.isSAEnabled() ? "true" : "false")
+ .set(MediaMetrics.Property.EVENT, TextUtils.emptyIfNull(event))
+ .set(MediaMetrics.Property.HAS_HEAD_TRACKER,
+ deviceState.hasHeadTracker() ? "true"
+ : "false") // this may be updated later.
+ .set(MediaMetrics.Property.HEAD_TRACKER_ENABLED,
+ deviceState.isHeadTrackerEnabled() ? "true" : "false")
+ .record();
}
synchronized void removeCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) {
loglogi("removeCompatibleAudioDevice: dev=" + ada);
- final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
- if (deviceState != null && deviceState.mEnabled) {
- deviceState.mEnabled = false;
+ final AdiDeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
+ if (deviceState != null && deviceState.isSAEnabled()) {
+ deviceState.setSAEnabled(false);
onRoutingUpdated();
- mAudioService.persistSpatialAudioDeviceSettings();
+ mDeviceBroker.persistAudioDeviceSettings();
logDeviceState(deviceState, "removeCompatibleAudioDevice");
}
}
@@ -611,8 +623,9 @@
* Returns a possibly aliased device type which is used
* for spatial audio settings (or TYPE_UNKNOWN if it doesn't exist).
*/
- private static @AudioDeviceInfo.AudioDeviceType int getCanonicalDeviceType(int deviceType) {
- if (isWireless(deviceType)) return deviceType;
+ @AudioDeviceInfo.AudioDeviceType
+ private static int getCanonicalDeviceType(int deviceType, int internalDeviceType) {
+ if (isBluetoothDevice(internalDeviceType)) return deviceType;
final int spatMode = SPAT_MODE_FOR_DEVICE_TYPE.get(deviceType, Integer.MIN_VALUE);
if (spatMode == SpatializationMode.SPATIALIZER_TRANSAURAL) {
@@ -629,18 +642,9 @@
*/
@GuardedBy("this")
@Nullable
- private SADeviceState findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada) {
- final int deviceType = ada.getType();
- final boolean isWireless = isWireless(deviceType);
- final int canonicalDeviceType = getCanonicalDeviceType(deviceType);
-
- for (SADeviceState deviceState : mSADevices) {
- if (deviceState.mDeviceType == canonicalDeviceType
- && (!isWireless || ada.getAddress().equals(deviceState.mDeviceAddress))) {
- return deviceState;
- }
- }
- return null;
+ private AdiDeviceState findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada) {
+ return mDeviceBroker.findDeviceStateForAudioDeviceAttributes(ada,
+ getCanonicalDeviceType(ada.getType(), ada.getInternalType()));
}
/**
@@ -662,14 +666,14 @@
Log.e(TAG, "no spatialization mode found for device type:" + deviceType);
return new Pair<>(false, false);
}
- final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
+ final AdiDeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
if (deviceState == null) {
// no matching device state?
Log.i(TAG, "no spatialization device state found for Spatial Audio device:" + ada);
return new Pair<>(false, false);
}
// found the matching device state.
- return new Pair<>(deviceState.mEnabled, true /* available */);
+ return new Pair<>(deviceState.isSAEnabled(), true /* available */);
}
private synchronized void addWirelessDeviceIfNew(@NonNull AudioDeviceAttributes ada) {
@@ -678,16 +682,19 @@
}
if (findDeviceStateForAudioDeviceAttributes(ada) == null) {
// wireless device types should be canonical, but we translate to be sure.
- final int canonicalDeviceType = getCanonicalDeviceType((ada.getType()));
+ final int canonicalDeviceType = getCanonicalDeviceType(ada.getType(),
+ ada.getInternalType());
if (canonicalDeviceType == AudioDeviceInfo.TYPE_UNKNOWN) {
Log.e(TAG, "addWirelessDeviceIfNew with incompatible AudioDeviceAttributes "
+ ada);
return;
}
- final SADeviceState deviceState =
- new SADeviceState(canonicalDeviceType, ada.getAddress());
- mSADevices.add(deviceState);
- mAudioService.persistSpatialAudioDeviceSettings();
+ final AdiDeviceState deviceState =
+ new AdiDeviceState(canonicalDeviceType, ada.getInternalType(),
+ ada.getAddress());
+ initSAState(deviceState);
+ mDeviceBroker.addDeviceStateToInventory(deviceState);
+ mDeviceBroker.persistAudioDeviceSettings();
logDeviceState(deviceState, "addWirelessDeviceIfNew"); // may be updated later.
}
}
@@ -756,6 +763,12 @@
return false;
}
+ private boolean isSADevice(AdiDeviceState deviceState) {
+ return deviceState.getDeviceType() == getCanonicalDeviceType(deviceState.getDeviceType(),
+ deviceState.getInternalDeviceType()) && isDeviceCompatibleWithSpatializationModes(
+ deviceState.getAudioDeviceAttributes());
+ }
+
synchronized void setFeatureEnabled(boolean enabled) {
loglogi("setFeatureEnabled(" + enabled + ") was featureEnabled:" + mFeatureEnabled);
if (mFeatureEnabled == enabled) {
@@ -768,7 +781,7 @@
return;
}
if (mState == STATE_UNINITIALIZED) {
- init(true, null /* settings */);
+ init(true);
}
setSpatializerEnabledInt(true);
} else {
@@ -1137,16 +1150,16 @@
Log.v(TAG, "no headtracking support, ignoring setHeadTrackerEnabled to " + enabled
+ " for " + ada);
}
- final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
+ final AdiDeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
if (deviceState == null) return;
- if (!deviceState.mHasHeadTracker) {
+ if (!deviceState.hasHeadTracker()) {
Log.e(TAG, "Called setHeadTrackerEnabled enabled:" + enabled
+ " device:" + ada + " on a device without headtracker");
return;
}
Log.i(TAG, "setHeadTrackerEnabled enabled:" + enabled + " device:" + ada);
- deviceState.mHeadTrackerEnabled = enabled;
- mAudioService.persistSpatialAudioDeviceSettings();
+ deviceState.setHeadTrackerEnabled(enabled);
+ mDeviceBroker.persistAudioDeviceSettings();
logDeviceState(deviceState, "setHeadTrackerEnabled");
// check current routing to see if it affects the headtracking mode
@@ -1170,8 +1183,8 @@
Log.v(TAG, "no headtracking support, hasHeadTracker always false for " + ada);
return false;
}
- final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
- return deviceState != null && deviceState.mHasHeadTracker;
+ final AdiDeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
+ return deviceState != null && deviceState.hasHeadTracker();
}
/**
@@ -1184,14 +1197,14 @@
Log.v(TAG, "no headtracking support, setHasHeadTracker always false for " + ada);
return false;
}
- final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
+ final AdiDeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
if (deviceState != null) {
- if (!deviceState.mHasHeadTracker) {
- deviceState.mHasHeadTracker = true;
- mAudioService.persistSpatialAudioDeviceSettings();
+ if (!deviceState.hasHeadTracker()) {
+ deviceState.setHasHeadTracker(true);
+ mDeviceBroker.persistAudioDeviceSettings();
logDeviceState(deviceState, "setHasHeadTracker");
}
- return deviceState.mHeadTrackerEnabled;
+ return deviceState.isHeadTrackerEnabled();
}
Log.e(TAG, "setHasHeadTracker: device not found for:" + ada);
return false;
@@ -1202,9 +1215,9 @@
Log.v(TAG, "no headtracking support, isHeadTrackerEnabled always false for " + ada);
return false;
}
- final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
+ final AdiDeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
return deviceState != null
- && deviceState.mHasHeadTracker && deviceState.mHeadTrackerEnabled;
+ && deviceState.hasHeadTracker() && deviceState.isHeadTrackerEnabled();
}
synchronized boolean isHeadTrackerAvailable() {
@@ -1543,144 +1556,6 @@
pw.println("\tsupports binaural:" + mBinauralSupported + " / transaural:"
+ mTransauralSupported);
pw.println("\tmSpatOutput:" + mSpatOutput);
- pw.println("\tdevices:");
- for (SADeviceState device : mSADevices) {
- pw.println("\t\t" + device);
- }
- }
-
- /*package*/ static final class SADeviceState {
- private static boolean sBinauralEnabledDefault = true;
- private static boolean sTransauralEnabledDefault = true;
- private static boolean sHeadTrackingEnabledDefault = false;
- final @AudioDeviceInfo.AudioDeviceType int mDeviceType;
- final @NonNull String mDeviceAddress;
- boolean mEnabled;
- boolean mHasHeadTracker = false;
- boolean mHeadTrackerEnabled;
- static final String SETTING_FIELD_SEPARATOR = ",";
- static final String SETTING_DEVICE_SEPARATOR_CHAR = "|";
- static final String SETTING_DEVICE_SEPARATOR = "\\|";
-
- /**
- * Constructor
- * @param deviceType
- * @param address must be non-null for wireless devices
- * @throws NullPointerException if a null address is passed for a wireless device
- */
- SADeviceState(@AudioDeviceInfo.AudioDeviceType int deviceType, @Nullable String address) {
- mDeviceType = deviceType;
- mDeviceAddress = isWireless(deviceType) ? Objects.requireNonNull(address) : "";
- final int spatMode = SPAT_MODE_FOR_DEVICE_TYPE.get(deviceType, Integer.MIN_VALUE);
- mEnabled = spatMode == SpatializationMode.SPATIALIZER_BINAURAL
- ? sBinauralEnabledDefault
- : spatMode == SpatializationMode.SPATIALIZER_TRANSAURAL
- ? sTransauralEnabledDefault
- : false;
- mHeadTrackerEnabled = sHeadTrackingEnabledDefault;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- // type check and cast
- if (getClass() != obj.getClass()) {
- return false;
- }
- final SADeviceState sads = (SADeviceState) obj;
- return mDeviceType == sads.mDeviceType
- && mDeviceAddress.equals(sads.mDeviceAddress)
- && mEnabled == sads.mEnabled
- && mHasHeadTracker == sads.mHasHeadTracker
- && mHeadTrackerEnabled == sads.mHeadTrackerEnabled;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mDeviceType, mDeviceAddress, mEnabled, mHasHeadTracker,
- mHeadTrackerEnabled);
- }
-
- @Override
- public String toString() {
- return "type: " + mDeviceType + " addr: " + mDeviceAddress + " enabled: " + mEnabled
- + " HT: " + mHasHeadTracker + " HTenabled: " + mHeadTrackerEnabled;
- }
-
- String toPersistableString() {
- return (new StringBuilder().append(mDeviceType)
- .append(SETTING_FIELD_SEPARATOR).append(mDeviceAddress)
- .append(SETTING_FIELD_SEPARATOR).append(mEnabled ? "1" : "0")
- .append(SETTING_FIELD_SEPARATOR).append(mHasHeadTracker ? "1" : "0")
- .append(SETTING_FIELD_SEPARATOR).append(mHeadTrackerEnabled ? "1" : "0")
- .toString());
- }
-
- static @Nullable SADeviceState fromPersistedString(@Nullable String persistedString) {
- if (persistedString == null) {
- return null;
- }
- if (persistedString.isEmpty()) {
- return null;
- }
- String[] fields = TextUtils.split(persistedString, SETTING_FIELD_SEPARATOR);
- if (fields.length != 5) {
- // expecting all fields, fewer may mean corruption, ignore those settings
- return null;
- }
- try {
- final int deviceType = Integer.parseInt(fields[0]);
- final SADeviceState deviceState = new SADeviceState(deviceType, fields[1]);
- deviceState.mEnabled = Integer.parseInt(fields[2]) == 1;
- deviceState.mHasHeadTracker = Integer.parseInt(fields[3]) == 1;
- deviceState.mHeadTrackerEnabled = Integer.parseInt(fields[4]) == 1;
- return deviceState;
- } catch (NumberFormatException e) {
- Log.e(TAG, "unable to parse setting for SADeviceState: " + persistedString, e);
- return null;
- }
- }
-
- public AudioDeviceAttributes getAudioDeviceAttributes() {
- return new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
- mDeviceType, mDeviceAddress == null ? "" : mDeviceAddress);
- }
-
- }
-
- /*package*/ synchronized String getSADeviceSettings() {
- // expected max size of each String for each SADeviceState is 25 (accounting for separator)
- final StringBuilder settingsBuilder = new StringBuilder(mSADevices.size() * 25);
- for (int i = 0; i < mSADevices.size(); i++) {
- settingsBuilder.append(mSADevices.get(i).toPersistableString());
- if (i != mSADevices.size() - 1) {
- settingsBuilder.append(SADeviceState.SETTING_DEVICE_SEPARATOR_CHAR);
- }
- }
- return settingsBuilder.toString();
- }
-
- /*package*/ synchronized void setSADeviceSettings(@NonNull String persistedSettings) {
- String[] devSettings = TextUtils.split(Objects.requireNonNull(persistedSettings),
- SADeviceState.SETTING_DEVICE_SEPARATOR);
- // small list, not worth overhead of Arrays.stream(devSettings)
- for (String setting : devSettings) {
- SADeviceState devState = SADeviceState.fromPersistedString(setting);
- // Note if the device is not compatible with spatialization mode
- // or the device type is not canonical, it is ignored.
- if (devState != null
- && devState.mDeviceType == getCanonicalDeviceType(devState.mDeviceType)
- && isDeviceCompatibleWithSpatializationModes(
- devState.getAudioDeviceAttributes())) {
- mSADevices.add(devState);
- logDeviceState(devState, "setSADeviceSettings");
- }
- }
}
private static String spatStateString(int state) {
@@ -1702,15 +1577,6 @@
}
}
- private static boolean isWireless(@AudioDeviceInfo.AudioDeviceType int deviceType) {
- for (int type : WIRELESS_TYPES) {
- if (type == deviceType) {
- return true;
- }
- }
- return false;
- }
-
private int getHeadSensorHandleUpdateTracker() {
int headHandle = -1;
if (sRoutingDevices.isEmpty()) {
@@ -1780,11 +1646,6 @@
//------------------------------------------------
// for testing purposes only
-
- /*package*/ void clearSADevices() {
- mSADevices.clear();
- }
-
/*package*/ synchronized void forceStateForTest(int state) {
mState = state;
}
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index f8f0088..3c885a1 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -53,6 +53,8 @@
import android.hardware.usb.UsbManager;
import android.media.AudioManager;
import android.nfc.INfcAdapter;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcManager;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerExecutor;
@@ -162,10 +164,6 @@
* SCALER_ROTATE_AND_CROP_NONE -> Always return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE
*/
- // Flags arguments to NFC adapter to enable/disable NFC
- public static final int DISABLE_POLLING_FLAGS = 0x1000;
- public static final int ENABLE_POLLING_FLAGS = 0x0000;
-
// Handler message codes
private static final int MSG_SWITCH_USER = 1;
private static final int MSG_NOTIFY_DEVICE_STATE = 2;
@@ -215,7 +213,6 @@
private final List<CameraUsageEvent> mCameraUsageHistory = new ArrayList<>();
private static final String NFC_NOTIFICATION_PROP = "ro.camera.notify_nfc";
- private static final String NFC_SERVICE_BINDER_NAME = "nfc";
private static final IBinder nfcInterfaceToken = new Binder();
private final boolean mNotifyNfc;
@@ -1255,8 +1252,13 @@
}
}
- private void notifyNfcService(boolean enablePolling) {
-
+ // TODO(b/303286040): Remove the raw INfcAdapter usage once |ENABLE_NFC_MAINLINE_FLAG| is
+ // rolled out.
+ private static final String NFC_SERVICE_BINDER_NAME = "nfc";
+ // Flags arguments to NFC adapter to enable/disable NFC
+ public static final int DISABLE_POLLING_FLAGS = 0x1000;
+ public static final int ENABLE_POLLING_FLAGS = 0x0000;
+ private void setNfcReaderModeUsingINfcAdapter(boolean enablePolling) {
IBinder nfcServiceBinder = getBinderService(NFC_SERVICE_BINDER_NAME);
if (nfcServiceBinder == null) {
Slog.w(TAG, "Could not connect to NFC service to notify it of camera state");
@@ -1272,6 +1274,25 @@
}
}
+ private void notifyNfcService(boolean enablePolling) {
+ if (android.nfc.Flags.enableNfcMainline()) {
+ NfcManager nfcManager = mContext.getSystemService(NfcManager.class);
+ if (nfcManager == null) {
+ Slog.w(TAG, "Could not connect to NFC service to notify it of camera state");
+ return;
+ }
+ NfcAdapter nfcAdapter = nfcManager.getDefaultAdapter();
+ if (nfcAdapter == null) {
+ Slog.w(TAG, "Could not connect to NFC service to notify it of camera state");
+ return;
+ }
+ if (DEBUG) Slog.v(TAG, "Setting NFC reader mode. enablePolling: " + enablePolling);
+ nfcAdapter.setReaderMode(enablePolling);
+ } else {
+ setNfcReaderModeUsingINfcAdapter(enablePolling);
+ }
+ }
+
private static int[] toArray(Collection<Integer> c) {
int len = c.size();
int[] ret = new int[len];
diff --git a/services/core/java/com/android/server/compat/overrides/OWNERS b/services/core/java/com/android/server/compat/overrides/OWNERS
index b80f340..6ca7803 100644
--- a/services/core/java/com/android/server/compat/overrides/OWNERS
+++ b/services/core/java/com/android/server/compat/overrides/OWNERS
@@ -1,2 +1,2 @@
-tomnatan@google.com
+mcarli@google.com
mariiasand@google.com
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 4ccc554..fa95a34 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -694,9 +694,9 @@
return;
}
- if (isUserKeyUnlocked(userId)) {
- // If storage is not locked, the user will be automatically unlocked so there is
- // no need to show the notification.
+ if (isCeStorageUnlocked(userId)) {
+ // If the user's CE storage is already unlocked, then the user will be automatically
+ // unlocked, so there is no need to show the notification.
return;
}
@@ -1027,8 +1027,8 @@
// they did have an SP then their CE key wasn't encrypted by it.
//
// If this gets interrupted (e.g. by the device powering off), there shouldn't be a
- // problem since this will run again on the next boot, and setUserKeyProtection() is
- // okay with the key being already protected by the given secret.
+ // problem since this will run again on the next boot, and setCeStorageProtection() is
+ // okay with the CE key being already protected by the given secret.
if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) {
for (UserInfo user : mUserManager.getAliveUsers()) {
removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber);
@@ -1063,7 +1063,7 @@
Slogf.wtf(TAG, "Failed to unwrap synthetic password for unsecured user %d", userId);
return;
}
- setUserKeyProtection(userId, result.syntheticPassword);
+ setCeStorageProtection(userId, result.syntheticPassword);
}
}
@@ -2002,11 +2002,11 @@
mStorage.writeChildProfileLock(profileUserId, ArrayUtils.concat(iv, ciphertext));
}
- private void setUserKeyProtection(@UserIdInt int userId, SyntheticPassword sp) {
+ private void setCeStorageProtection(@UserIdInt int userId, SyntheticPassword sp) {
final byte[] secret = sp.deriveFileBasedEncryptionKey();
final long callingId = Binder.clearCallingIdentity();
try {
- mStorageManager.setUserKeyProtection(userId, secret);
+ mStorageManager.setCeStorageProtection(userId, secret);
} catch (RemoteException e) {
throw new IllegalStateException("Failed to protect CE key for user " + userId, e);
} finally {
@@ -2014,11 +2014,11 @@
}
}
- private boolean isUserKeyUnlocked(int userId) {
+ private boolean isCeStorageUnlocked(int userId) {
try {
- return mStorageManager.isUserKeyUnlocked(userId);
+ return mStorageManager.isCeStorageUnlocked(userId);
} catch (RemoteException e) {
- Slog.e(TAG, "failed to check user key locked state", e);
+ Slog.e(TAG, "Error checking whether CE storage is unlocked", e);
return false;
}
}
@@ -2029,8 +2029,8 @@
* This method doesn't throw exceptions because it is called opportunistically whenever a user
* is started. Whether it worked or not can be detected by whether the key got unlocked or not.
*/
- private void unlockUserKey(@UserIdInt int userId, SyntheticPassword sp) {
- if (isUserKeyUnlocked(userId)) {
+ private void unlockCeStorage(@UserIdInt int userId, SyntheticPassword sp) {
+ if (isCeStorageUnlocked(userId)) {
Slogf.d(TAG, "CE storage for user %d is already unlocked", userId);
return;
}
@@ -2038,7 +2038,7 @@
final String userType = isUserSecure(userId) ? "secured" : "unsecured";
final byte[] secret = sp.deriveFileBasedEncryptionKey();
try {
- mStorageManager.unlockUserKey(userId, userInfo.serialNumber, secret);
+ mStorageManager.unlockCeStorage(userId, userInfo.serialNumber, secret);
Slogf.i(TAG, "Unlocked CE storage for %s user %d", userType, userId);
} catch (RemoteException e) {
Slogf.wtf(TAG, e, "Failed to unlock CE storage for %s user %d", userType, userId);
@@ -2051,8 +2051,10 @@
public void unlockUserKeyIfUnsecured(@UserIdInt int userId) {
checkPasswordReadPermission();
synchronized (mSpManager) {
- if (isUserKeyUnlocked(userId)) {
+ if (isCeStorageUnlocked(userId)) {
Slogf.d(TAG, "CE storage for user %d is already unlocked", userId);
+ // This method actually does more than unlock CE storage. However, if CE storage is
+ // already unlocked, then the other parts must have already been done too.
return;
}
if (isUserSecure(userId)) {
@@ -2069,7 +2071,7 @@
return;
}
onSyntheticPasswordUnlocked(userId, result.syntheticPassword);
- unlockUserKey(userId, result.syntheticPassword);
+ unlockCeStorage(userId, result.syntheticPassword);
}
}
@@ -2772,7 +2774,7 @@
final long protectorId = mSpManager.createLskfBasedProtector(getGateKeeperService(),
LockscreenCredential.createNone(), sp, userId);
setCurrentLskfBasedProtectorId(protectorId, userId);
- setUserKeyProtection(userId, sp);
+ setCeStorageProtection(userId, sp);
onSyntheticPasswordCreated(userId, sp);
Slogf.i(TAG, "Successfully initialized synthetic password for user %d", userId);
return sp;
@@ -2833,7 +2835,7 @@
unlockKeystore(userId, sp);
- unlockUserKey(userId, sp);
+ unlockCeStorage(userId, sp);
unlockUser(userId);
@@ -2897,7 +2899,7 @@
mSpManager.clearSidForUser(userId);
gateKeeperClearSecureUserId(userId);
- unlockUserKey(userId, sp);
+ unlockCeStorage(userId, sp);
unlockKeystore(userId, sp);
setKeystorePassword(null, userId);
removeBiometricsForUser(userId);
diff --git a/services/core/java/com/android/server/notification/OWNERS b/services/core/java/com/android/server/notification/OWNERS
index 6c4dd6d..9f16662 100644
--- a/services/core/java/com/android/server/notification/OWNERS
+++ b/services/core/java/com/android/server/notification/OWNERS
@@ -1,6 +1,9 @@
-# Bug component: 34005
+# Bug component: 78010
juliacr@google.com
yurilin@google.com
+aroederer@google.com
+matiashe@google.com
+valiiftime@google.com
jeffdq@google.com
dsandler@android.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 622cb66..8080e40 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -114,6 +114,7 @@
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.DataLoaderType;
+import android.content.pm.Flags;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageInstaller;
@@ -167,6 +168,7 @@
import com.android.server.EventLogTags;
import com.android.server.LocalManagerRegistry;
import com.android.server.SystemConfig;
+import com.android.server.art.model.ArtFlags;
import com.android.server.art.model.DexoptParams;
import com.android.server.art.model.DexoptResult;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
@@ -2534,8 +2536,15 @@
LocalManagerRegistry.getManager(PackageManagerLocal.class);
try (PackageManagerLocal.FilteredSnapshot snapshot =
packageManagerLocal.withFilteredSnapshot()) {
- DexoptParams params =
- dexoptOptions.convertToDexoptParams(0 /* extraFlags */);
+ boolean ignoreDexoptProfile =
+ (installRequest.getInstallFlags()
+ & PackageManager.INSTALL_IGNORE_DEXOPT_PROFILE)
+ != 0;
+ /*@DexoptFlags*/ int extraFlags =
+ ignoreDexoptProfile && Flags.useArtServiceV2()
+ ? ArtFlags.FLAG_IGNORE_PROFILE
+ : 0;
+ DexoptParams params = dexoptOptions.convertToDexoptParams(extraFlags);
DexoptResult dexOptResult = DexOptHelper.getArtManagerLocal().dexoptPackage(
snapshot, packageName, params);
installRequest.onDexoptFinished(dexOptResult);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 2327b85..3a84e15 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3368,6 +3368,9 @@
sessionParams.installFlags |=
PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
break;
+ case "--ignore-dexopt-profile":
+ sessionParams.installFlags |= PackageManager.INSTALL_IGNORE_DEXOPT_PROFILE;
+ break;
default:
throw new IllegalArgumentException("Unknown option " + opt);
}
@@ -4259,7 +4262,7 @@
pw.println(" [--enable-rollback]");
pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
pw.println(" [--apex] [--non-staged] [--force-non-staged]");
- pw.println(" [--staged-ready-timeout TIMEOUT]");
+ pw.println(" [--staged-ready-timeout TIMEOUT] [--ignore-dexopt-profile]");
pw.println(" [PATH [SPLIT...]|-]");
pw.println(" Install an application. Must provide the apk data to install, either as");
pw.println(" file path(s) or '-' to read from stdin. Options are:");
@@ -4299,6 +4302,13 @@
pw.println(" milliseconds for pre-reboot verification to complete when");
pw.println(" performing staged install. This flag is used to alter the waiting");
pw.println(" time. You can skip the waiting time by specifying a TIMEOUT of '0'");
+ pw.println(" --ignore-dexopt-profile: If set, all profiles are ignored by dexopt");
+ pw.println(" during the installation, including the profile in the DM file and");
+ pw.println(" the profile embedded in the APK file. If an invalid profile is");
+ pw.println(" provided during installation, no warning will be reported by `adb");
+ pw.println(" install`.");
+ pw.println(" This option does not affect later dexopt operations (e.g.,");
+ pw.println(" background dexopt and manual `pm compile` invocations).");
pw.println("");
pw.println(" install-existing [--user USER_ID|all|current]");
pw.println(" [--instant] [--full] [--wait] [--restrict-permissions] PACKAGE");
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 7e88e13..e5c19f5 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -4905,9 +4905,9 @@
}
}
- t.traceBegin("createUserKey");
+ t.traceBegin("createUserStorageKeys");
final StorageManager storage = mContext.getSystemService(StorageManager.class);
- storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral());
+ storage.createUserStorageKeys(userId, userInfo.serialNumber, userInfo.isEphemeral());
t.traceEnd();
// Only prepare DE storage here. CE storage will be prepared later, when the user is
@@ -5731,17 +5731,18 @@
private void removeUserState(final @UserIdInt int userId) {
Slog.i(LOG_TAG, "Removing user state of user " + userId);
- // Cleanup lock settings. This must happen before destroyUserKey(), since the user's DE
- // storage must still be accessible for the lock settings state to be properly cleaned up.
+ // Cleanup lock settings. This requires that the user's DE storage still be accessible, so
+ // this must happen before destroyUserStorageKeys().
mLockPatternUtils.removeUser(userId);
// Evict and destroy the user's CE and DE encryption keys. At this point, the user's CE and
// DE storage is made inaccessible, except to delete its contents.
try {
- mContext.getSystemService(StorageManager.class).destroyUserKey(userId);
+ mContext.getSystemService(StorageManager.class).destroyUserStorageKeys(userId);
} catch (IllegalStateException e) {
// This may be simply because the user was partially created.
- Slog.i(LOG_TAG, "Destroying key for user " + userId + " failed, continuing anyway", e);
+ Slog.i(LOG_TAG, "Destroying storage keys for user " + userId
+ + " failed, continuing anyway", e);
}
// Cleanup package manager settings
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index dccacb4..a3403bb 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -345,7 +345,7 @@
assertWithMessage("should not have received intents")
.that(getActions(mInjector.mSentIntents)).isEmpty();
// TODO(b/140868593): should have received a USER_UNLOCK_MSG message as well, but it doesn't
- // because StorageManager.isUserKeyUnlocked(TEST_PRE_CREATED_USER_ID) returns false - to
+ // because StorageManager.isCeStorageUnlocked(TEST_PRE_CREATED_USER_ID) returns false - to
// properly fix it, we'd need to move this class to FrameworksMockingServicesTests so we can
// mock static methods (but moving this class would involve changing the presubmit tests,
// and the cascade effect goes on...). In fact, a better approach would to not assert the
@@ -648,7 +648,7 @@
// checking.
waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
verify(mInjector.mStorageManagerMock, times(0))
- .lockUserKey(anyInt());
+ .lockCeStorage(anyInt());
addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1,
numerOfUserSwitches, true);
@@ -663,7 +663,7 @@
mUserController.finishUserStopped(ussUser1, /* allowDelayedLocking= */ true);
waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
verify(mInjector.mStorageManagerMock, times(1))
- .lockUserKey(TEST_USER_ID);
+ .lockCeStorage(TEST_USER_ID);
}
/**
@@ -757,7 +757,7 @@
mUserController.startUser(TEST_USER_ID, USER_START_MODE_BACKGROUND);
verify(mInjector.mStorageManagerMock, never())
- .unlockUserKey(eq(TEST_USER_ID), anyInt(), any());
+ .unlockCeStorage(eq(TEST_USER_ID), anyInt(), any());
}
@Test
@@ -1035,7 +1035,7 @@
mUserController.finishUserStopped(ussUser, delayedLocking);
waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS);
verify(mInjector.mStorageManagerMock, times(expectLocking ? 1 : 0))
- .lockUserKey(userId);
+ .lockCeStorage(userId);
}
private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId,
diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
index 31599ee..aba24fb 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
@@ -29,13 +29,14 @@
import android.content.Context;
import android.content.Intent;
import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.BluetoothProfileConnectionInfo;
import android.util.Log;
-import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
@@ -54,7 +55,6 @@
private static final String TAG = "AudioDeviceBrokerTest";
private static final int MAX_MESSAGE_HANDLING_DELAY_MS = 100;
- private Context mContext;
// the actual class under test
private AudioDeviceBroker mAudioDeviceBroker;
@@ -67,13 +67,13 @@
@Before
public void setUp() throws Exception {
- mContext = InstrumentationRegistry.getTargetContext();
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
mMockAudioService = mock(AudioService.class);
mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
mSpyDevInventory = spy(new AudioDeviceInventory(mSpyAudioSystem));
mSpySystemServer = spy(new NoOpSystemServerAdapter());
- mAudioDeviceBroker = new AudioDeviceBroker(mContext, mMockAudioService, mSpyDevInventory,
+ mAudioDeviceBroker = new AudioDeviceBroker(context, mMockAudioService, mSpyDevInventory,
mSpySystemServer, mSpyAudioSystem);
mSpyDevInventory.setDeviceBroker(mAudioDeviceBroker);
@@ -197,6 +197,37 @@
any(Intent.class));
}
+ /**
+ * Test that constructing an AdiDeviceState instance requires a non-null address for a
+ * wireless type, but can take null for a non-wireless type;
+ * @throws Exception
+ */
+ @Test
+ public void testAdiDeviceStateNullAddressCtor() throws Exception {
+ try {
+ new AdiDeviceState(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
+ AudioManager.DEVICE_OUT_SPEAKER, null);
+ new AdiDeviceState(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
+ AudioManager.DEVICE_OUT_BLUETOOTH_A2DP, null);
+ Assert.fail();
+ } catch (NullPointerException e) { }
+ }
+
+ @Test
+ public void testAdiDeviceStateStringSerialization() throws Exception {
+ Log.i(TAG, "starting testAdiDeviceStateStringSerialization");
+ final AdiDeviceState devState = new AdiDeviceState(
+ AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, AudioManager.DEVICE_OUT_SPEAKER, "bla");
+ devState.setHasHeadTracker(false);
+ devState.setHeadTrackerEnabled(false);
+ devState.setSAEnabled(true);
+ final String persistString = devState.toPersistableString();
+ final AdiDeviceState result = AdiDeviceState.fromPersistedString(persistString);
+ Log.i(TAG, "original:" + devState);
+ Log.i(TAG, "result :" + result);
+ Assert.assertEquals(devState, result);
+ }
+
private void doTestConnectionDisconnectionReconnection(int delayAfterDisconnection,
boolean mockMediaPlayback, boolean guaranteeSingleConnection) throws Exception {
when(mMockAudioService.getDeviceForStream(AudioManager.STREAM_MUSIC))
diff --git a/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
index 3ad24de..ad09ef0 100644
--- a/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
@@ -15,8 +15,6 @@
*/
package com.android.server.audio;
-import com.android.server.audio.SpatializerHelper.SADeviceState;
-
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doNothing;
@@ -26,12 +24,12 @@
import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
-import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioSystem;
import android.util.Log;
import androidx.test.filters.MediumTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Assert;
@@ -55,72 +53,25 @@
@Mock private AudioService mMockAudioService;
@Spy private AudioSystemAdapter mSpyAudioSystem;
- @Mock private AudioSystemAdapter mMockAudioSystem;
+ @Spy private AudioDeviceBroker mSpyDeviceBroker;
@Before
public void setUp() throws Exception {
mMockAudioService = mock(AudioService.class);
- }
- /**
- * Initializes mSpatHelper, the SpatizerHelper instance under test, to use the mock or spy
- * AudioSystemAdapter
- * @param useSpyAudioSystem true to use the spy adapter, mSpyAudioSystem, or false to use
- * the mock adapter, mMockAudioSystem.
- */
- private void setUpSpatHelper(boolean useSpyAudioSystem) {
- final AudioSystemAdapter asAdapter;
- if (useSpyAudioSystem) {
- mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
- asAdapter = mSpyAudioSystem;
- mMockAudioSystem = null;
- } else {
- mSpyAudioSystem = null;
- mMockAudioSystem = mock(NoOpAudioSystemAdapter.class);
- asAdapter = mMockAudioSystem;
- }
- mSpatHelper = new SpatializerHelper(mMockAudioService, asAdapter,
- true /*binauralEnabledDefault*/,
- true /*transauralEnabledDefault*/,
- false /*headTrackingEnabledDefault*/);
-
- }
-
- /**
- * Test that constructing an SADeviceState instance requires a non-null address for a
- * wireless type, but can take null for a non-wireless type;
- * @throws Exception
- */
- @Test
- public void testSADeviceStateNullAddressCtor() throws Exception {
- setUpSpatHelper(true /*useSpyAudioSystem*/);
- try {
- SADeviceState devState = new SADeviceState(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, null);
- devState = new SADeviceState(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, null);
- Assert.fail();
- } catch (NullPointerException e) { }
+ mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
+ mSpyDeviceBroker = spy(
+ new AudioDeviceBroker(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(),
+ mMockAudioService, mSpyAudioSystem));
+ mSpatHelper = new SpatializerHelper(mMockAudioService, mSpyAudioSystem,
+ mSpyDeviceBroker, /*binauralEnabledDefault=*/true, /*transauralEnabledDefault=*/
+ true, /*headTrackingEnabledDefault*/false);
}
@Test
- public void testSADeviceStateStringSerialization() throws Exception {
- Log.i(TAG, "starting testSADeviceStateStringSerialization");
- setUpSpatHelper(true /*useSpyAudioSystem*/);
- final SADeviceState devState = new SADeviceState(
- AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "bla");
- devState.mHasHeadTracker = false;
- devState.mHeadTrackerEnabled = false;
- devState.mEnabled = true;
- final String persistString = devState.toPersistableString();
- final SADeviceState result = SADeviceState.fromPersistedString(persistString);
- Log.i(TAG, "original:" + devState);
- Log.i(TAG, "result :" + result);
- Assert.assertEquals(devState, result);
- }
-
- @Test
- public void testSADeviceSettings() throws Exception {
+ public void testAdiDeviceStateSettings() throws Exception {
Log.i(TAG, "starting testSADeviceSettings");
- setUpSpatHelper(true /*useSpyAudioSystem*/);
final AudioDeviceAttributes dev1 =
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, "");
final AudioDeviceAttributes dev2 =
@@ -128,7 +79,7 @@
final AudioDeviceAttributes dev3 =
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "R2:D2:bloop");
- doNothing().when(mMockAudioService).persistSpatialAudioDeviceSettings();
+ doNothing().when(mSpyDeviceBroker).persistAudioDeviceSettings();
mSpatHelper.initForTest(true /*binaural*/, true /*transaural*/);
// test with single device
@@ -163,11 +114,11 @@
* the original one.
*/
private void checkAddSettings() throws Exception {
- String settings = mSpatHelper.getSADeviceSettings();
+ String settings = mSpyDeviceBroker.getDeviceSettings();
Log.i(TAG, "device settings: " + settings);
- mSpatHelper.clearSADevices();
- mSpatHelper.setSADeviceSettings(settings);
- String settingsRestored = mSpatHelper.getSADeviceSettings();
+ mSpyDeviceBroker.clearDeviceInventory();
+ mSpyDeviceBroker.setDeviceSettings(settings);
+ String settingsRestored = mSpyDeviceBroker.getDeviceSettings();
Log.i(TAG, "device settingsRestored: " + settingsRestored);
Assert.assertEquals(settings, settingsRestored);
}
@@ -179,7 +130,6 @@
@Test
public void testNoRoutingCanBeSpatialized() throws Exception {
Log.i(TAG, "Starting testNoRoutingCanBeSpatialized");
- setUpSpatHelper(false /*useSpyAudioSystem*/);
mSpatHelper.forceStateForTest(SpatializerHelper.STATE_ENABLED_AVAILABLE);
final ArrayList<AudioDeviceAttributes> emptyList = new ArrayList<>(0);
@@ -191,12 +141,12 @@
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1).build();
- when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean()))
+ when(mSpyAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean()))
.thenReturn(emptyList);
Assert.assertFalse("can be spatialized on empty routing",
mSpatHelper.canBeSpatialized(media, spatialFormat));
- when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean()))
+ when(mSpyAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean()))
.thenReturn(listWithNull);
Assert.assertFalse("can be spatialized on null routing",
mSpatHelper.canBeSpatialized(media, spatialFormat));
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index fe2ac17..f5d50d1 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -304,17 +304,17 @@
doAnswer(invocation -> {
Object[] args = invocation.getArguments();
- mStorageManager.unlockUserKey(/* userId= */ (int) args[0],
+ mStorageManager.unlockCeStorage(/* userId= */ (int) args[0],
/* secret= */ (byte[]) args[2]);
return null;
- }).when(sm).unlockUserKey(anyInt(), anyInt(), any());
+ }).when(sm).unlockCeStorage(anyInt(), anyInt(), any());
doAnswer(invocation -> {
Object[] args = invocation.getArguments();
- mStorageManager.setUserKeyProtection(/* userId= */ (int) args[0],
+ mStorageManager.setCeStorageProtection(/* userId= */ (int) args[0],
/* secret= */ (byte[]) args[1]);
return null;
- }).when(sm).setUserKeyProtection(anyInt(), any());
+ }).when(sm).setCeStorageProtection(anyInt(), any());
return sm;
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java b/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java
index 91f3fed..c08ad13 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java
@@ -24,7 +24,7 @@
private final ArrayMap<Integer, byte[]> mUserSecrets = new ArrayMap<>();
- public void setUserKeyProtection(int userId, byte[] secret) {
+ public void setCeStorageProtection(int userId, byte[] secret) {
assertThat(mUserSecrets).doesNotContainKey(userId);
mUserSecrets.put(userId, secret);
}
@@ -35,7 +35,7 @@
return secret;
}
- public void unlockUserKey(int userId, byte[] secret) {
+ public void unlockCeStorage(int userId, byte[] secret) {
assertThat(mUserSecrets.get(userId)).isEqualTo(secret);
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 749ed03..43dab53 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -8770,7 +8770,9 @@
* {@link android.net.ipsec.ike.SaProposal#DH_GROUP_NONE},
* {@link android.net.ipsec.ike.SaProposal#DH_GROUP_1024_BIT_MODP},
* {@link android.net.ipsec.ike.SaProposal#DH_GROUP_1536_BIT_MODP},
- * {@link android.net.ipsec.ike.SaProposal#DH_GROUP_2048_BIT_MODP}
+ * {@link android.net.ipsec.ike.SaProposal#DH_GROUP_2048_BIT_MODP},
+ * {@link android.net.ipsec.ike.SaProposal#DH_GROUP_3072_BIT_MODP},
+ * {@link android.net.ipsec.ike.SaProposal#DH_GROUP_4096_BIT_MODP}
*/
public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY =
KEY_PREFIX + "diffie_hellman_groups_int_array";
@@ -8838,7 +8840,8 @@
/**
* List of supported encryption algorithms for child session. Possible values are
- * {@link android.net.ipsec.ike.SaProposal#ENCRYPTION_ALGORITHM_AES_CBC}
+ * {@link android.net.ipsec.ike.SaProposal#ENCRYPTION_ALGORITHM_AES_CBC},
+ * {@link android.net.ipsec.ike.SaProposal#ENCRYPTION_ALGORITHM_AES_CTR}
*/
public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
KEY_PREFIX + "supported_child_session_encryption_algorithms_int_array";