Merge "Remove one duplicate comparison from OutputConfiguration#equals" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index f96a1de..f44f5fe 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -12,23 +12,36 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-aconfig_srcjars = [
- ":android.content.pm.flags-aconfig-java{.generated_srcjars}",
- ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}",
- ":android.net.vcn.flags-aconfig-java{.generated_srcjars}",
- ":android.nfc.flags-aconfig-java{.generated_srcjars}",
- ":android.os.flags-aconfig-java{.generated_srcjars}",
- ":android.security.flags-aconfig-java{.generated_srcjars}",
- ":com.android.hardware.camera2-aconfig-java{.generated_srcjars}",
- ":com.android.window.flags.window-aconfig-java{.generated_srcjars}",
- ":com.android.hardware.input-aconfig-java{.generated_srcjars}",
- ":com.android.text.flags-aconfig-java{.generated_srcjars}",
- ":com.android.net.flags-aconfig-java{.generated_srcjars}",
-]
+aconfig_declarations_group {
+ name: "framework-minus-apex-aconfig-declarations",
+ java_aconfig_libraries: [
+ // !!! KEEP THIS LIST ALPHABETICAL !!!
+ "aconfig_mediacodec_flags_java_lib",
+ "android.content.pm.flags-aconfig-java",
+ "android.content.res.flags-aconfig-java",
+ "android.crashrecovery.flags-aconfig-java",
+ "android.hardware.biometrics.flags-aconfig-java",
+ "android.media.codec-aconfig-java",
+ "android.media.playback.flags-aconfig-java",
+ "android.net.platform.flags-aconfig-java",
+ "android.net.vcn.flags-aconfig-java",
+ "android.nfc.flags-aconfig-java",
+ "android.os.flags-aconfig-java",
+ "android.security.flags-aconfig-java",
+ "com.android.hardware.camera2-aconfig-java",
+ "com.android.hardware.input-aconfig-java",
+ "com.android.net.thread.platform.flags-aconfig-java",
+ "com.android.text.flags-aconfig-java",
+ "com.android.window.flags.window-aconfig-java",
+ // !!! KEEP THIS LIST ALPHABETICAL !!!
+ ],
+}
filegroup {
name: "framework-minus-apex-aconfig-srcjars",
- srcs: aconfig_srcjars,
+ srcs: [
+ ":framework-minus-apex-aconfig-declarations{.srcjars}",
+ ],
}
// Aconfig declarations and libraries for the core framework
@@ -37,7 +50,9 @@
// Add java_aconfig_libraries to here to add them to the core framework
// Add aconfig-annotations-lib as a dependency for the optimization
- srcs: aconfig_srcjars,
+ srcs: [
+ ":framework-minus-apex-aconfig-declarations{.srcjars}",
+ ],
libs: ["aconfig-annotations-lib"],
}
@@ -118,7 +133,7 @@
aconfig_declarations {
name: "android.nfc.flags-aconfig",
package: "android.nfc",
- srcs: ["core/java/android/nfc/*.aconfig"],
+ srcs: ["nfc/java/android/nfc/*.aconfig"],
}
cc_aconfig_library {
@@ -136,7 +151,7 @@
java_aconfig_library {
name: "android.nfc.flags-aconfig-java",
aconfig_declarations: "android.nfc.flags-aconfig",
- min_sdk_version: "VanillaIceCream",
+ min_sdk_version: "34",
apex_available: [
"//apex_available:platform",
"com.android.nfcservices",
@@ -190,6 +205,19 @@
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+// Resources
+aconfig_declarations {
+ name: "android.content.res.flags-aconfig",
+ package: "android.content.res",
+ srcs: ["core/java/android/content/res/*.aconfig"],
+}
+
+java_aconfig_library {
+ name: "android.content.res.flags-aconfig-java",
+ aconfig_declarations: "android.content.res.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
// Biometrics
aconfig_declarations {
name: "android.hardware.biometrics.flags-aconfig",
@@ -205,14 +233,29 @@
// Networking
aconfig_declarations {
- name: "com.android.net.flags-aconfig",
- package: "com.android.net.flags",
+ name: "android.net.platform.flags-aconfig",
+ package: "android.net.platform.flags",
srcs: ["core/java/android/net/flags.aconfig"],
+ visibility: [":__subpackages__"],
+}
+
+// Thread network
+aconfig_declarations {
+ name: "com.android.net.thread.platform.flags-aconfig",
+ package: "com.android.net.thread.platform.flags",
+ srcs: ["core/java/android/net/thread/flags.aconfig"],
}
java_aconfig_library {
- name: "com.android.net.flags-aconfig-java",
- aconfig_declarations: "com.android.net.flags-aconfig",
+ name: "android.net.platform.flags-aconfig-java",
+ aconfig_declarations: "android.net.platform.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+ visibility: [":__subpackages__"],
+}
+
+java_aconfig_library {
+ name: "com.android.net.thread.platform.flags-aconfig-java",
+ aconfig_declarations: "com.android.net.thread.platform.flags-aconfig",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
@@ -246,3 +289,16 @@
aconfig_declarations: "android.net.vcn.flags-aconfig",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+
+// CrashRecovery Module
+aconfig_declarations {
+ name: "android.crashrecovery.flags-aconfig",
+ package: "android.crashrecovery.flags",
+ srcs: ["packages/CrashRecovery/aconfig/flags.aconfig"],
+}
+
+java_aconfig_library {
+ name: "android.crashrecovery.flags-aconfig-java",
+ aconfig_declarations: "android.crashrecovery.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/Android.bp b/Android.bp
index f5c0b6d..d4b63c4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -127,6 +127,7 @@
":libcamera_client_aidl",
":libcamera_client_framework_aidl",
":libupdate_engine_aidl",
+ ":libupdate_engine_stable-V2-java-source",
":logd_aidl",
":resourcemanager_aidl",
":storaged_aidl",
@@ -163,6 +164,9 @@
"//external/robolectric:__subpackages__",
"//frameworks/layoutlib:__subpackages__",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
// AIDL files under these paths are mixture of public and private ones.
@@ -204,6 +208,7 @@
"updatable-driver-protos",
"ota_metadata_proto_java",
"android.hidl.base-V1.0-java",
+ "android.hidl.manager-V1.2-java",
"android.hardware.cas-V1-java", // AIDL
"android.hardware.cas-V1.0-java",
"android.hardware.cas-V1.1-java",
@@ -257,6 +262,9 @@
],
sdk_version: "core_platform",
installable: false,
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
// NOTE: This filegroup is exposed for vendor libraries to depend on and is referenced in
@@ -419,10 +427,12 @@
name: "framework-non-updatable-unbundled-impl-libs",
static_libs: [
"framework-location.impl",
- "framework-nfc.impl",
],
sdk_version: "core_platform",
installable: false,
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
// Separated so framework-minus-apex-defaults can be used without the libs dependency
@@ -466,6 +476,9 @@
],
compile_dex: false,
headers_only: true,
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_library {
@@ -493,6 +506,10 @@
"-Xep:AndroidFrameworkUid:ERROR",
],
},
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
+ jarjar_prefix: "com.android.internal.hidden_from_bootclasspath",
}
java_library {
@@ -507,6 +524,7 @@
},
lint: {
enabled: false,
+ baseline_filename: "lint-baseline.xml",
},
}
@@ -531,6 +549,9 @@
],
sdk_version: "core_platform",
apex_available: ["//apex_available:platform"],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_library {
@@ -545,6 +566,9 @@
"calendar-provider-compat-config",
"contacts-provider-platform-compat-config",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
platform_compat_config {
@@ -592,6 +616,9 @@
"rappor",
],
dxflags: ["--core-library"],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
// utility classes statically linked into framework-wifi and dynamically linked
@@ -617,6 +644,10 @@
"//frameworks/base/services/net",
"//packages/modules/Wifi/framework",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
+ apex_available: ["com.android.wifi"],
}
filegroup {
diff --git a/INPUT_OWNERS b/INPUT_OWNERS
index 44b2f38..06ead06 100644
--- a/INPUT_OWNERS
+++ b/INPUT_OWNERS
@@ -1,4 +1,6 @@
# Bug component: 136048
+arpitks@google.com
+asmitapoddar@google.com
hcutts@google.com
joseprio@google.com
michaelwr@google.com
diff --git a/LSE_APP_COMPAT_OWNERS b/LSE_APP_COMPAT_OWNERS
new file mode 100644
index 0000000..3db0cd4
--- /dev/null
+++ b/LSE_APP_COMPAT_OWNERS
@@ -0,0 +1,6 @@
+# Owners for the App Compat flags (large_screen_experiences_app_compat)
+mcarli@google.com
+eevlachavas@google.com
+gracielawputri@google.com
+minagranic@google.com
+mariiasand@google.com
diff --git a/MEMORY_OWNERS b/MEMORY_OWNERS
new file mode 100644
index 0000000..89ce5140
--- /dev/null
+++ b/MEMORY_OWNERS
@@ -0,0 +1,6 @@
+surenb@google.com
+tjmercier@google.com
+kaleshsingh@google.com
+jyescas@google.com
+carlosgalo@google.com
+jji@google.com
diff --git a/OWNERS b/OWNERS
index 733157f..555bbfb 100644
--- a/OWNERS
+++ b/OWNERS
@@ -32,6 +32,7 @@
per-file TestProtoLibraries.bp = file:platform/platform_testing:/libraries/health/OWNERS
per-file TestProtoLibraries.bp = file:platform/tools/tradefederation:/OWNERS
+per-file INPUT_OWNERS = file:/INPUT_OWNERS
per-file ZYGOTE_OWNERS = file:/ZYGOTE_OWNERS
per-file SQLITE_OWNERS = file:/SQLITE_OWNERS
@@ -39,3 +40,5 @@
per-file *Ravenwood* = file:ravenwood/OWNERS
per-file PERFORMANCE_OWNERS = file:/PERFORMANCE_OWNERS
+
+per-file PACKAGE_MANAGER_OWNERS = file:/PACKAGE_MANAGER_OWNERS
diff --git a/PACKAGE_MANAGER_OWNERS b/PACKAGE_MANAGER_OWNERS
index e4549b4..eb5842b 100644
--- a/PACKAGE_MANAGER_OWNERS
+++ b/PACKAGE_MANAGER_OWNERS
@@ -1,3 +1,3 @@
-chiuwinson@google.com
+alexbuy@google.com
patb@google.com
schfan@google.com
\ No newline at end of file
diff --git a/SECURITY_STATE_OWNERS b/SECURITY_STATE_OWNERS
new file mode 100644
index 0000000..30ddfe2
--- /dev/null
+++ b/SECURITY_STATE_OWNERS
@@ -0,0 +1,5 @@
+alxu@google.com
+musashi@google.com
+maunik@google.com
+davidkwak@google.com
+willcoster@google.com
\ No newline at end of file
diff --git a/TEST_MAPPING b/TEST_MAPPING
index eef3d27..8338c33 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -125,6 +125,9 @@
},
{
"name": "vts_treble_vintf_vendor_test"
+ },
+ {
+ "name": "CtsStrictJavaPackagesTestCases"
}
],
"postsubmit-managedprofile-stress": [
diff --git a/WEAR_OWNERS b/WEAR_OWNERS
index 4f3bc27..4127f99 100644
--- a/WEAR_OWNERS
+++ b/WEAR_OWNERS
@@ -4,3 +4,9 @@
adsule@google.com
andriyn@google.com
yfz@google.com
+con@google.com
+leetodd@google.com
+sadrul@google.com
+rwmyers@google.com
+nalmalki@google.com
+shijianli@google.com
diff --git a/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt b/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
index aadbc23..add0a08 100644
--- a/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
+++ b/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
@@ -16,8 +16,6 @@
package android.input
-import android.content.Context
-import android.content.res.Resources
import android.os.SystemProperties
import android.perftests.utils.PerfStatusReporter
import android.view.InputDevice
@@ -38,8 +36,6 @@
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.`when`
import java.time.Duration
@@ -68,18 +64,6 @@
InputDevice.SOURCE_STYLUS, /*flags=*/0)
}
-private fun getPredictionContext(offset: Duration, enablePrediction: Boolean): Context {
- val context = mock(Context::class.java)
- val resources: Resources = mock(Resources::class.java)
- `when`(context.getResources()).thenReturn(resources)
- `when`(resources.getInteger(
- com.android.internal.R.integer.config_motionPredictionOffsetNanos)).thenReturn(
- offset.toNanos().toInt())
- `when`(resources.getBoolean(
- com.android.internal.R.bool.config_enableMotionPrediction)).thenReturn(enablePrediction)
- return context
-}
-
@RunWith(AndroidJUnit4::class)
@LargeTest
class MotionPredictorBenchmark {
@@ -115,7 +99,7 @@
var eventPosition = 0f
val positionInterval = 10f
- val predictor = MotionPredictor(getPredictionContext(offset, /*enablePrediction=*/true))
+ val predictor = MotionPredictor(/*isPredictionEnabled=*/true, offset.toNanos().toInt())
// ACTION_DOWN t=0 x=0 y=0
predictor.record(getStylusMotionEvent(
eventTime, ACTION_DOWN, /*x=*/eventPosition, /*y=*/eventPosition))
@@ -141,12 +125,11 @@
*/
@Test
fun timeCreatePredictor() {
- val context = getPredictionContext(
- /*offset=*/Duration.ofMillis(20), /*enablePrediction=*/true)
+ val offsetNanos = Duration.ofMillis(20).toNanos().toInt()
val state = perfStatusReporter.getBenchmarkState()
while (state.keepRunning()) {
- MotionPredictor(context)
+ MotionPredictor(/*isPredictionEnabled=*/true, offsetNanos)
}
}
}
diff --git a/api/Android.bp b/api/Android.bp
index 179113f..bc217f3 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -69,8 +69,40 @@
visibility: ["//visibility:public"],
}
+soong_config_module_type {
+ name: "enable_crashrecovery_module",
+ module_type: "combined_apis_defaults",
+ config_namespace: "ANDROID",
+ bool_variables: ["release_crashrecovery_module"],
+ properties: [
+ "bootclasspath",
+ "system_server_classpath",
+ ],
+}
+
+soong_config_bool_variable {
+ name: "release_crashrecovery_module",
+}
+
+enable_crashrecovery_module {
+ name: "crashrecovery_module_defaults",
+ soong_config_variables: {
+ release_crashrecovery_module: {
+ bootclasspath: [
+ "framework-crashrecovery",
+ ],
+ system_server_classpath: [
+ "service-crashrecovery",
+ ],
+ },
+ },
+}
+
combined_apis {
name: "frameworks-base-api",
+ defaults: [
+ "crashrecovery_module_defaults",
+ ],
bootclasspath: [
"android.net.ipsec.ike",
"art.module.public.api",
@@ -90,6 +122,7 @@
"framework-nfc",
"framework-ondevicepersonalization",
"framework-pdf",
+ "framework-pdf-v",
"framework-permission",
"framework-permission-s",
"framework-scheduling",
@@ -176,7 +209,7 @@
out: ["current.srcjar"],
cmd: "$(location merge_zips) $(out) $(in)",
srcs: [
- ":api-stubs-docs-non-updatable",
+ ":api-stubs-docs-non-updatable{.exportable}",
":all-modules-public-stubs-source",
],
visibility: ["//visibility:private"], // Used by make module in //development, mind
@@ -199,7 +232,7 @@
name: "sdk-annotations.zip",
defaults: ["sdk-annotations-defaults"],
srcs: [
- ":android-non-updatable-doc-stubs{.annotations.zip}",
+ ":android-non-updatable-doc-stubs{.exportable.annotations.zip}",
":all-modules-public-annotations",
],
}
@@ -208,7 +241,7 @@
name: "sdk-annotations-system.zip",
defaults: ["sdk-annotations-defaults"],
srcs: [
- ":android-non-updatable-doc-stubs-system{.annotations.zip}",
+ ":android-non-updatable-doc-stubs-system{.exportable.annotations.zip}",
":all-modules-system-annotations",
],
}
@@ -217,7 +250,7 @@
name: "sdk-annotations-module-lib.zip",
defaults: ["sdk-annotations-defaults"],
srcs: [
- ":android-non-updatable-doc-stubs-module-lib{.annotations.zip}",
+ ":android-non-updatable-doc-stubs-module-lib{.exportable.annotations.zip}",
":all-modules-module-lib-annotations",
],
}
@@ -226,7 +259,7 @@
name: "sdk-annotations-system-server.zip",
defaults: ["sdk-annotations-defaults"],
srcs: [
- ":android-non-updatable-doc-stubs-system-server{.annotations.zip}",
+ ":android-non-updatable-doc-stubs-system-server{.exportable.annotations.zip}",
":all-modules-system-server-annotations",
],
}
@@ -278,6 +311,7 @@
// classpath (or sources) somehow.
stubs_defaults {
name: "android-non-updatable-stubs-defaults",
+ aconfig_declarations: ["framework-minus-apex-aconfig-declarations"],
srcs: [":android-non-updatable-stub-sources"],
sdk_version: "none",
system_modules: "none",
@@ -318,10 +352,6 @@
"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",
@@ -345,7 +375,10 @@
previous_api: ":android.api.public.latest",
merge_annotations_dirs: ["metalava-manual"],
defaults_visibility: ["//frameworks/base/api"],
- visibility: ["//frameworks/base/api"],
+ visibility: [
+ "//frameworks/base/api",
+ "//frameworks/base/core/api",
+ ],
}
// We resolve dependencies on APIs in modules by depending on a prebuilt of the whole
@@ -462,3 +495,12 @@
targets: ["droid"],
},
}
+
+phony_rule {
+ name: "checkapi",
+ phony_deps: [
+ "frameworks-base-api-current-compat",
+ "frameworks-base-api-system-current-compat",
+ "frameworks-base-api-module-lib-current-compat",
+ ],
+}
diff --git a/api/Android.mk b/api/Android.mk
deleted file mode 100644
index ce5f995..0000000
--- a/api/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-.PHONY: checkapi
-checkapi: frameworks-base-api-current-compat frameworks-base-api-system-current-compat frameworks-base-api-module-lib-current-compat
diff --git a/api/ApiDocs.bp b/api/ApiDocs.bp
index 5744bdf..426ffdf 100644
--- a/api/ApiDocs.bp
+++ b/api/ApiDocs.bp
@@ -51,6 +51,7 @@
":framework-graphics-srcs",
":framework-mediaprovider-sources",
":framework-nearby-sources",
+ ":framework-nfc-updatable-sources",
":framework-ondevicepersonalization-sources",
":framework-permission-sources",
":framework-permission-s-sources",
@@ -171,6 +172,7 @@
"-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 101", // TODO: turn Lint 101 back into an error again
"-hide 111", // HIDDEN_SUPERCLASS
"-hide 113", // DEPRECATION_MISMATCH
"-hide 125", // REQUIRES_PERMISSION
@@ -206,7 +208,7 @@
name: "offline-sdk-docs",
defaults: ["framework-docs-default"],
srcs: [
- ":framework-doc-stubs",
+ ":framework-doc-stubs{.exportable}",
],
hdf: [
"android.whichdoc offline",
@@ -227,7 +229,7 @@
name: "offline-sdk-referenceonly-docs",
defaults: ["framework-docs-default"],
srcs: [
- ":framework-doc-stubs",
+ ":framework-doc-stubs{.exportable}",
],
hdf: [
"android.whichdoc offline",
@@ -271,7 +273,7 @@
name: "ds-docs-java",
defaults: ["framework-docs-default"],
srcs: [
- ":framework-doc-stubs",
+ ":framework-doc-stubs{.exportable}",
],
hdf: [
"android.whichdoc online",
@@ -305,7 +307,7 @@
droiddoc {
name: "ds-docs-kt",
srcs: [
- ":framework-doc-stubs",
+ ":framework-doc-stubs{.exportable}",
],
flags: [
"-noJdkLink",
@@ -359,7 +361,7 @@
name: "ds-static-docs",
defaults: ["framework-docs-default"],
srcs: [
- ":framework-doc-stubs",
+ ":framework-doc-stubs{.exportable}",
],
hdf: [
"android.whichdoc online",
@@ -376,7 +378,7 @@
name: "ds-ref-navtree-docs",
defaults: ["framework-docs-default"],
srcs: [
- ":framework-doc-stubs",
+ ":framework-doc-stubs{.exportable}",
],
hdf: [
"android.whichdoc online",
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp
index 28b2d4b..2edbd91 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -225,6 +225,7 @@
java_version: "1.8",
compile_dex: true,
visibility: ["//visibility:public"],
+ is_stubs_module: true,
}
java_defaults {
@@ -233,12 +234,17 @@
system_modules: "none",
java_version: "1.8",
compile_dex: true,
+ is_stubs_module: true,
}
java_defaults {
name: "android-non-updatable_from_source_defaults",
libs: ["stub-annotations"],
static_libs: ["framework-res-package-jar"], // Export package of framework-res
+}
+
+java_defaults {
+ name: "android-non-updatable_exportable_from_source_defaults",
dist: {
targets: ["sdk"],
tag: ".jar",
@@ -265,6 +271,14 @@
}
java_library {
+ name: "android-non-updatable.stubs.exportable",
+ defaults: ["android-non-updatable_defaults"],
+ static_libs: [
+ "android-non-updatable.stubs.exportable.from-source",
+ ],
+}
+
+java_library {
name: "android-non-updatable.stubs.system",
defaults: ["android-non-updatable_defaults"],
static_libs: [
@@ -283,6 +297,14 @@
}
java_library {
+ name: "android-non-updatable.stubs.exportable.system",
+ defaults: ["android-non-updatable_defaults"],
+ static_libs: [
+ "android-non-updatable.stubs.exportable.system.from-source",
+ ],
+}
+
+java_library {
name: "android-non-updatable.stubs.module_lib",
defaults: ["android-non-updatable_defaults"],
static_libs: [
@@ -301,6 +323,14 @@
}
java_library {
+ name: "android-non-updatable.stubs.exportable.module_lib",
+ defaults: ["android-non-updatable_defaults"],
+ static_libs: [
+ "android-non-updatable.stubs.exportable.module_lib.from-source",
+ ],
+}
+
+java_library {
name: "android-non-updatable.stubs.test",
defaults: ["android-non-updatable_defaults"],
static_libs: [
@@ -319,6 +349,14 @@
}
java_library {
+ name: "android-non-updatable.stubs.exportable.test",
+ defaults: ["android-non-updatable_defaults"],
+ static_libs: [
+ "android-non-updatable.stubs.exportable.test.from-source",
+ ],
+}
+
+java_library {
name: "android-non-updatable.stubs.from-source",
defaults: [
"android-non-updatable_defaults",
@@ -326,6 +364,17 @@
],
srcs: [":api-stubs-docs-non-updatable"],
libs: ["all-modules-public-stubs"],
+}
+
+java_library {
+ name: "android-non-updatable.stubs.exportable.from-source",
+ defaults: [
+ "android-non-updatable_defaults",
+ "android-non-updatable_from_source_defaults",
+ "android-non-updatable_exportable_from_source_defaults",
+ ],
+ srcs: [":api-stubs-docs-non-updatable{.exportable}"],
+ libs: ["all-modules-public-stubs"],
dist: {
dir: "apistubs/android/public",
},
@@ -339,6 +388,17 @@
],
srcs: [":system-api-stubs-docs-non-updatable"],
libs: ["all-modules-system-stubs"],
+}
+
+java_library {
+ name: "android-non-updatable.stubs.exportable.system.from-source",
+ defaults: [
+ "android-non-updatable_defaults",
+ "android-non-updatable_from_source_defaults",
+ "android-non-updatable_exportable_from_source_defaults",
+ ],
+ srcs: [":system-api-stubs-docs-non-updatable{.exportable}"],
+ libs: ["all-modules-system-stubs"],
dist: {
dir: "apistubs/android/system",
},
@@ -352,6 +412,17 @@
],
srcs: [":module-lib-api-stubs-docs-non-updatable"],
libs: non_updatable_api_deps_on_modules,
+}
+
+java_library {
+ name: "android-non-updatable.stubs.exportable.module_lib.from-source",
+ defaults: [
+ "android-non-updatable_defaults",
+ "android-non-updatable_from_source_defaults",
+ "android-non-updatable_exportable_from_source_defaults",
+ ],
+ srcs: [":module-lib-api-stubs-docs-non-updatable{.exportable}"],
+ libs: non_updatable_api_deps_on_modules,
dist: {
dir: "apistubs/android/module-lib",
},
@@ -365,6 +436,17 @@
],
srcs: [":test-api-stubs-docs-non-updatable"],
libs: ["all-modules-system-stubs"],
+}
+
+java_library {
+ name: "android-non-updatable.stubs.exportable.test.from-source",
+ defaults: [
+ "android-non-updatable_defaults",
+ "android-non-updatable_from_source_defaults",
+ "android-non-updatable_exportable_from_source_defaults",
+ ],
+ srcs: [":test-api-stubs-docs-non-updatable{.exportable}"],
+ libs: ["all-modules-system-stubs"],
dist: {
dir: "apistubs/android/test",
},
@@ -462,6 +544,16 @@
}
java_library {
+ name: "android_stubs_current_exportable.from-source",
+ static_libs: [
+ "all-modules-public-stubs-exportable",
+ "android-non-updatable.stubs.exportable",
+ "private-stub-annotations-jar",
+ ],
+ defaults: ["android.jar_defaults"],
+}
+
+java_library {
name: "android_system_stubs_current.from-source",
static_libs: [
"all-modules-system-stubs",
@@ -470,6 +562,19 @@
],
defaults: [
"android.jar_defaults",
+ ],
+ visibility: ["//frameworks/base/services"],
+}
+
+java_library {
+ name: "android_system_stubs_current_exportable.from-source",
+ static_libs: [
+ "all-modules-system-stubs-exportable",
+ "android-non-updatable.stubs.exportable.system",
+ "private-stub-annotations-jar",
+ ],
+ defaults: [
+ "android.jar_defaults",
"android_stubs_dists_default",
],
dist: {
@@ -498,6 +603,23 @@
],
defaults: [
"android.jar_defaults",
+ ],
+ visibility: ["//frameworks/base/services"],
+}
+
+java_library {
+ name: "android_test_stubs_current_exportable.from-source",
+ static_libs: [
+ // Updatable modules do not have test APIs, but we want to include their SystemApis, like we
+ // include the SystemApi of framework-non-updatable-sources.
+ "all-updatable-modules-system-stubs-exportable",
+ // Non-updatable modules on the other hand can have test APIs, so include their test-stubs.
+ "all-non-updatable-modules-test-stubs-exportable",
+ "android-non-updatable.stubs.exportable.test",
+ "private-stub-annotations-jar",
+ ],
+ defaults: [
+ "android.jar_defaults",
"android_stubs_dists_default",
],
dist: {
@@ -505,6 +627,7 @@
},
}
+// This module does not need to be copied to dist
java_library {
name: "android_test_frameworks_core_stubs_current.from-source",
static_libs: [
@@ -513,24 +636,34 @@
],
defaults: [
"android.jar_defaults",
- "android_stubs_dists_default",
],
- dist: {
- dir: "apistubs/android/test-core",
- },
+ visibility: ["//frameworks/base/services"],
}
java_library {
name: "android_module_lib_stubs_current.from-source",
defaults: [
"android.jar_defaults",
- "android_stubs_dists_default",
],
static_libs: [
"android-non-updatable.stubs.module_lib",
"art.module.public.api.stubs.module_lib",
"i18n.module.public.api.stubs",
],
+ visibility: ["//frameworks/base/services"],
+}
+
+java_library {
+ name: "android_module_lib_stubs_current_exportable.from-source",
+ defaults: [
+ "android.jar_defaults",
+ "android_stubs_dists_default",
+ ],
+ static_libs: [
+ "android-non-updatable.stubs.exportable.module_lib",
+ "art.module.public.api.stubs.exportable.module_lib",
+ "i18n.module.public.api.stubs.exportable",
+ ],
dist: {
dir: "apistubs/android/module-lib",
},
@@ -540,13 +673,26 @@
name: "android_system_server_stubs_current.from-source",
defaults: [
"android.jar_defaults",
- "android_stubs_dists_default",
],
srcs: [":services-non-updatable-stubs"],
installable: false,
static_libs: [
"android_module_lib_stubs_current.from-source",
],
+ visibility: ["//frameworks/base/services"],
+}
+
+java_library {
+ name: "android_system_server_stubs_current_exportable.from-source",
+ defaults: [
+ "android.jar_defaults",
+ "android_stubs_dists_default",
+ ],
+ srcs: [":services-non-updatable-stubs{.exportable}"],
+ installable: false,
+ static_libs: [
+ "android_module_lib_stubs_current_exportable.from-source",
+ ],
dist: {
dir: "apistubs/android/system-server",
},
@@ -572,6 +718,7 @@
// with its own package-private android.annotation.Nullable.
"private-stub-annotations-jar",
],
+ is_stubs_module: true,
}
java_genrule {
@@ -626,6 +773,7 @@
// annotations found, thus should exist inside android.jar.
"private-stub-annotations-jar",
],
+ is_stubs_module: true,
}
// Listing of API domains contribution and dependencies per API surfaces
@@ -635,7 +783,6 @@
api_contributions: [
"framework-virtualization.stubs.source.test.api.contribution",
"framework-location.stubs.source.test.api.contribution",
- "framework-nfc.stubs.source.test.api.contribution",
],
}
@@ -818,7 +965,7 @@
java_library {
name: "android_stubs_current_with_test_libs",
static_libs: [
- "android_stubs_current",
+ "android_stubs_current_exportable",
"android.test.base.stubs",
"android.test.mock.stubs",
"android.test.runner.stubs",
@@ -833,7 +980,7 @@
java_library {
name: "android_system_stubs_current_with_test_libs",
static_libs: [
- "android_system_stubs_current",
+ "android_system_stubs_current_exportable",
"android.test.base.stubs.system",
"android.test.mock.stubs.system",
"android.test.runner.stubs.system",
@@ -848,7 +995,7 @@
java_library {
name: "android_module_stubs_current_with_test_libs",
static_libs: [
- "android_module_lib_stubs_current",
+ "android_module_lib_stubs_current_exportable",
"android.test.base.stubs",
"android.test.mock.stubs",
"android.test.runner.stubs",
@@ -863,7 +1010,7 @@
java_library {
name: "android_system_server_stubs_current_with_test_libs",
static_libs: [
- "android_system_server_stubs_current",
+ "android_system_server_stubs_current_exportable",
"android.test.base.stubs.system",
"android.test.mock.stubs.system",
"android.test.runner.stubs.system",
@@ -900,10 +1047,19 @@
],
api_levels_sdk_type: "system",
extensions_info_file: ":sdk-extensions-info",
+ dists: [
+ // Make the api-versions.xml file for the system API available in the
+ // sdk build target.
+ {
+ targets: ["sdk"],
+ dest: "api-versions_system.xml",
+ tag: ".api_versions.xml",
+ },
+ ],
}
// This module can be built with:
-// m out/soong/.intermediates/frameworks/base/api_versions_module_lib/android_common/metalava/api-versions.xml
+// m out/soong/.intermediates/frameworks/base/api/api_versions_module_lib/android_common/metalava/api-versions.xml
droidstubs {
name: "api_versions_module_lib",
srcs: [":android_module_stubs_current_with_test_libs{.jar}"],
diff --git a/api/api.go b/api/api.go
index 2668999..b31a26c 100644
--- a/api/api.go
+++ b/api/api.go
@@ -31,7 +31,6 @@
const i18n = "i18n.module.public.api"
const virtualization = "framework-virtualization"
const location = "framework-location"
-const nfc = "framework-nfc"
var core_libraries_modules = []string{art, conscrypt, i18n}
@@ -43,7 +42,7 @@
// APIs.
// In addition, the modules in this list are allowed to contribute to test APIs
// stubs.
-var non_updatable_modules = []string{virtualization, location, nfc}
+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
@@ -64,6 +63,7 @@
type CombinedApis struct {
android.ModuleBase
+ android.DefaultableModuleBase
properties CombinedApisProperties
}
@@ -74,11 +74,50 @@
func registerBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("combined_apis", combinedApisModuleFactory)
+ ctx.RegisterModuleType("combined_apis_defaults", CombinedApisModuleDefaultsFactory)
}
var PrepareForCombinedApisTest = android.FixtureRegisterWithContext(registerBuildComponents)
+func (a *CombinedApis) apiFingerprintStubDeps() []string {
+ ret := []string{}
+ ret = append(
+ ret,
+ transformArray(a.properties.Bootclasspath, "", ".stubs")...,
+ )
+ ret = append(
+ ret,
+ transformArray(a.properties.Bootclasspath, "", ".stubs.system")...,
+ )
+ ret = append(
+ ret,
+ transformArray(a.properties.Bootclasspath, "", ".stubs.module_lib")...,
+ )
+ ret = append(
+ ret,
+ transformArray(a.properties.System_server_classpath, "", ".stubs.system_server")...,
+ )
+ return ret
+}
+
+func (a *CombinedApis) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), nil, a.apiFingerprintStubDeps()...)
+}
+
func (a *CombinedApis) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ if _, ok := child.(java.AndroidLibraryDependency); ok && child.Name() != "framework-res" {
+ // Stubs of BCP and SSCP libraries should not have any dependencies on apps
+ // This check ensures that we do not run into circular dependencies when UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT=true
+ ctx.ModuleErrorf(
+ "Module %s is not a valid dependency of the stub library %s\n."+
+ "If this dependency has been added via `libs` of java_sdk_library, please move it to `impl_only_libs`\n",
+ child.Name(), parent.Name())
+ return false // error detected
+ }
+ return true
+ })
+
}
type genruleProps struct {
@@ -92,11 +131,12 @@
}
type libraryProps struct {
- Name *string
- Sdk_version *string
- Static_libs []string
- Visibility []string
- Defaults []string
+ Name *string
+ Sdk_version *string
+ Static_libs []string
+ Visibility []string
+ Defaults []string
+ Is_stubs_module *bool
}
type fgProps struct {
@@ -129,7 +169,7 @@
Scope string
}
-func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) {
+func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition, stubsTypeSuffix string, doDist bool) {
metalavaCmd := "$(location metalava)"
// Silence reflection warnings. See b/168689341
metalavaCmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED "
@@ -139,7 +179,7 @@
if txt.Scope != "public" {
filename = txt.Scope + "-" + filename
}
- moduleName := ctx.ModuleName() + "-" + filename
+ moduleName := ctx.ModuleName() + stubsTypeSuffix + filename
props := genruleProps{}
props.Name = proptools.StringPtr(moduleName)
@@ -147,17 +187,19 @@
props.Out = []string{filename}
props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --out $(out)")
props.Srcs = append([]string{txt.BaseTxt}, createSrcs(txt.Modules, txt.ModuleTag)...)
- props.Dists = []android.Dist{
- {
- Targets: []string{"droidcore"},
- Dir: proptools.StringPtr("api"),
- Dest: proptools.StringPtr(filename),
- },
- {
- Targets: []string{"api_txt", "sdk"},
- Dir: proptools.StringPtr("apistubs/android/" + txt.Scope + "/api"),
- Dest: proptools.StringPtr(txt.DistFilename),
- },
+ if doDist {
+ props.Dists = []android.Dist{
+ {
+ Targets: []string{"droidcore"},
+ Dir: proptools.StringPtr("api"),
+ Dest: proptools.StringPtr(filename),
+ },
+ {
+ Targets: []string{"api_txt", "sdk"},
+ Dir: proptools.StringPtr("apistubs/android/" + txt.Scope + "/api"),
+ Dest: proptools.StringPtr(txt.DistFilename),
+ },
+ }
}
props.Visibility = []string{"//visibility:public"}
ctx.CreateModule(genrule.GenRuleFactory, &props)
@@ -200,6 +242,17 @@
props.Static_libs = transformArray(modules, "", ".stubs")
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
+ ctx.CreateModule(java.LibraryFactory, &props)
+}
+
+func createMergedPublicExportableStubs(ctx android.LoadHookContext, modules []string) {
+ props := libraryProps{}
+ props.Name = proptools.StringPtr("all-modules-public-stubs-exportable")
+ props.Static_libs = transformArray(modules, "", ".stubs.exportable")
+ props.Sdk_version = proptools.StringPtr("module_current")
+ props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
@@ -212,6 +265,7 @@
props.Static_libs = transformArray(updatable_modules, "", ".stubs.system")
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
// Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules
@@ -223,6 +277,33 @@
props.Static_libs = append(props.Static_libs, "all-updatable-modules-system-stubs")
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
+ ctx.CreateModule(java.LibraryFactory, &props)
+ }
+}
+
+func createMergedSystemExportableStubs(ctx android.LoadHookContext, modules []string) {
+ // First create the all-updatable-modules-system-stubs
+ {
+ updatable_modules := removeAll(modules, non_updatable_modules)
+ props := libraryProps{}
+ props.Name = proptools.StringPtr("all-updatable-modules-system-stubs-exportable")
+ props.Static_libs = transformArray(updatable_modules, "", ".stubs.exportable.system")
+ props.Sdk_version = proptools.StringPtr("module_current")
+ props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
+ ctx.CreateModule(java.LibraryFactory, &props)
+ }
+ // Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules
+ // into all-modules-system-stubs.
+ {
+ props := libraryProps{}
+ props.Name = proptools.StringPtr("all-modules-system-stubs-exportable")
+ props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.system")
+ props.Static_libs = append(props.Static_libs, "all-updatable-modules-system-stubs-exportable")
+ props.Sdk_version = proptools.StringPtr("module_current")
+ props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
}
@@ -233,6 +314,17 @@
props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.test")
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
+ ctx.CreateModule(java.LibraryFactory, &props)
+}
+
+func createMergedTestExportableStubsForNonUpdatableModules(ctx android.LoadHookContext) {
+ props := libraryProps{}
+ props.Name = proptools.StringPtr("all-non-updatable-modules-test-stubs-exportable")
+ props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.test")
+ props.Sdk_version = proptools.StringPtr("module_current")
+ props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
@@ -266,6 +358,20 @@
}
}
+func createMergedFrameworkModuleLibExportableStubs(ctx android.LoadHookContext, modules []string) {
+ // 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-exportable")
+ props.Static_libs = transformArray(modules, "", ".stubs.exportable.module_lib")
+ props.Sdk_version = proptools.StringPtr("module_current")
+ props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
+ ctx.CreateModule(java.LibraryFactory, &props)
+}
+
func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules []string) {
// The user of this module compiles against the "core" SDK and against non-updatable modules,
// so remove to avoid dupes.
@@ -276,6 +382,7 @@
props.Static_libs = transformArray(modules, "", ".stubs.module_lib")
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
@@ -287,7 +394,7 @@
ctx.CreateModule(android.FileGroupFactory, &props)
}
-func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) {
+func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string, baseTxtModulePrefix, stubsTypeSuffix string, doDist bool) {
var textFiles []MergedTxtDefinition
tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
@@ -296,7 +403,7 @@
textFiles = append(textFiles, MergedTxtDefinition{
TxtFilename: f,
DistFilename: distFilename[i],
- BaseTxt: ":non-updatable-" + f,
+ BaseTxt: ":" + baseTxtModulePrefix + f,
Modules: bootclasspath,
ModuleTag: "{.public" + tagSuffix[i],
Scope: "public",
@@ -304,7 +411,7 @@
textFiles = append(textFiles, MergedTxtDefinition{
TxtFilename: f,
DistFilename: distFilename[i],
- BaseTxt: ":non-updatable-system-" + f,
+ BaseTxt: ":" + baseTxtModulePrefix + "system-" + f,
Modules: bootclasspath,
ModuleTag: "{.system" + tagSuffix[i],
Scope: "system",
@@ -312,7 +419,7 @@
textFiles = append(textFiles, MergedTxtDefinition{
TxtFilename: f,
DistFilename: distFilename[i],
- BaseTxt: ":non-updatable-module-lib-" + f,
+ BaseTxt: ":" + baseTxtModulePrefix + "module-lib-" + f,
Modules: bootclasspath,
ModuleTag: "{.module-lib" + tagSuffix[i],
Scope: "module-lib",
@@ -320,14 +427,14 @@
textFiles = append(textFiles, MergedTxtDefinition{
TxtFilename: f,
DistFilename: distFilename[i],
- BaseTxt: ":non-updatable-system-server-" + f,
+ BaseTxt: ":" + baseTxtModulePrefix + "system-server-" + f,
Modules: system_server_classpath,
ModuleTag: "{.system-server" + tagSuffix[i],
Scope: "system-server",
})
}
for _, txt := range textFiles {
- createMergedTxt(ctx, txt)
+ createMergedTxt(ctx, txt, stubsTypeSuffix, doDist)
}
}
@@ -376,6 +483,29 @@
props.Static_libs = []string{staticLib}
props.Defaults = []string{"android.jar_defaults"}
props.Visibility = []string{"//visibility:public"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
+
+ ctx.CreateModule(java.LibraryFactory, &props)
+ }
+}
+
+func createFullExportableApiLibraries(ctx android.LoadHookContext) {
+ javaLibraryNames := []string{
+ "android_stubs_current_exportable",
+ "android_system_stubs_current_exportable",
+ "android_test_stubs_current_exportable",
+ "android_module_lib_stubs_current_exportable",
+ "android_system_server_stubs_current_exportable",
+ }
+
+ for _, libraryName := range javaLibraryNames {
+ props := libraryProps{}
+ props.Name = proptools.StringPtr(libraryName)
+ staticLib := libraryName + ".from-source"
+ props.Static_libs = []string{staticLib}
+ props.Defaults = []string{"android.jar_defaults"}
+ props.Visibility = []string{"//visibility:public"}
+ props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
@@ -388,7 +518,8 @@
bootclasspath = append(bootclasspath, a.properties.Conditional_bootclasspath...)
sort.Strings(bootclasspath)
}
- createMergedTxts(ctx, bootclasspath, system_server_classpath)
+ createMergedTxts(ctx, bootclasspath, system_server_classpath, "non-updatable-", "-", false)
+ createMergedTxts(ctx, bootclasspath, system_server_classpath, "non-updatable-exportable-", "-exportable-", true)
createMergedPublicStubs(ctx, bootclasspath)
createMergedSystemStubs(ctx, bootclasspath)
@@ -396,6 +527,11 @@
createMergedFrameworkModuleLibStubs(ctx, bootclasspath)
createMergedFrameworkImpl(ctx, bootclasspath)
+ createMergedPublicExportableStubs(ctx, bootclasspath)
+ createMergedSystemExportableStubs(ctx, bootclasspath)
+ createMergedTestExportableStubsForNonUpdatableModules(ctx)
+ createMergedFrameworkModuleLibExportableStubs(ctx, bootclasspath)
+
createMergedAnnotationsFilegroups(ctx, bootclasspath, system_server_classpath)
createPublicStubsSourceFilegroup(ctx, bootclasspath)
@@ -403,12 +539,15 @@
createApiContributionDefaults(ctx, bootclasspath)
createFullApiLibraries(ctx)
+
+ createFullExportableApiLibraries(ctx)
}
func combinedApisModuleFactory() android.Module {
module := &CombinedApis{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
+ android.InitDefaultableModule(module)
android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) })
return module
}
@@ -445,3 +584,16 @@
}
return s2
}
+
+// Defaults
+type CombinedApisModuleDefaults struct {
+ android.ModuleBase
+ android.DefaultsModuleBase
+}
+
+func CombinedApisModuleDefaultsFactory() android.Module {
+ module := &CombinedApisModuleDefaults{}
+ module.AddProperties(&CombinedApisProperties{})
+ android.InitDefaultsModule(module)
+ return module
+}
diff --git a/api/coverage/tools/ExtractFlaggedApis.kt b/api/coverage/tools/ExtractFlaggedApis.kt
index 43caaec..caa1929 100644
--- a/api/coverage/tools/ExtractFlaggedApis.kt
+++ b/api/coverage/tools/ExtractFlaggedApis.kt
@@ -43,7 +43,7 @@
.setClassName(it.fullName())
.setMethodName(method.name())
for (param in method.parameters()) {
- api.addParameterTypes(param.type().toTypeString())
+ api.addParameters(param.type().toTypeString())
}
if (builder.containsFlagToApi(flagValue)) {
var updatedApis =
diff --git a/api/coverage/tools/extract_flagged_apis.proto b/api/coverage/tools/extract_flagged_apis.proto
index 031d621..4db2a8b 100644
--- a/api/coverage/tools/extract_flagged_apis.proto
+++ b/api/coverage/tools/extract_flagged_apis.proto
@@ -32,6 +32,6 @@
string package_name = 1;
string class_name = 2;
string method_name = 3;
- repeated string parameter_types = 4;
+ repeated string parameters = 4;
}
diff --git a/boot/Android.bp b/boot/Android.bp
index 8a3d35e..4b3ad655 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -29,6 +29,7 @@
config_namespace: "AUTO",
bool_variables: [
"car_bootclasspath_fragment",
+ "release_crashrecovery_module",
],
properties: [
"fragments",
@@ -155,6 +156,15 @@
},
],
},
+ release_crashrecovery_module: {
+ fragments: [
+ // only used when crashrecovery is enabled
+ {
+ apex: "com.android.crashrecovery",
+ module: "com.android.crashrecovery-bootclasspath-fragment",
+ },
+ ],
+ },
},
// Additional information needed by hidden api processing.
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 681f8e9..f8706b3 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -389,8 +389,8 @@
break;
}
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
diff --git a/config/dirty-image-objects b/config/dirty-image-objects
index 2584610e..f2e2b82 100644
--- a/config/dirty-image-objects
+++ b/config/dirty-image-objects
@@ -16,282 +16,1713 @@
#
#
# Dirty-image-objects file for boot image.
-#
-# Objects in this file are known dirty at runtime. Current this includes:
-# - classes with known dirty static fields.
-#
# The image writer will bin these objects together in the image.
+# More info about dirty objects format and how to collect the data can be
+# found in: art/imgdiag/dirty_image_objects.md
+# This particular file was generated by dumping all pre-installed apps.
#
-# This file can be generated using imgdiag with a command such as:
-# adb shell imgdiag --image-diff-pid=<app pid> --zygote-diff-pid=<zygote pid> \
-# --boot-image=/system/framework/boot.art --dump-dirty-objects
-# Then, grep for lines containing "Private dirty object" from the output.
-# This particular file was generated by dumping systemserver and systemui.
-#
-Landroid/animation/LayoutTransition;
-Landroid/app/ActivityManager;
-Landroid/app/ActivityTaskManager;
-Landroid/app/ActivityThread;
-Landroid/app/AlarmManager;
-Landroid/app/AppOpsManager;
-Landroid/app/ContextImpl;
-Landroid/app/Notification;
-Landroid/app/NotificationManager;
-Landroid/app/PendingIntent$FinishedDispatcher;
-Landroid/app/PropertyInvalidatedCache$NoPreloadHolder;
-Landroid/app/QueuedWork;
-Landroid/app/ResourcesManager;
-Landroid/app/SystemServiceRegistry;
-Landroid/app/WallpaperManager;
-Landroid/app/backup/BackupManager;
-Landroid/compat/Compatibility;
-Landroid/content/AsyncQueryHandler;
-Landroid/content/ContentProviderClient;
-Landroid/content/ContentResolver;
-Landroid/content/Context;
-Landroid/content/pm/PackageItemInfo;
-Landroid/content/pm/UserPackage;
-Landroid/content/res/ResourceTimer;
-Landroid/database/CursorWindow;
-Landroid/database/sqlite/SQLiteCompatibilityWalFlags;
-Landroid/database/sqlite/SQLiteDebug$NoPreloadHolder;
-Landroid/database/sqlite/SQLiteGlobal;
-Landroid/ddm/DdmHandleAppName;
-Landroid/graphics/Bitmap;
-Landroid/graphics/Canvas;
-Landroid/graphics/Compatibility;
-Landroid/graphics/HardwareRenderer;
-Landroid/graphics/TemporaryBuffer;
-Landroid/graphics/Typeface;
-Landroid/graphics/drawable/AdaptiveIconDrawable;
-Landroid/hardware/SensorPrivacyManager;
-Landroid/hardware/SystemSensorManager;
-Landroid/hardware/devicestate/DeviceStateManagerGlobal;
-Landroid/hardware/display/ColorDisplayManager$ColorDisplayManagerInternal;
-Landroid/hardware/display/DisplayManagerGlobal;
-Landroid/hardware/input/InputManagerGlobal;
-Landroid/hardware/location/GeofenceHardwareImpl;
-Landroid/icu/impl/number/range/StandardPluralRanges;
-Landroid/icu/text/Collator;
-Landroid/icu/util/TimeZone;
-Landroid/location/LocationManager;
-Landroid/media/AudioManager;
-Landroid/media/AudioPlaybackConfiguration;
-Landroid/media/AudioSystem;
-Landroid/media/MediaCodec;
-Landroid/media/MediaCodecList;
-Landroid/media/MediaFrameworkPlatformInitializer;
-Landroid/media/MediaRouter2Manager;
-Landroid/media/MediaRouter;
-Landroid/media/PlayerBase;
-Landroid/media/audiopolicy/AudioProductStrategy;
-Landroid/media/audiopolicy/AudioVolumeGroup;
-Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcFrameworkInitializer;
-Landroid/nfc/cardemulation/CardEmulation;
-Landroid/os/AsyncTask;
-Landroid/os/BaseBundle;
-Landroid/os/Binder;
-Landroid/os/BinderProxy;
-Landroid/os/Environment;
-Landroid/os/FileObserver;
-Landroid/os/Handler;
-Landroid/os/LocaleList;
-Landroid/os/Looper;
-Landroid/os/Message;
-Landroid/os/NullVibrator;
-Landroid/os/Parcel;
-Landroid/os/Process;
-Landroid/os/ServiceManager;
-Landroid/os/StrictMode;
-Landroid/os/UEventObserver;
-Landroid/os/UserManager;
-Landroid/os/WorkSource;
-Landroid/os/storage/StorageManager;
-Landroid/permission/PermissionManager;
-Landroid/provider/DeviceConfigInitializer;
-Landroid/provider/FontsContract;
-Landroid/provider/Settings;
-Landroid/renderscript/RenderScript;
-Landroid/renderscript/RenderScriptCacheDir;
-Landroid/security/keystore2/KeyStoreCryptoOperationUtils;
-Landroid/security/net/config/ApplicationConfig;
-Landroid/security/net/config/SystemCertificateSource$NoPreloadHolder;
-Landroid/security/net/config/UserCertificateSource$NoPreloadHolder;
-Landroid/telecom/Log;
-Landroid/telecom/TelecomManager;
-Landroid/telephony/AnomalyReporter;
-Landroid/telephony/TelephonyFrameworkInitializer;
-Landroid/telephony/TelephonyLocalConnection;
-Landroid/telephony/TelephonyManager;
-Landroid/telephony/TelephonyRegistryManager;
-Landroid/text/DynamicLayout;
-Landroid/text/TextUtils;
-Landroid/text/format/DateFormat;
-Landroid/text/format/DateUtils;
-Landroid/text/method/ArrowKeyMovementMethod;
-Landroid/text/method/LinkMovementMethod;
-Landroid/text/method/SingleLineTransformationMethod;
-Landroid/text/style/ClickableSpan;
-Landroid/timezone/TelephonyLookup;
-Landroid/timezone/TimeZoneFinder;
-Landroid/util/ArrayMap;
-Landroid/util/ArraySet;
-Landroid/util/EventLog;
-Landroid/util/NtpTrustedTime;
-Landroid/view/Choreographer;
-Landroid/view/CrossWindowBlurListeners;
-Landroid/view/DisplayCutout;
-Landroid/view/KeyEvent;
-Landroid/view/MotionEvent;
-Landroid/view/PointerIcon;
-Landroid/view/RoundedCorners;
-Landroid/view/SurfaceControl;
-Landroid/view/View;
-Landroid/view/ViewGroup$TouchTarget;
-Landroid/view/ViewRootImpl;
-Landroid/view/ViewTreeObserver;
-Landroid/view/WindowManagerGlobal;
-Landroid/view/accessibility/AccessibilityManager;
-Landroid/view/accessibility/AccessibilityNodeIdManager;
-Landroid/view/autofill/Helper;
-Landroid/view/inputmethod/IInputMethodManagerGlobalInvoker;
-Landroid/view/inputmethod/InputMethodManager;
-Landroid/webkit/CookieSyncManager;
-Landroid/webkit/WebView;
-Landroid/webkit/WebViewFactory;
-Landroid/webkit/WebViewZygote;
-Landroid/widget/AbsListView;
-Landroid/widget/ImageView;
-Landroid/widget/LinearLayout;
-Landroid/widget/Toast;
-Landroid/window/SurfaceSyncGroup;
-Lcom/android/i18n/timezone/TelephonyLookup;
-Lcom/android/i18n/timezone/TimeZoneFinder;
-Lcom/android/internal/config/appcloning/AppCloningDeviceConfigHelper;
-Lcom/android/internal/content/om/OverlayConfig;
-Lcom/android/internal/display/BrightnessSynchronizer;
-Lcom/android/internal/infra/AndroidFuture;
-Lcom/android/internal/inputmethod/ImeTracing;
-Lcom/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry;
-Lcom/android/internal/jank/InteractionJankMonitor$InstanceHolder;
-Lcom/android/internal/jank/InteractionJankMonitor;
-Lcom/android/internal/logging/MetricsLogger;
-Lcom/android/internal/os/BackgroundThread;
-Lcom/android/internal/os/BinderInternal;
-Lcom/android/internal/os/KernelCpuBpfTracking;
-Lcom/android/internal/os/RuntimeInit;
-Lcom/android/internal/os/SomeArgs;
-Lcom/android/internal/os/ZygoteInit;
-Lcom/android/internal/policy/AttributeCache;
-Lcom/android/internal/protolog/BaseProtoLogImpl;
-Lcom/android/internal/protolog/ProtoLogImpl;
-Lcom/android/internal/statusbar/NotificationVisibility;
-Lcom/android/internal/telephony/CellBroadcastServiceManager;
-Lcom/android/internal/telephony/IntentBroadcaster;
-Lcom/android/internal/telephony/MccTable;
-Lcom/android/internal/telephony/MultiSimSettingController;
-Lcom/android/internal/telephony/PackageChangeReceiver;
-Lcom/android/internal/telephony/PhoneConfigurationManager;
-Lcom/android/internal/telephony/PhoneFactory;
-Lcom/android/internal/telephony/ProxyController;
-Lcom/android/internal/telephony/RILRequest;
-Lcom/android/internal/telephony/RadioConfig;
-Lcom/android/internal/telephony/RadioInterfaceCapabilityController;
-Lcom/android/internal/telephony/SmsApplication;
-Lcom/android/internal/telephony/SmsBroadcastUndelivered;
-Lcom/android/internal/telephony/SomeArgs;
-Lcom/android/internal/telephony/TelephonyComponentFactory;
-Lcom/android/internal/telephony/TelephonyDevController;
-Lcom/android/internal/telephony/cat/CatService;
-Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler;
-Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;
-Lcom/android/internal/telephony/euicc/EuiccCardController;
-Lcom/android/internal/telephony/euicc/EuiccController;
-Lcom/android/internal/telephony/ims/ImsResolver;
-Lcom/android/internal/telephony/metrics/TelephonyMetrics;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$CarrierIdMismatch;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularDataServiceSwitch;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularServiceState;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$DataCallSession;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$EmergencyNumbersInfo;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$GbaEvent;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerEvent;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerListenerEvent;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationFeatureTagStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationServiceDescStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationTermination;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$IncomingSms;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequests;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequestsV2;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingShortCodeSms;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingSms;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$PresenceNotifyEvent;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsAcsProvisioningStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsClientProvisioningStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteController;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteIncomingDatagram;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteOutgoingDatagram;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteProvision;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSession;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSosMessageRecommender;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipDelegateStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipMessageResponse;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportFeatureTagStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportSession;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$UceEventStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$UnmeteredNetworks;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallRatUsage;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallSession;
-Lcom/android/internal/telephony/nano/TelephonyProto$RilDataCall;
-Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyCallSession$Event$RilCall;
-Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyServiceState$NetworkRegistrationInfo;
-Lcom/android/internal/telephony/satellite/PointingAppController;
-Lcom/android/internal/telephony/satellite/SatelliteModemInterface;
-Lcom/android/internal/telephony/uicc/UiccController;
-Lcom/android/internal/telephony/uicc/UiccStateChangedLauncher;
-Lcom/android/internal/util/ContrastColorUtil;
-Lcom/android/internal/view/WindowManagerPolicyThread;
-Lcom/android/org/bouncycastle/crypto/CryptoServicesRegistrar;
-Lcom/android/phone/ecc/nano/ProtobufEccData$CountryInfo;
-Lcom/android/phone/ecc/nano/ProtobufEccData$EccInfo;
-Lcom/android/server/AppWidgetBackupBridge;
-Ldalvik/system/BaseDexClassLoader;
-Ldalvik/system/BlockGuard;
-Ldalvik/system/CloseGuard;
-Ldalvik/system/RuntimeHooks;
-Ldalvik/system/SocketTagger;
-Ldalvik/system/VMRuntime;
-Ldalvik/system/ZipPathValidator;
-Ldalvik/system/ZygoteHooks;
-Ljava/lang/System;
-Ljava/lang/Thread;
-Ljava/lang/Throwable;
-Ljava/lang/ref/FinalizerReference;
-Ljava/lang/ref/ReferenceQueue;
-Ljava/net/ResponseCache;
-Ljava/nio/Bits;
-Ljava/nio/charset/Charset;
-Ljava/security/Provider;
-Ljava/util/Collections;
-Ljava/util/GregorianCalendar;
-Ljava/util/Locale$NoImagePreloadHolder;
-Ljava/util/Locale;
-Ljava/util/Scanner;
-Ljava/util/TimeZone;
-Ljava/util/concurrent/ForkJoinPool;
-Ljava/util/concurrent/ThreadLocalRandom;
-Ljavax/net/ServerSocketFactory;
-Ljavax/net/SocketFactory;
-Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder;
-Ljavax/net/ssl/HttpsURLConnection;
-Ljavax/net/ssl/SSLContext;
-Ljavax/net/ssl/SSLServerSocketFactory;
-Ljavax/net/ssl/SSLSocketFactory;
-Llibcore/io/Libcore;
-Llibcore/net/NetworkSecurityPolicy;
-Lsun/misc/Cleaner;
-Lsun/nio/ch/FileChannelImpl$Unmapper;
-Lsun/nio/ch/FileChannelImpl;
-Lsun/security/jca/Providers;
+Landroid/text/style/URLSpan; 0
+Landroid/content/res/Resources$NotFoundException; 1
+Landroid/os/PowerManager$WakeLock; 2
+Landroid/os/BatterySaverPolicyConfig; 2
+Landroid/content/ContextWrapper; 2
+Landroid/app/WallpaperInfo; 2
+Landroid/content/pm/PackageManager; 2
+Landroid/app/IWallpaperManager; 2
+Ljava/lang/BootClassLoader; 2
+Ljava/time/Duration; 2
+Landroid/util/Printer; 2
+Landroid/app/WallpaperManager$OnColorsChangedListener; 2
+Landroid/app/WallpaperColors; 2
+Landroid/content/pm/ServiceInfo; 2
+Landroid/app/KeyguardManager$KeyguardDismissCallback; 2
+Ljava/lang/CharSequence; 3
+Landroid/widget/Switch; 4
+Lcom/android/internal/util/ContrastColorUtil; 4
+Landroid/view/SurfaceControl; 4
+Landroid/graphics/ColorMatrix;.dexCache:Ljava/lang/Object; 4
+Lcom/android/internal/widget/CachingIconView; 4
+Landroid/window/IRemoteTransition$Stub$Proxy; 4
+Landroid/app/trust/TrustManager$TrustListener; 4
+Landroid/view/NotificationHeaderView; 4
+Lcom/android/internal/widget/ImageResolver; 4
+Landroid/window/WindowContainerTransaction$Change; 4
+Lcom/android/internal/widget/MessagingLayout; 4
+Ljava/util/concurrent/ConcurrentLinkedQueue; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
+Landroid/view/RemotableViewMethod; 4
+Landroid/app/IApplicationThread$Stub$Proxy; 4
+Landroid/os/FileUtils; 4
+Landroid/view/View;.SCALE_X:Landroid/util/Property; 4
+Landroid/widget/GridLayout;.UNDEFINED_ALIGNMENT:Landroid/widget/GridLayout$Alignment; 4
+Landroid/media/MediaPlayer$EventHandler; 4
+Landroid/widget/DateTimeView; 4
+Llibcore/util/ZoneInfo; 4
+Lcom/android/internal/statusbar/IStatusBarService; 4
+Ljava/lang/invoke/MethodType;.internTable:Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;.stale:Ljava/lang/ref/ReferenceQueue; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
+Lcom/android/internal/logging/UiEventLogger; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
+Landroid/renderscript/RenderScript; 4
+Landroid/view/ViewTreeObserver$OnWindowVisibilityChangeListener; 4
+Lcom/android/internal/widget/RemeasuringLinearLayout; 4
+Landroid/widget/DateTimeView$ReceiverInfo$1; 4
+Landroid/view/View;.TRANSLATION_Y:Landroid/util/Property; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry; 4
+Lcom/android/internal/widget/NotificationExpandButton; 4
+Lcom/android/internal/view/menu/ActionMenuItemView; 4
+Landroid/view/animation/AnimationSet; 4
+Landroid/hardware/biometrics/BiometricSourceType;.FINGERPRINT:Landroid/hardware/biometrics/BiometricSourceType; 4
+Landroid/window/WindowOrganizer;.IWindowOrganizerControllerSingleton:Landroid/util/Singleton; 4
+Ljava/lang/Runnable; 4
+Lorg/apache/harmony/dalvik/ddmc/DdmServer;.mHandlerMap:Ljava/util/HashMap; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
+Lcom/android/internal/widget/ImageFloatingTextView; 4
+Landroid/window/IWindowContainerToken$Stub$Proxy; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
+Landroid/content/res/ColorStateList; 4
+Landroid/view/View;.SCALE_Y:Landroid/util/Property; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap; 4
+Lcom/android/internal/widget/ConversationLayout; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
+Lcom/android/internal/colorextraction/ColorExtractor$OnColorsChangedListener; 4
+Landroid/hardware/face/FaceManager$FaceDetectionCallback; 4
+Landroid/widget/RemoteViews;.sLookupKey:Landroid/widget/RemoteViews$MethodKey; 4
+Landroid/widget/ViewSwitcher;.dexCache:Ljava/lang/Object; 4
+Lcom/android/internal/widget/NotificationActionListLayout; 4
+Ljava/util/concurrent/ConcurrentLinkedQueue$Node; 4
+Landroid/hardware/biometrics/BiometricSourceType;.FACE:Landroid/hardware/biometrics/BiometricSourceType; 4
+Landroid/hardware/biometrics/BiometricSourceType;.IRIS:Landroid/hardware/biometrics/BiometricSourceType; 4
+Landroid/view/NotificationTopLineView; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
+Landroid/widget/RemoteViews;.sMethods:Landroid/util/ArrayMap; 4
+Lcom/android/internal/os/BinderInternal$BinderProxyLimitListener; 5
+Landroid/app/AppOpsManager$OnOpNotedInternalListener; 5
+Lcom/android/internal/R$styleable;.WindowAnimation:[I 5
+Lcom/android/internal/logging/UiEventLogger$UiEventEnum; 5
+Lcom/android/internal/policy/AttributeCache; 5
+Landroid/app/Notification$CallStyle; 5
+Landroid/app/AppOpsManager$OnOpNotedListener; 5
+Lcom/android/internal/protolog/BaseProtoLogImpl; 5
+Landroid/app/AppOpsManager$OnOpStartedListener; 5
+Lcom/android/internal/util/ScreenshotHelper$1; 5
+Landroid/app/Notification$DecoratedCustomViewStyle; 5
+Landroid/view/DisplayCutout; 5
+Landroid/view/InputEvent;.mNextSeq:Ljava/util/concurrent/atomic/AtomicInteger; 5
+Lcom/android/internal/statusbar/NotificationVisibility; 5
+Landroid/telephony/DataSpecificRegistrationInfo; 6
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle; 7
+Landroid/telephony/VoiceSpecificRegistrationInfo; 8
+Landroid/telephony/AnomalyReporter; 8
+Landroid/telephony/TelephonyRegistryManager;.sCarrierPrivilegeCallbacks:Ljava/util/WeakHashMap; 8
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.1:Ljava/util/WeakHashMap$Entry; 8
+Landroid/app/LoadedApk$ServiceDispatcher$InnerConnection; 8
+Landroid/content/ContentProvider$Transport; 8
+Landroid/telephony/NetworkRegistrationInfo; 8
+Landroid/net/MatchAllNetworkSpecifier; 8
+Landroid/telephony/TelephonyRegistryManager;.sCarrierPrivilegeCallbacks:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry; 8
+Landroid/app/PropertyInvalidatedCache;.sInvalidates:Ljava/util/HashMap; 9
+Landroid/app/PropertyInvalidatedCache$NoPreloadHolder; 9
+Landroid/app/PropertyInvalidatedCache;.sDisabledKeys:Ljava/util/HashSet;.map:Ljava/util/HashMap; 10
+Landroid/media/AudioSystem$AudioRecordingCallback; 11
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedString; 11
+Landroid/net/metrics/IpManagerEvent; 11
+Lcom/android/internal/os/ProcessCpuTracker$FilterStats; 11
+Lcom/android/internal/infra/AbstractRemoteService$AsyncRequest; 11
+Landroid/content/pm/RegisteredServicesCache$3; 11
+Lcom/android/internal/os/LooperStats; 11
+Lcom/android/server/AppWidgetBackupBridge; 11
+Landroid/hardware/display/DisplayManagerInternal; 11
+Landroid/content/pm/PackageInfo; 11
+Landroid/hardware/soundtrigger/SoundTriggerModule$EventHandlerDelegate; 11
+Landroid/app/servertransaction/ResumeActivityItem; 11
+Lcom/android/internal/widget/AlertDialogLayout; 11
+Landroid/content/pm/FallbackCategoryProvider;.sFallbacks:Landroid/util/ArrayMap; 11
+Landroid/os/RemoteCallback$1; 11
+Landroid/content/pm/SharedLibraryInfo; 11
+Landroid/util/MemoryIntArray; 11
+Landroid/net/metrics/DhcpErrorEvent; 11
+Lcom/android/internal/util/function/DodecConsumer; 11
+Landroid/provider/Settings; 11
+Landroid/app/PropertyInvalidatedCache;.sCorkLock:Ljava/lang/Object; 11
+Lcom/android/internal/os/CachedDeviceState$Readonly; 11
+Landroid/app/job/JobServiceEngine$JobHandler; 11
+Landroid/app/SystemServiceRegistry; 11
+Lcom/android/internal/os/BinderInternal$CallStatsObserver; 11
+Lcom/android/internal/statusbar/IStatusBar$Stub$Proxy; 11
+Landroid/hardware/location/IActivityRecognitionHardwareClient; 11
+Landroid/telecom/Logging/EventManager$EventListener; 11
+Landroid/accounts/AccountManagerInternal; 11
+Lcom/android/internal/os/KernelCpuBpfTracking; 11
+Lcom/android/internal/statusbar/NotificationVisibility$NotificationLocation; 11
+Landroid/hardware/camera2/CameraManager$CameraManagerGlobal; 11
+Landroid/os/ServiceSpecificException; 11
+Landroid/net/Uri$PathPart;.NULL:Landroid/net/Uri$PathPart; 11
+Landroid/app/ActivityManagerInternal; 11
+Landroid/media/AudioSystem; 11
+Landroid/service/dreams/DreamManagerInternal; 11
+Landroid/debug/AdbManagerInternal; 11
+Landroid/graphics/Bitmap$CompressFormat; 11
+Landroid/hardware/location/NanoAppMessage; 11
+Landroid/os/storage/StorageManagerInternal; 11
+Landroid/app/AppOpsManagerInternal; 11
+Ljava/security/cert/CertificateException; 11
+Ldalvik/system/VMRuntime; 11
+Landroid/content/pm/SigningInfo; 11
+Landroid/view/KeyEvent; 11
+Lcom/android/internal/view/WindowManagerPolicyThread; 11
+Landroid/graphics/Region;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 11
+Landroid/content/res/ResourceTimer; 11
+Landroid/view/autofill/AutofillManagerInternal; 11
+Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object; 11
+Landroid/graphics/Region;.sPool:Landroid/util/Pools$SynchronizedPool; 11
+Landroid/app/LoadedApk$ReceiverDispatcher$Args$$ExternalSyntheticLambda0; 11
+Lcom/android/server/LocalServices;.sLocalServiceObjects:Landroid/util/ArrayMap; 11
+Landroid/app/admin/DevicePolicyManagerInternal$OnCrossProfileWidgetProvidersChangeListener; 11
+Landroid/accounts/AccountManagerInternal$OnAppPermissionChangeListener; 11
+Landroid/content/pm/PermissionInfo; 11
+Landroid/view/WindowManagerPolicyConstants$PointerEventListener; 11
+Landroid/os/UEventObserver; 11
+Landroid/media/AudioManagerInternal$RingerModeDelegate; 11
+Landroid/view/Display$HdrCapabilities; 11
+Landroid/service/notification/Condition; 11
+Landroid/content/pm/UserPackage; 11
+Landroid/app/AppOpsManager$SamplingStrategy; 11
+Landroid/telephony/ServiceState; 11
+Landroid/app/servertransaction/PauseActivityItem; 11
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sMessageCallbacksPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;.mLock:Ljava/lang/Object; 11
+Landroid/view/KeyCharacterMap$FallbackAction; 11
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringArray; 11
+Landroid/hardware/display/DeviceProductInfo; 11
+Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap;.mHashes:[I 11
+Landroid/content/pm/RegisteredServicesCache$2; 11
+Landroid/content/pm/PackageManager;.sCacheAutoCorker:Landroid/app/PropertyInvalidatedCache$AutoCorker; 11
+Landroid/app/PropertyInvalidatedCache;.sCorks:Ljava/util/HashMap; 11
+Landroid/service/notification/StatusBarNotification; 11
+Landroid/app/servertransaction/ConfigurationChangeItem; 11
+Landroid/app/ActivityManager$RecentTaskInfo; 11
+Landroid/app/Notification; 11
+Landroid/app/servertransaction/DestroyActivityItem; 11
+Landroid/webkit/WebViewLibraryLoader$RelroFileCreator; 11
+Landroid/net/metrics/NetworkEvent; 11
+Landroid/media/AudioPlaybackConfiguration; 11
+Landroid/accessibilityservice/AccessibilityServiceInfo; 11
+Landroid/hardware/display/DeviceProductInfo$ManufactureDate; 11
+Landroid/os/storage/StorageVolume; 11
+Landroid/os/BatteryManagerInternal; 11
+Landroid/appwidget/AppWidgetManagerInternal; 11
+Landroid/app/servertransaction/NewIntentItem; 11
+Landroid/content/pm/ShortcutServiceInternal; 11
+Landroid/app/assist/ActivityId; 11
+Landroid/window/DisplayAreaAppearedInfo; 11
+Landroid/os/Process;.ZYGOTE_PROCESS:Landroid/os/ZygoteProcess;.mLock:Ljava/lang/Object; 11
+Landroid/app/usage/UsageStats; 11
+Landroid/app/Notification$MediaStyle; 11
+Landroid/media/AudioSystem$DynamicPolicyCallback; 11
+Landroid/content/pm/ProviderInfo; 11
+Landroid/os/PowerManagerInternal; 11
+Landroid/service/voice/VoiceInteractionManagerInternal; 11
+Landroid/content/pm/FeatureInfo; 11
+Landroid/app/servertransaction/TopResumedActivityChangeItem; 11
+Landroid/app/Notification$DecoratedMediaCustomViewStyle; 11
+Landroid/appwidget/AppWidgetProviderInfo; 11
+Landroid/app/AppOpsManager$NoteOpEvent; 11
+Landroid/graphics/GraphicsStatsService; 11
+Landroid/view/DisplayAddress$Physical; 11
+Landroid/content/ComponentName$WithComponentName; 11
+Landroid/app/admin/DevicePolicyManagerInternal; 11
+Landroid/os/ResultReceiver$MyResultReceiver; 11
+Landroid/content/ContentProviderClient; 11
+Landroid/content/pm/RegisteredServicesCache$1; 11
+Landroid/app/PendingIntent$FinishedDispatcher; 11
+Landroid/location/LocationManager; 11
+Landroid/hardware/location/ContextHubInfo; 11
+Landroid/content/pm/ShortcutServiceInternal$ShortcutChangeListener; 11
+Lcom/android/server/usage/AppStandbyInternal; 11
+Landroid/content/pm/RegisteredServicesCacheListener; 11
+Landroid/app/servertransaction/LaunchActivityItem; 11
+Landroid/content/pm/BaseParceledListSlice$1; 11
+Landroid/annotation/StringRes; 11
+Lcom/android/internal/R$styleable;.Window:[I 11
+Landroid/service/notification/ZenModeConfig; 11
+Landroid/telecom/Logging/SessionManager$ISessionListener; 11
+Landroid/app/time/TimeZoneConfiguration; 11
+Landroid/net/metrics/ValidationProbeEvent; 11
+Landroid/content/pm/PackageInstaller$SessionInfo; 11
+Landroid/content/pm/UserPackage;.sCache:Landroid/util/SparseArrayMap;.mData:Landroid/util/SparseArray; 11
+Landroid/content/pm/PermissionGroupInfo; 11
+Landroid/hardware/sidekick/SidekickInternal; 11
+Lcom/android/internal/widget/ButtonBarLayout; 11
+Landroid/content/pm/LauncherActivityInfoInternal; 11
+Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap; 11
+Lcom/android/internal/widget/LockSettingsInternal; 11
+Landroid/media/AudioManagerInternal; 11
+Landroid/app/AppOpsManager$AttributedOpEntry; 11
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringList; 11
+Landroid/telecom/Log; 11
+Landroid/app/time/TimeZoneCapabilities; 11
+Landroid/attention/AttentionManagerInternal; 11
+Landroid/view/WindowManagerPolicyConstants; 11
+Landroid/content/pm/CrossProfileAppsInternal; 11
+Landroid/hardware/location/GeofenceHardwareService; 11
+Landroid/content/pm/dex/ArtManagerInternal; 11
+Landroid/net/metrics/IpReachabilityEvent; 11
+Landroid/content/pm/LauncherApps$ShortcutQuery$QueryFlags; 11
+Landroid/media/AudioAttributes; 11
+Landroid/app/PropertyInvalidatedCache$AutoCorker$1; 11
+Landroid/net/metrics/ApfProgramEvent; 11
+Landroid/content/pm/SigningDetails; 11
+Lcom/android/internal/protolog/ProtoLogImpl; 11
+Landroid/hardware/biometrics/ComponentInfoInternal; 11
+Lcom/android/internal/util/ToBooleanFunction; 11
+Landroid/app/ActivityThread$H; 11
+Landroid/hardware/location/GeofenceHardwareImpl; 11
+Landroid/net/wifi/nl80211/WifiNl80211Manager$ScanEventHandler; 11
+Landroid/util/NtpTrustedTime; 11
+Landroid/hardware/soundtrigger/SoundTrigger$StatusListener; 11
+Lcom/android/internal/app/procstats/AssociationState;.sTmpSourceKey:Lcom/android/internal/app/procstats/AssociationState$SourceKey; 11
+Ljava/util/zip/ZipFile$ZipFileInflaterInputStream; 11
+Landroid/app/job/JobInfo; 11
+Lcom/android/internal/content/om/OverlayConfig; 11
+Landroid/webkit/WebViewZygote; 11
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringSet; 11
+Lcom/android/internal/infra/AbstractRemoteService$VultureCallback; 11
+Landroid/permission/PermissionManagerInternal; 11
+Lcom/android/server/WidgetBackupProvider; 11
+Landroid/window/WindowOnBackInvokedDispatcher$OnBackInvokedCallbackWrapper; 11
+Landroid/app/PropertyInvalidatedCache;.sCorkedInvalidates:Ljava/util/HashMap; 11
+Landroid/media/AudioPlaybackConfiguration$PlayerDeathMonitor; 11
+Landroid/net/wifi/nl80211/WifiNl80211Manager$ScanEventCallback; 11
+Landroid/service/notification/NotificationListenerService$RankingMap; 11
+Landroid/os/UserHandle;.sExtraUserHandleCache:Landroid/util/SparseArray; 11
+Ljava/time/DateTimeException; 11
+Ljava/lang/NumberFormatException; 11
+Ljava/security/Provider;.knownEngines:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.125:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 11
+Landroid/app/LoadedApk$ServiceDispatcher$RunConnection; 11
+Landroid/view/RoundedCorners; 11
+Landroid/os/Process;.ZYGOTE_PROCESS:Landroid/os/ZygoteProcess; 11
+Landroid/media/audiopolicy/AudioVolumeGroup; 11
+Landroid/media/AudioSystem$ErrorCallback; 11
+Landroid/app/servertransaction/ActivityResultItem; 11
+Lcom/android/internal/widget/DialogTitle; 11
+Lcom/android/internal/os/StoragedUidIoStatsReader$Callback; 11
+Landroid/view/ViewRootImpl$W; 11
+Landroid/app/ServiceStartArgs; 11
+Landroid/window/TaskAppearedInfo; 11
+Lcom/android/internal/listeners/ListenerExecutor$FailureCallback; 11
+Landroid/app/ApplicationExitInfo; 11
+Landroid/content/pm/PackageManager;.sCacheAutoCorker:Landroid/app/PropertyInvalidatedCache$AutoCorker;.mLock:Ljava/lang/Object; 11
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringValueMap; 11
+Landroid/content/pm/ResolveInfo; 11
+Lcom/android/internal/display/BrightnessSynchronizer; 11
+Landroid/window/IOnBackInvokedCallback$Stub$Proxy; 12
+Landroid/graphics/drawable/PictureDrawable; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.126:Ljava/lang/Byte; 13
+Landroid/view/ViewDebug$ExportedProperty; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.41:Ljava/lang/Byte; 13
+Landroid/view/inputmethod/DeleteGesture; 13
+Landroid/view/ViewDebug$IntToString; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.56:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.65:Ljava/lang/Byte; 13
+Landroid/webkit/WebViewFactory;.sProviderLock:Ljava/lang/Object; 13
+Ljava/lang/IllegalAccessError; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.51:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.52:Ljava/lang/Byte; 13
+Landroid/view/inputmethod/DeleteRangeGesture; 13
+Landroid/window/WindowContext; 13
+Ljava/util/concurrent/ConcurrentSkipListMap$Node; 13
+Landroid/view/inputmethod/SelectRangeGesture; 13
+Landroid/util/MalformedJsonException; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.131:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.120:Ljava/lang/Byte; 13
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 13
+Ljava/nio/file/StandardOpenOption;.TRUNCATE_EXISTING:Ljava/nio/file/StandardOpenOption; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.121:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.16:Ljava/lang/Byte; 13
+Ljava/util/concurrent/ConcurrentSkipListMap$Index; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.139:Ljava/lang/Byte; 13
+Landroid/view/ViewDebug$FlagToString; 13
+Landroid/view/inputmethod/SelectGesture; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.20:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.94:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.64:Ljava/lang/Byte; 13
+Landroid/webkit/WebViewFactoryProvider$Statics; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.95:Ljava/lang/Byte; 13
+Landroid/service/media/MediaBrowserService$ServiceBinder$1; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.7:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.23:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.46:Ljava/lang/Byte; 13
+Landroid/provider/Settings$SettingNotFoundException; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.74:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.8:Ljava/lang/Byte; 13
+Landroid/widget/TextView;.TEMP_POSITION:[F 13
+Ljava/io/ByteArrayInputStream; 14
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.93:Ljava/lang/Byte; 14
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.134:Ljava/lang/Byte; 14
+Landroid/text/style/ImageSpan; 14
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.154:Ljava/lang/Byte; 15
+Landroid/view/TextureView$SurfaceTextureListener; 16
+Landroid/media/AudioManager$OnAudioFocusChangeListener; 17
+Ljava/util/Locale;.JAPAN:Ljava/util/Locale; 18
+Ljava/util/Locale;.GERMANY:Ljava/util/Locale; 19
+Ljava/util/Locale;.CANADA_FRENCH:Ljava/util/Locale; 20
+Ljava/util/Locale;.ITALY:Ljava/util/Locale; 20
+Ljava/util/Locale;.FRANCE:Ljava/util/Locale; 20
+Ljava/util/Locale;.UK:Ljava/util/Locale; 21
+Ljava/util/Locale;.CANADA:Ljava/util/Locale; 21
+Ljava/util/Locale$Cache;.LOCALECACHE:Ljava/util/Locale$Cache;.map:Ljava/util/concurrent/ConcurrentMap; 22
+Ljava/lang/IllegalStateException; 23
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sMessageCallbacksPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool; 24
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sMessageCallbacksPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;.mPool:[Ljava/lang/Object; 24
+Landroid/media/MediaRouter$WifiDisplayStatusChangedReceiver; 25
+Landroid/media/MediaRouter$VolumeChangeReceiver; 25
+Landroid/app/AppOpsManager$OnOpActiveChangedListener; 26
+Landroid/media/PlayerBase; 27
+Landroid/content/pm/Checksum$Type; 28
+Ljava/lang/Class; 29
+Landroid/widget/MediaController$MediaPlayerControl; 30
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.135:Ljava/lang/Long; 30
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.152:Ljava/lang/Long; 30
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.215:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.206:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.137:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.203:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.213:Ljava/lang/Byte; 31
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.549:Ljava/lang/Long; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.201:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.249:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.163:Ljava/lang/Byte; 31
+Ljava/util/HashMap; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.210:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.161:Ljava/lang/Byte; 31
+Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.0:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.199:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.248:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.252:Ljava/lang/Byte; 31
+Lcom/android/ims/rcs/uce/UceDeviceState;.DEVICE_STATE_DESCRIPTION:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.3:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.159:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.217:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.200:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.240:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.198:Ljava/lang/Byte; 31
+Lcom/android/ims/rcs/uce/UceDeviceState;.DEVICE_STATE_DESCRIPTION:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.4:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 31
+Landroid/content/pm/PackageManager$OnChecksumsReadyListener; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.193:Ljava/lang/Byte; 31
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.228:Ljava/lang/Long; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.236:Ljava/lang/Byte; 31
+Landroid/telephony/ims/ImsService;.CAPABILITIES_LOG_MAP:Ljava/util/Map;.table:[Ljava/lang/Object;.2:Ljava/lang/Long; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.211:Ljava/lang/Byte; 31
+Landroid/view/SurfaceView; 32
+Landroid/view/ViewStub$OnInflateListener; 33
+Landroid/graphics/drawable/DrawableInflater;.CONSTRUCTOR_MAP:Ljava/util/HashMap; 34
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.245:Ljava/lang/Byte; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.232:Ljava/lang/Byte; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.12:Ljava/lang/Byte; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.170:Ljava/lang/Long; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.183:Ljava/lang/Long; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.246:Ljava/lang/Byte; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.168:Ljava/lang/Long; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.72:Ljava/lang/Byte; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.243:Ljava/lang/Byte; 35
+Ljava/util/WeakHashMap;.NULL_KEY:Ljava/lang/Object; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.235:Ljava/lang/Byte; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.147:Ljava/lang/Long; 35
+Ljava/io/InterruptedIOException; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.184:Ljava/lang/Long; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.165:Ljava/lang/Long; 35
+Landroid/text/style/ForegroundColorSpan; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.176:Ljava/lang/Long; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.173:Ljava/lang/Long; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.181:Ljava/lang/Byte; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.157:Ljava/lang/Byte; 35
+Landroid/content/res/AssetManager$AssetInputStream; 35
+Landroid/graphics/drawable/TransitionDrawable; 36
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1:Ljava/lang/Boolean; 37
+Landroid/view/ViewOverlay$OverlayViewGroup; 38
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.11:Ljava/lang/Boolean; 39
+Ljava/util/Observer; 40
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.129:Ljava/lang/Byte; 41
+[Ljava/lang/Byte; 41
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.144:Ljava/lang/Byte; 41
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.164:Ljava/lang/Byte; 42
+Landroid/view/OrientationEventListener; 43
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.195:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.233:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.229:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.128:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.242:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.196:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.208:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.212:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.228:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.205:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.197:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.204:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.207:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.223:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.244:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.174:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.194:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.225:Ljava/lang/Byte; 45
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.239:Ljava/lang/Byte; 45
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.238:Ljava/lang/Byte; 45
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.227:Ljava/lang/Byte; 45
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.152:Ljava/lang/Byte; 46
+Landroid/app/RemoteAction; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.168:Ljava/lang/Byte; 46
+Landroid/text/style/QuoteSpan; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.54:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.124:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.142:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.190:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.114:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.69:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.30:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.133:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.49:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.58:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.143:Ljava/lang/Byte; 47
+Landroid/icu/text/RelativeDateTimeFormatter$AbsoluteUnit; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.82:Ljava/lang/Byte; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.140:Ljava/lang/Byte; 47
+Landroid/icu/text/RelativeDateTimeFormatter;.fallbackCache:[Landroid/icu/text/RelativeDateTimeFormatter$Style; 47
+Landroid/icu/text/RelativeDateTimeFormatter$Style; 47
+Landroid/icu/text/RelativeDateTimeFormatter;.cache:Landroid/icu/text/RelativeDateTimeFormatter$Cache;.cache:Landroid/icu/impl/CacheBase;.map:Ljava/util/concurrent/ConcurrentHashMap; 47
+Landroid/icu/text/RelativeDateTimeFormatter$RelativeUnit; 47
+Landroid/icu/text/RelativeDateTimeFormatter$Direction; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.130:Ljava/lang/Byte; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.43:Ljava/lang/Byte; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.146:Ljava/lang/Byte; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.138:Ljava/lang/Byte; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.136:Ljava/lang/Byte; 48
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.0:Ljava/lang/Byte; 49
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.160:Ljava/lang/Byte; 49
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.169:Ljava/lang/Byte; 50
+Landroid/widget/Spinner; 50
+Landroid/widget/MultiAutoCompleteTextView; 50
+Ljava/util/ArrayList; 50
+Landroid/widget/CheckBox; 50
+Ljava/io/Serializable; 50
+Landroid/widget/RatingBar; 50
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.132:Ljava/lang/Byte; 50
+Landroid/widget/AutoCompleteTextView; 50
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node; 50
+[Ljava/lang/Object; 50
+Landroid/widget/SeekBar; 51
+Ljava/lang/Void; 52
+Landroid/app/ActivityTaskManager;.sInstance:Landroid/util/Singleton; 53
+Landroid/view/ViewRootImpl$$ExternalSyntheticLambda11; 54
+Landroid/view/ViewTreeObserver$OnWindowFocusChangeListener; 55
+Landroid/view/InsetsAnimationThread; 56
+Lcom/android/internal/jank/InteractionJankMonitor$InstanceHolder; 57
+Lcom/android/internal/jank/InteractionJankMonitor; 57
+Landroid/hardware/camera2/CameraCharacteristics;.FLASH_INFO_AVAILABLE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 58
+Landroid/hardware/display/NightDisplayListener$Callback; 59
+Landroid/media/MediaRouter2Manager; 59
+Landroid/os/HandlerExecutor; 59
+Landroid/os/strictmode/LeakedClosableViolation; 60
+Lcom/android/internal/logging/MetricsLogger; 60
+Lcom/android/internal/os/PowerProfile;.sPowerItemMap:Ljava/util/HashMap; 61
+Lcom/android/internal/os/PowerProfile;.sPowerArrayMap:Ljava/util/HashMap; 61
+Lcom/android/internal/os/PowerProfile;.sModemPowerProfile:Lcom/android/internal/power/ModemPowerProfile;.mPowerConstants:Landroid/util/SparseDoubleArray;.mValues:Landroid/util/SparseLongArray; 61
+Landroid/content/IntentFilter; 62
+Landroid/telecom/TelecomManager; 63
+Ljava/lang/IllegalArgumentException; 64
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.1:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object; 65
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.1:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mCache:Ljava/util/LinkedHashMap; 65
+Landroid/telephony/VisualVoicemailSmsFilterSettings;.DEFAULT_ORIGINATING_NUMBERS:Ljava/util/List; 66
+Ljava/util/AbstractList; 68
+Ljava/util/AbstractCollection; 68
+Ljava/util/Collections$EmptyList; 69
+Ljava/lang/StackTraceElement; 69
+[Ljava/lang/StackTraceElement; 69
+Landroid/os/strictmode/Violation; 70
+Ljava/util/List; 71
+Ljava/lang/String; 72
+Ljava/io/ObjectInputStream; 73
+Ljava/io/ObjectStreamClass$Caches;.localDescs:Ljava/util/concurrent/ConcurrentMap; 73
+Ljava/io/ObjectStreamClass$Caches;.reflectors:Ljava/util/concurrent/ConcurrentMap; 73
+Ljava/io/ObjectOutputStream; 73
+Ljava/lang/Number; 74
+Ljava/math/BigInteger; 75
+[B 76
+Landroid/os/Handler; 77
+Landroid/view/accessibility/AccessibilityManager; 78
+Landroid/view/ViewConfiguration;.sConfigurations:Landroid/util/SparseArray;.mKeys:[I 79
+Landroid/view/ViewConfiguration;.sConfigurations:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 79
+Landroid/view/ViewConfiguration;.sConfigurations:Landroid/util/SparseArray; 79
+Landroid/widget/FrameLayout; 80
+Lcom/android/internal/inputmethod/ImeTracing; 80
+Lcom/android/internal/policy/DecorView; 80
+Landroid/view/accessibility/AccessibilityNodeIdManager; 80
+Landroid/view/ViewTreeObserver; 80
+Landroid/view/ViewRootImpl; 80
+Landroid/os/SystemProperties;.sChangeCallbacks:Ljava/util/ArrayList; 80
+Landroid/transition/ChangeTransform; 80
+Landroid/window/SurfaceSyncGroup; 80
+Landroid/transition/ChangeClipBounds; 80
+Landroid/view/SurfaceControlRegistry; 80
+Landroid/transition/ChangeImageTransform; 80
+Landroid/widget/LinearLayout; 80
+Landroid/view/ViewStub; 81
+Landroid/text/TextLine;.sCached:[Landroid/text/TextLine; 82
+Landroid/text/TextUtils; 82
+Landroid/graphics/TemporaryBuffer; 82
+Landroid/content/res/ColorStateList;.sCache:Landroid/util/SparseArray; 83
+Landroid/text/Layout;.sTempRect:Landroid/graphics/Rect; 84
+Landroid/widget/ImageView; 85
+Landroid/graphics/drawable/ColorDrawable; 86
+Landroid/os/StrictMode$InstanceTracker;.sInstanceCounts:Ljava/util/HashMap; 87
+Landroid/app/ActivityClient;.INTERFACE_SINGLETON:Landroid/app/ActivityClient$ActivityClientControllerSingleton; 88
+Landroid/app/ActivityClient;.sInstance:Landroid/util/Singleton; 88
+Landroid/view/AbsSavedState$1; 89
+Landroid/app/FragmentManagerState; 90
+Landroid/window/OnBackAnimationCallback; 91
+Landroid/animation/AnimatorInflater;.sTmpTypedValue:Landroid/util/TypedValue; 92
+Landroid/graphics/drawable/RippleDrawable; 93
+Landroid/view/inputmethod/IInputMethodManagerGlobalInvoker; 94
+Landroid/app/ActivityTaskManager;.IActivityTaskManagerSingleton:Landroid/util/Singleton; 95
+Landroid/view/Choreographer; 96
+Lcom/android/internal/os/SomeArgs; 97
+Landroid/graphics/Bitmap; 98
+Landroid/view/autofill/AutofillId; 99
+Landroid/view/inputmethod/BaseInputConnection;.COMPOSING:Ljava/lang/Object; 100
+Landroid/text/Selection;.SELECTION_MEMORY:Ljava/lang/Object; 101
+Landroid/text/Selection;.SELECTION_END:Ljava/lang/Object; 101
+Landroid/text/Selection;.SELECTION_START:Ljava/lang/Object; 101
+Landroid/text/SpannableStringBuilder;.sCachedIntBuffer:[[I 102
+Landroid/text/Selection$MemoryTextWatcher; 103
+Landroid/text/SpanWatcher; 104
+Lcom/android/internal/util/ArrayUtils;.sCache:[Ljava/lang/Object; 105
+Ljava/lang/Integer;.SMALL_NEG_VALUES:[Ljava/lang/String; 106
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 107
+Lsun/nio/ch/SharedFileLockTable;.lockMap:Ljava/util/concurrent/ConcurrentHashMap; 108
+Lsun/nio/ch/FileChannelImpl; 108
+Landroid/database/sqlite/SQLiteDatabase$CursorFactory; 109
+Landroid/database/sqlite/SQLiteDebug$NoPreloadHolder; 110
+Landroid/database/sqlite/SQLiteCompatibilityWalFlags; 110
+Landroid/database/sqlite/SQLiteGlobal; 110
+Landroid/database/CursorWindow; 111
+Landroid/content/ContentResolver; 112
+Ljava/nio/charset/Charset; 113
+Landroid/app/ContextImpl; 114
+Ljava/util/concurrent/Executors$DefaultThreadFactory;.poolNumber:Ljava/util/concurrent/atomic/AtomicInteger; 115
+Landroid/content/pm/PackageManager;.sPackageInfoCache:Landroid/app/PropertyInvalidatedCache;.mCache:Ljava/util/LinkedHashMap; 116
+Landroid/content/pm/PackageManager;.sApplicationInfoCache:Landroid/app/PropertyInvalidatedCache;.mCache:Ljava/util/LinkedHashMap; 117
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.systemContext:Ljava/util/logging/LogManager$LoggerContext;.namedLoggers:Ljava/util/Hashtable;.table:[Ljava/util/Hashtable$HashtableEntry; 118
+Landroid/ddm/DdmHandleAppName; 118
+Landroid/provider/DeviceConfigInitializer; 118
+Lsun/misc/Cleaner; 118
+Ldalvik/system/CloseGuard; 118
+Landroid/graphics/Typeface; 118
+Landroid/os/BinderProxy;.sProxyMap:Landroid/os/BinderProxy$ProxyMap;.mMainIndexKeys:[[Ljava/lang/Long; 118
+Landroid/permission/PermissionManager; 118
+Landroid/media/MediaFrameworkPlatformInitializer; 118
+Ljava/util/TimeZone; 118
+Landroid/os/Environment; 118
+Landroid/compat/Compatibility; 118
+Landroid/os/ServiceManager; 118
+Landroid/content/pm/PackageManager;.sApplicationInfoCache:Landroid/app/PropertyInvalidatedCache; 118
+Ljava/util/Locale$NoImagePreloadHolder; 118
+Ljava/lang/System; 118
+Lcom/android/internal/os/RuntimeInit; 118
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.systemContext:Ljava/util/logging/LogManager$LoggerContext;.namedLoggers:Ljava/util/Hashtable; 118
+Ldalvik/system/VMRuntime;.THE_ONE:Ldalvik/system/VMRuntime; 118
+Landroid/view/View; 118
+Landroid/hardware/display/DisplayManagerGlobal; 118
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager; 118
+Landroid/telephony/TelephonyFrameworkInitializer; 118
+Landroid/se/omapi/SeFrameworkInitializer; 118
+Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap;.mHashes:[I 118
+Landroid/security/net/config/SystemCertificateSource$NoPreloadHolder; 118
+Landroid/security/net/config/ApplicationConfig; 118
+Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map; 118
+Ljava/util/Locale; 118
+Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map;.table:[Ljava/util/WeakHashMap$Entry; 118
+Ljava/security/Provider; 118
+Ldalvik/system/ZygoteHooks; 118
+Landroid/os/Message; 118
+Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object; 118
+Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap; 118
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap; 118
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.userContext:Ljava/util/logging/LogManager$LoggerContext;.namedLoggers:Ljava/util/Hashtable; 118
+Ljava/lang/ThreadGroup;.mainThreadGroup:Ljava/lang/ThreadGroup; 118
+Ldalvik/system/RuntimeHooks; 118
+Landroid/nfc/NfcFrameworkInitializer; 118
+Landroid/os/Looper; 118
+Landroid/os/LocaleList; 118
+Ldalvik/system/SocketTagger; 118
+Landroid/icu/util/TimeZone; 118
+Landroid/util/ArraySet; 118
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.systemContext:Ljava/util/logging/LogManager$LoggerContext;.root:Ljava/util/logging/LogManager$LogNode; 118
+Landroid/os/BinderProxy;.sProxyMap:Landroid/os/BinderProxy$ProxyMap;.mMainIndexValues:[Ljava/util/ArrayList; 118
+Ljava/util/Random;.seedUniquifier:Ljava/util/concurrent/atomic/AtomicLong; 118
+Landroid/app/ActivityThread; 118
+Landroid/os/Binder; 118
+Ljava/lang/ThreadLocal;.nextHashCode:Ljava/util/concurrent/atomic/AtomicInteger; 119
+Landroid/os/Parcel; 120
+Landroid/system/UnixSocketAddress; 120
+Ljava/lang/ThreadGroup;.systemThreadGroup:Ljava/lang/ThreadGroup; 120
+Ljava/lang/Daemons$FinalizerDaemon;.INSTANCE:Ljava/lang/Daemons$FinalizerDaemon; 120
+Landroid/os/Parcel;.sPairedCreators:Ljava/util/HashMap; 120
+Ljava/lang/Thread; 120
+Landroid/os/Parcel;.mCreators:Ljava/util/HashMap; 120
+Ljava/lang/Daemons$FinalizerDaemon;.INSTANCE:Ljava/lang/Daemons$FinalizerDaemon;.progressCounter:Ljava/util/concurrent/atomic/AtomicInteger; 120
+Landroid/system/StructPollfd; 120
+Ljava/lang/Daemons$HeapTaskDaemon;.INSTANCE:Ljava/lang/Daemons$HeapTaskDaemon; 120
+Landroid/system/StructTimeval; 120
+Ldalvik/system/VMRuntime;.THE_ONE:Ldalvik/system/VMRuntime;.allocationCount:Ljava/util/concurrent/atomic/AtomicInteger; 120
+Ljava/lang/Daemons$ReferenceQueueDaemon;.INSTANCE:Ljava/lang/Daemons$ReferenceQueueDaemon;.progressCounter:Ljava/util/concurrent/atomic/AtomicInteger; 120
+Landroid/os/GraphicsEnvironment;.sInstance:Landroid/os/GraphicsEnvironment; 120
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;.INSTANCE:Ljava/lang/Daemons$FinalizerWatchdogDaemon; 120
+Ljava/lang/ref/FinalizerReference; 120
+Landroid/os/Process; 120
+Ljava/lang/Daemons$ReferenceQueueDaemon;.INSTANCE:Ljava/lang/Daemons$ReferenceQueueDaemon; 120
+Lcom/android/internal/os/BinderInternal; 120
+Landroid/app/ApplicationLoaders;.gApplicationLoaders:Landroid/app/ApplicationLoaders;.mLoaders:Landroid/util/ArrayMap; 121
+Landroid/app/DexLoadReporter;.INSTANCE:Landroid/app/DexLoadReporter;.mDataDirs:Ljava/util/Set;.map:Ljava/util/HashMap; 122
+Ldalvik/system/BaseDexClassLoader; 122
+Landroid/renderscript/RenderScriptCacheDir; 122
+Landroid/graphics/Compatibility; 123
+Llibcore/io/Libcore; 123
+Landroid/provider/FontsContract; 123
+Ljava/security/Security;.version:Ljava/util/concurrent/atomic/AtomicInteger; 123
+Llibcore/net/NetworkSecurityPolicy; 123
+Lsun/security/jca/Providers; 123
+Landroid/graphics/Canvas; 123
+Landroid/os/StrictMode; 124
+Landroid/content/pm/PackageManager;.sPackageInfoCache:Landroid/app/PropertyInvalidatedCache; 125
+Lcom/android/internal/os/StatsdHiddenApiUsageLogger;.sInstance:Lcom/android/internal/os/StatsdHiddenApiUsageLogger; 126
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.loggerRefQueue:Ljava/lang/ref/ReferenceQueue; 127
+Landroid/view/WindowManagerGlobal; 128
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool; 129
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;.mPool:[Ljava/lang/Object; 129
+Landroid/view/inputmethod/InputMethodManager; 130
+Landroid/media/MediaRouter; 131
+Landroid/hardware/SensorPrivacyManager; 132
+Landroid/os/storage/StorageManager; 133
+Landroid/view/contentcapture/ContentCaptureManager; 134
+Landroid/hardware/input/InputManager; 134
+Landroid/app/people/PeopleManager; 134
+Landroid/media/session/MediaSessionManager; 134
+Landroid/security/attestationverification/AttestationVerificationManager; 134
+Landroid/net/vcn/VcnManager; 134
+Landroid/os/RecoverySystem; 134
+Landroid/net/NetworkPolicyManager; 134
+Landroid/net/wifi/sharedconnectivity/app/SharedConnectivityManager; 134
+Landroid/permission/PermissionControllerManager; 134
+Landroid/app/tare/EconomyManager; 134
+Landroid/view/translation/TranslationManager; 134
+Landroid/view/textclassifier/TextClassificationManager; 134
+Landroid/view/autofill/AutofillManager; 134
+Landroid/os/SystemConfigManager; 134
+Landroid/view/LayoutInflater; 134
+Landroid/credentials/CredentialManager; 134
+Landroid/service/persistentdata/PersistentDataBlockManager; 134
+Landroid/view/textservice/TextServicesManager; 134
+Landroid/app/admin/DevicePolicyManager; 134
+Ljava/lang/StackStreamFactory; 134
+Landroid/view/WindowManager; 134
+Landroid/app/contentsuggestions/ContentSuggestionsManager; 134
+Landroid/media/tv/tunerresourcemanager/TunerResourceManager; 134
+Landroid/telephony/SubscriptionManager; 134
+Landroid/os/HardwarePropertiesManager; 134
+Landroid/media/AudioManager; 135
+Landroid/telephony/TelephonyManager; 136
+Landroid/util/ArrayMap; 137
+Landroid/app/QueuedWork; 138
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.0:Ljava/util/WeakHashMap$Entry; 139
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap; 140
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;.sequencer:Ljava/util/concurrent/atomic/AtomicLong; 141
+Landroid/util/Log; 142
+Ljava/util/Collections$SynchronizedCollection; 143
+Ljava/util/Set; 143
+Ljava/util/Collections$SynchronizedSet; 143
+Ljava/util/Collection; 143
+Ljava/lang/Integer;.SMALL_NONNEG_VALUES:[Ljava/lang/String; 144
+Landroid/content/ComponentName; 145
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle; 146
+Landroid/os/PersistableBundle;.EMPTY:Landroid/os/PersistableBundle; 147
+Landroid/icu/impl/locale/BaseLocale;.CACHE:Landroid/icu/impl/locale/BaseLocale$Cache;._map:Ljava/util/concurrent/ConcurrentHashMap; 148
+Ljava/util/GregorianCalendar; 149
+Ljava/text/DontCareFieldPosition;.INSTANCE:Ljava/text/FieldPosition; 150
+Landroid/app/UiModeManager; 151
+Ljdk/internal/access/SharedSecrets; 152
+Landroid/icu/impl/ZoneMeta;.CANONICAL_ID_CACHE:Landroid/icu/impl/ICUCache; 153
+Landroid/icu/impl/ZoneMeta;.SYSTEM_ZONE_CACHE:Landroid/icu/impl/ZoneMeta$SystemTimeZoneCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 154
+Ljava/time/ZoneOffset;.ID_CACHE:Ljava/util/concurrent/ConcurrentMap; 155
+Ljava/time/ZoneOffset;.ID_CACHE:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 155
+Ljava/time/ZoneOffset;.SECONDS_CACHE:Ljava/util/concurrent/ConcurrentMap; 155
+Ljava/time/ZoneOffset;.SECONDS_CACHE:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.0:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 155
+Ljava/time/ZoneOffset;.SECONDS_CACHE:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 155
+Landroid/widget/TextView; 156
+Landroid/view/ViewGroup$ChildListForAutoFillOrContentCapture;.sPool:Landroid/util/Pools$SimplePool;.mPool:[Ljava/lang/Object; 157
+Landroid/view/ViewGroup$ChildListForAutoFillOrContentCapture;.sPool:Landroid/util/Pools$SimplePool; 157
+Landroid/view/ViewGroup; 158
+Landroid/graphics/Rect; 159
+Landroid/view/View$BaseSavedState; 160
+Landroid/widget/Button; 161
+Landroid/widget/ImageButton; 162
+Landroid/view/View$OnHoverListener; 163
+Landroid/widget/Toolbar; 164
+Landroid/hardware/display/ColorDisplayManager$ColorDisplayManagerInternal; 165
+Landroid/app/WallpaperManager; 166
+Landroid/graphics/ColorSpace$Model;.RGB:Landroid/graphics/ColorSpace$Model; 166
+Landroid/graphics/drawable/AdaptiveIconDrawable; 167
+Landroid/animation/ValueAnimator$DurationScaleChangeListener; 168
+Landroid/widget/Toast; 168
+Landroid/app/smartspace/SmartspaceSession$OnTargetsAvailableListener; 168
+Landroid/view/CrossWindowBlurListeners; 168
+Landroid/app/servertransaction/ActivityRelaunchItem; 169
+[Ljava/util/concurrent/ForkJoinTask; 169
+Landroid/view/WindowManager$LayoutParams; 169
+Ljava/util/concurrent/ForkJoinPool$WorkQueue; 169
+Landroid/app/prediction/AppTargetEvent; 169
+Lorg/xmlpull/v1/XmlPullParserException; 169
+Landroid/app/servertransaction/ObjectPool;.sPoolMap:Ljava/util/Map; 170
+Landroid/app/servertransaction/ClientTransaction; 170
+Landroid/app/servertransaction/StopActivityItem; 170
+Landroid/system/ErrnoException; 171
+Landroid/hardware/location/ContextHubTransaction$OnCompleteListener; 172
+Landroid/app/PendingIntent$OnFinished; 172
+Ljava/lang/NullPointerException; 173
+Landroid/os/strictmode/DiskReadViolation; 174
+Lorg/apache/http/params/HttpParams; 175
+Landroid/nfc/cardemulation/CardEmulation; 176
+Ljava/io/FileDescriptor; 177
+Landroid/content/pm/PackageManager$OnPermissionsChangedListener; 178
+Landroid/security/keystore2/KeyStoreCryptoOperationUtils; 179
+Landroid/app/ActivityTaskManager; 180
+Landroid/util/EventLog; 181
+Ljava/net/URLConnection; 181
+Ljava/net/SocketException; 181
+Ljava/lang/reflect/InvocationTargetException; 181
+Ljava/lang/Enum; 182
+Landroid/widget/AbsListView$SelectionBoundsAdjuster; 183
+Ljava/lang/ClassNotFoundException; 183
+Landroid/content/SyncStatusObserver; 184
+Landroid/content/AsyncTaskLoader$LoadTask; 185
+Landroid/app/LoaderManager$LoaderCallbacks; 185
+Landroid/webkit/CookieSyncManager; 186
+Landroid/webkit/WebViewProvider$ViewDelegate; 187
+Landroid/webkit/WebView; 187
+Landroid/webkit/WebViewProvider$ScrollDelegate; 187
+Landroid/webkit/WebViewProvider; 187
+Landroid/webkit/WebViewFactory;.sTimestamps:Landroid/webkit/WebViewFactory$StartupTimestamps; 188
+Landroid/webkit/WebViewFactoryProvider; 189
+Landroid/webkit/WebViewFactory; 190
+Landroid/os/PowerManager$OnThermalStatusChangedListener; 191
+Landroid/os/Bundle; 192
+Landroid/widget/ProgressBar; 193
+Landroid/graphics/Bitmap$Config;.ALPHA_8:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/Bitmap$Config;.RGB_565:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/Bitmap$Config;.RGBA_1010102:Landroid/graphics/Bitmap$Config; 194
+Landroid/renderscript/Allocation;.mBitmapOptions:Landroid/graphics/BitmapFactory$Options;.inPreferredConfig:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/Bitmap$Config;.RGBA_F16:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/Bitmap$Config;.ARGB_4444:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/Bitmap$Config;.HARDWARE:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/drawable/StateListDrawable; 195
+Landroid/view/PointerIcon;.gSystemIconsByDisplay:Landroid/util/SparseArray; 196
+Landroid/view/PointerIcon; 196
+Ljavax/net/ssl/SSLServerSocketFactory; 197
+Ljavax/net/ssl/SSLSocketFactory; 198
+Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder; 198
+Ljavax/net/ssl/SSLSessionContext; 199
+Lcom/android/org/bouncycastle/crypto/CryptoServicesRegistrar; 200
+Lsun/security/x509/PKIXExtensions;.KeyUsage_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/x509/PKIXExtensions;.PolicyConstraints_Id:Lsun/security/util/ObjectIdentifier; 201
+Ljava/security/cert/PKIXRevocationChecker$Option;.ONLY_END_ENTITY:Ljava/security/cert/PKIXRevocationChecker$Option; 201
+Lsun/security/x509/PKIXExtensions;.ExtendedKeyUsage_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/provider/X509Factory;.certCache:Lsun/security/util/Cache; 201
+Lsun/security/x509/PKIXExtensions;.CertificatePolicies_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/x509/PKIXExtensions;.NameConstraints_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/x509/PKIXExtensions;.AuthorityKey_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/provider/X509Factory;.certCache:Lsun/security/util/Cache;.cacheMap:Ljava/util/Map; 201
+Ljava/security/cert/PKIXRevocationChecker$Option;.NO_FALLBACK:Ljava/security/cert/PKIXRevocationChecker$Option; 201
+Lsun/security/x509/PKIXExtensions;.SubjectAlternativeName_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/x509/PKIXExtensions;.PolicyMappings_Id:Lsun/security/util/ObjectIdentifier; 202
+Lsun/security/x509/PKIXExtensions;.InhibitAnyPolicy_Id:Lsun/security/util/ObjectIdentifier; 202
+Lsun/security/x509/PKIXExtensions;.BasicConstraints_Id:Lsun/security/util/ObjectIdentifier; 202
+Ljava/security/Security;.spiMap:Ljava/util/Map; 203
+Lsun/security/x509/X500Name;.commonName_oid:Lsun/security/util/ObjectIdentifier; 204
+Lsun/security/x509/X500Name;.countryName_oid:Lsun/security/util/ObjectIdentifier; 204
+Lsun/security/x509/X500Name;.orgName_oid:Lsun/security/util/ObjectIdentifier; 204
+Ljava/nio/charset/Charset;.cache2:Ljava/util/HashMap; 205
+Ljava/net/URL;.handlers:Ljava/util/Hashtable;.table:[Ljava/util/Hashtable$HashtableEntry; 206
+Ljava/net/URL;.handlers:Ljava/util/Hashtable; 206
+Ljava/net/Inet6AddressImpl;.addressCache:Ljava/net/AddressCache;.cache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap; 207
+Ljava/net/Proxy$Type;.DIRECT:Ljava/net/Proxy$Type; 208
+Ljava/net/ProxySelector;.theProxySelector:Ljava/net/ProxySelector; 208
+Lcom/android/okhttp/okio/SegmentPool; 209
+Lcom/android/okhttp/internal/http/AuthenticatorAdapter;.INSTANCE:Lcom/android/okhttp/Authenticator; 209
+Lcom/android/okhttp/HttpsHandler;.HTTP_1_1_ONLY:Ljava/util/List;.element:Ljava/lang/Object; 209
+Lcom/android/okhttp/ConfigAwareConnectionPool;.instance:Lcom/android/okhttp/ConfigAwareConnectionPool;.networkEventDispatcher:Llibcore/net/event/NetworkEventDispatcher;.listeners:Ljava/util/List; 210
+Lcom/android/okhttp/Dns;.SYSTEM:Lcom/android/okhttp/Dns; 210
+Lcom/android/okhttp/ConfigAwareConnectionPool;.instance:Lcom/android/okhttp/ConfigAwareConnectionPool; 210
+Lcom/android/okhttp/okio/AsyncTimeout; 211
+Ljava/lang/IllegalAccessException; 212
+Ljavax/net/ssl/SSLContext; 213
+Ljavax/net/ssl/HttpsURLConnection; 213
+Ljava/security/Security;.props:Ljava/util/Properties;.map:Ljava/util/concurrent/ConcurrentHashMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.12:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 214
+Ljava/security/Security;.props:Ljava/util/Properties;.map:Ljava/util/concurrent/ConcurrentHashMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.30:Ljava/util/concurrent/ConcurrentHashMap$Node; 214
+Landroid/database/sqlite/SQLiteTransactionListener; 215
+Landroid/accounts/OnAccountsUpdateListener; 216
+Landroid/accounts/AccountManager$20; 217
+Lsun/nio/ch/FileChannelImpl$Unmapper; 218
+Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map;.queue:Ljava/lang/ref/ReferenceQueue; 219
+Landroid/text/method/SingleLineTransformationMethod; 220
+Landroid/widget/RelativeLayout; 221
+Landroid/graphics/drawable/BitmapDrawable; 222
+Landroid/graphics/drawable/GradientDrawable; 223
+Landroid/animation/PropertyValuesHolder;.sGetterPropertyMap:Ljava/util/HashMap; 224
+Landroid/animation/PropertyValuesHolder$FloatPropertyValuesHolder;.sJNISetterPropertyMap:Ljava/util/HashMap; 225
+Landroid/graphics/drawable/Drawable;.DEFAULT_TINT_MODE:Landroid/graphics/PorterDuff$Mode; 226
+Landroid/text/StaticLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool; 227
+Landroid/text/StaticLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 227
+Ljava/util/concurrent/ThreadLocalRandom; 228
+Landroid/widget/Space; 229
+Landroid/widget/ScrollView; 230
+Landroid/text/style/LineHeightSpan; 231
+Landroid/text/style/TabStopSpan; 232
+Landroid/text/style/ReplacementSpan; 233
+Landroid/text/style/MetricAffectingSpan; 233
+Landroid/text/style/LeadingMarginSpan; 233
+Landroid/text/style/LineBackgroundSpan; 234
+Landroid/text/style/CharacterStyle; 235
+Landroid/text/style/SuggestionSpan; 236
+Landroid/widget/TextView$ChangeWatcher; 237
+Landroid/text/DynamicLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 238
+Landroid/text/DynamicLayout; 238
+Landroid/text/DynamicLayout$ChangeWatcher; 238
+Landroid/text/style/WrapTogetherSpan; 238
+Landroid/text/DynamicLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool; 238
+Landroid/text/method/LinkMovementMethod; 239
+Landroid/text/style/ClickableSpan; 240
+Ljava/util/logging/LogRecord;.globalSequenceNumber:Ljava/util/concurrent/atomic/AtomicLong; 241
+Ljava/lang/Runtime;.currentRuntime:Ljava/lang/Runtime; 242
+Landroid/content/pm/LauncherActivityInfo; 243
+Landroid/database/sqlite/SQLiteMisuseException; 243
+Landroid/speech/tts/TextToSpeech$Connection$SetupConnectionAsyncTask; 243
+Landroid/database/sqlite/SQLiteCantOpenDatabaseException; 243
+Landroid/database/sqlite/SQLiteDatabaseCorruptException; 243
+Landroid/database/sqlite/SQLiteDatabaseLockedException; 243
+Ljava/util/Map$Entry; 243
+Ljava/util/zip/ZipException; 243
+Landroid/database/sqlite/SQLiteAccessPermException; 243
+Landroid/speech/tts/TextToSpeech$OnInitListener; 243
+Landroid/app/Notification$MessagingStyle; 244
+Landroid/text/TextUtils$TruncateAt; 245
+Landroid/app/smartspace/SmartspaceTarget; 246
+Landroid/app/prediction/AppTarget; 246
+Landroid/app/smartspace/uitemplatedata/BaseTemplateData; 246
+Landroid/location/LocationManager;.sLocationListeners:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry; 247
+Landroid/location/LocationManager;.sLocationListeners:Ljava/util/WeakHashMap; 247
+Landroid/service/notification/ConditionProviderService; 248
+Landroid/os/WorkSource; 249
+Landroid/security/keystore2/AndroidKeyStoreProvider; 249
+Ljava/net/Socket; 249
+Lcom/android/internal/listeners/ListenerTransport; 249
+Landroid/os/ParcelUuid; 250
+Landroid/telephony/emergency/EmergencyNumber; 251
+Lcom/android/internal/telephony/uicc/UiccProfile$4; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$IncomingSms; 251
+Lcom/android/internal/telephony/SmsStorageMonitor$1; 251
+Lcom/android/internal/telephony/TelephonyDevController; 251
+Lcom/android/internal/telephony/uicc/UiccController; 251
+Lcom/android/internal/telephony/emergency/EmergencyNumberTracker$1; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$DataCallSession; 251
+Lcom/android/internal/telephony/TelephonyDevController;.mSims:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsAcsProvisioningStats; 251
+Ljava/lang/UnsupportedOperationException; 251
+Landroid/database/CursorToBulkCursorAdaptor; 251
+Lcom/android/internal/telephony/satellite/PointingAppController; 251
+Landroid/telephony/ModemActivityInfo; 251
+Lcom/android/internal/telephony/imsphone/ImsPhone; 251
+Lcom/android/internal/telephony/ServiceStateTracker; 251
+Lcom/android/internal/telephony/IccSmsInterfaceManager; 251
+Lcom/android/internal/telephony/util/NotificationChannelController$1; 251
+Lcom/android/internal/telephony/RilWakelockInfo; 251
+Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler$GsmCbTestBroadcastReceiver; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportFeatureTagStats; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$UceEventStats; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$BindingState; 251
+Lcom/android/internal/telephony/ims/ImsResolver$3; 251
+Landroid/net/NetworkPolicyManager$SubscriptionCallbackProxy; 251
+Lcom/android/internal/telephony/TelephonyDevController;.mModems:Ljava/util/ArrayList; 251
+Landroid/telephony/ims/aidl/IImsServiceController$Stub$Proxy; 251
+Lcom/android/internal/telephony/CarrierPrivilegesTracker$1; 251
+Lcom/android/internal/telephony/CommandException; 251
+Lcom/android/ims/FeatureConnector$1; 251
+Lcom/android/internal/telephony/IWapPushManager; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipDelegateStats; 251
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mTtyModeReceivedRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mMmiCompleteRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/i18n/timezone/TelephonyLookup; 251
+Landroid/telephony/BarringInfo$BarringServiceInfo; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequests; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$ConnectedState$14; 251
+Lcom/android/internal/telephony/SmsBroadcastUndelivered; 251
+Lcom/android/internal/telephony/LocaleTracker; 251
+Lcom/android/internal/telephony/PhoneSubInfoController; 251
+Lcom/android/internal/telephony/CarrierKeyDownloadManager$1; 251
+Lcom/android/internal/telephony/GsmCdmaCallTracker$1; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.339:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/ServiceStateTracker$1; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.353:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/euicc/EuiccCardController$SimSlotStatusChangedBroadcastReceiver; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$PresenceNotifyEvent; 251
+Lcom/android/internal/telephony/SimActivationTracker$1; 251
+Landroid/telephony/ModemInfo; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1393:[Ljava/lang/String; 251
+Landroid/telephony/CellSignalStrengthWcdma; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteProvision; 251
+Lcom/android/internal/telephony/PhoneConfigurationManager; 251
+Lcom/android/internal/telephony/SmsApplication$SmsPackageMonitor; 251
+Landroid/telephony/TelephonyRegistryManager$3; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallSession; 251
+Landroid/os/Handler$MessengerImpl; 251
+Lcom/android/internal/telephony/LocaleTracker$1; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularDataServiceSwitch; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mInCallVoicePrivacyOffRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSosMessageRecommender; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationServiceDescStats; 251
+Lcom/android/internal/telephony/uicc/UiccPkcs15$Pkcs15Selector; 251
+Lcom/android/internal/telephony/CarrierResolver$2; 251
+Lcom/android/internal/telephony/CarrierActionAgent$1; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mPhones:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/SmsController; 251
+Lcom/android/internal/telephony/uicc/euicc/EuiccCardException; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationTermination; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1125:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/NetworkTypeController$1; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.803:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/uicc/asn1/TagNotFoundException; 251
+Lcom/android/internal/telephony/CarrierServiceBindHelper$1; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularServiceState; 251
+Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager; 251
+Lcom/android/internal/telephony/InboundSmsHandler$NewMessageNotificationActionReceiver; 251
+Lcom/android/internal/telephony/CarrierActionAgent; 251
+Lcom/android/i18n/timezone/TimeZoneFinder; 251
+Lcom/android/internal/telephony/RILRequest; 251
+Lcom/android/internal/telephony/RIL;.sRilTimeHistograms:Landroid/util/SparseArray; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.33:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/MccTable; 251
+Lcom/android/internal/telephony/uicc/UiccProfile$2; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CarrierIdMismatch; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1235:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules; 251
+Landroid/telephony/CellSignalStrengthTdscdma; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerListenerEvent; 251
+Lcom/android/internal/telephony/SmsDispatchersController; 251
+Landroid/timezone/TelephonyLookup; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteOutgoingDatagram; 251
+Lcom/android/internal/telephony/SMSDispatcher$1; 251
+Lcom/android/internal/telephony/AppSmsManager; 251
+Landroid/timezone/TimeZoneFinder; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mBackgroundCalls:Ljava/util/ArrayList; 251
+Lcom/android/ims/rcs/uce/eab/EabProvider; 251
+Lcom/android/internal/telephony/uicc/PinStorage$1; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerEvent; 251
+Landroid/telephony/CellSignalStrengthLte; 251
+Landroid/telephony/ims/ProvisioningManager$Callback$CallbackBinder; 251
+Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray;.mKeys:[I 251
+Landroid/telephony/CellSignalStrengthNr; 251
+Lcom/android/internal/telephony/SomeArgs; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mInCallVoicePrivacyOnRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/StateMachine$SmHandler; 251
+Lcom/android/internal/telephony/PackageChangeReceiver; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingShortCodeSms; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequestsV2; 251
+Lcom/android/internal/telephony/nano/TelephonyProto$RilDataCall; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$AvailableState; 251
+Lcom/android/ims/internal/IImsServiceFeatureCallback$Stub$Proxy; 251
+Landroid/telephony/data/ApnSetting;.APN_TYPE_INT_MAP:Ljava/util/Map; 251
+Lcom/android/internal/telephony/RadioInterfaceCapabilityController; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationStats; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallRatUsage; 251
+Lcom/android/internal/telephony/metrics/TelephonyMetrics; 251
+Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyCallSession$Event$RilCall; 251
+Lcom/android/internal/telephony/NetworkRegistrationManager$NetworkRegStateCallback; 251
+Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$ConnectedState; 251
+Lcom/android/internal/telephony/RadioConfig; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$DisconnectedState; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSession; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mDisplayInfoRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/phone/ecc/nano/ProtobufEccData$EccInfo; 251
+Lcom/android/internal/telephony/GsmCdmaPhone; 251
+Lcom/android/internal/telephony/TelephonyTester$1; 251
+Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler$CdmaScpTestBroadcastReceiver; 251
+Lcom/android/internal/telephony/NetworkTypeController$DefaultState; 251
+Landroid/net/TelephonyNetworkSpecifier; 251
+Lcom/android/internal/telephony/NitzStateMachine; 251
+Landroid/app/timezonedetector/TimeZoneDetector; 251
+Lcom/android/internal/telephony/IntentBroadcaster$1; 251
+Lcom/android/internal/telephony/uicc/UiccStateChangedLauncher; 251
+Lcom/android/internal/telephony/ims/ImsResolver$1; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingSms; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$UnmeteredNetworks; 251
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader;.packages:Ljava/util/Map;.m:Ljava/util/Map; 251
+Lcom/android/internal/telephony/euicc/EuiccController; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mForegroundCalls:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/satellite/SatelliteModemInterface; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.531:[Ljava/lang/String; 251
+Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$1; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.467:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipMessageResponse; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportSession; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$UnavailableState; 251
+Lcom/android/internal/telephony/DeviceStateMonitor$3; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mSignalInfoRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 251
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager; 251
+Lcom/android/internal/telephony/DisplayInfoController; 251
+Lcom/android/internal/telephony/ims/ImsResolver$2; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1377:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyServiceState$NetworkRegistrationInfo; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteController; 251
+Landroid/telephony/ims/RegistrationManager$RegistrationCallback$RegistrationBinder; 251
+Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$EmergencyNumbersInfo; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$GbaEvent; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.23:[Ljava/lang/String; 251
+Landroid/telephony/CellSignalStrengthCdma; 251
+Landroid/telephony/TelephonyLocalConnection; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteIncomingDatagram; 251
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker$2; 251
+Lcom/android/internal/telephony/ims/ImsResolver; 251
+Lcom/android/internal/telephony/SmsStorageMonitor; 251
+Lcom/android/internal/telephony/uicc/UiccProfile; 251
+Landroid/telephony/ims/ImsMmTelManager$CapabilityCallback$CapabilityBinder; 251
+Lcom/android/internal/telephony/euicc/EuiccCardController; 251
+Lcom/android/internal/telephony/SmsBroadcastUndelivered$1; 251
+Lcom/android/internal/telephony/GsmCdmaCallTracker; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsClientProvisioningStats; 251
+Lcom/android/internal/telephony/cat/CatService; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.761:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/SmsApplication; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mDisconnectRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/PhoneFactory; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mHandlerMap:Ljava/util/HashMap; 251
+Landroid/os/AsyncResult; 251
+Lcom/android/internal/telephony/ProxyController; 251
+Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler$CdmaCbTestBroadcastReceiver; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.453:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/MultiSimSettingController; 251
+Ljava/io/BufferedReader; 251
+Landroid/telephony/CellSignalStrengthGsm; 251
+Lcom/android/internal/telephony/SimActivationTracker; 251
+Lcom/android/internal/telephony/CellBroadcastServiceManager; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mRingingCalls:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/IntentBroadcaster; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationFeatureTagStats; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$EuiccPackageMonitor; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mSuppServiceFailedRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader;.packages:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node; 251
+Lcom/android/internal/telephony/CarrierServiceBindHelper$CarrierServicePackageMonitor; 251
+Lcom/android/internal/telephony/TelephonyComponentFactory; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.637:[Ljava/lang/String; 251
+Lcom/android/phone/ecc/nano/ProtobufEccData$CountryInfo; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.651:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/SmsUsageMonitor; 251
+Lcom/android/internal/telephony/CommandException$Error;.INVALID_SIM_STATE:Lcom/android/internal/telephony/CommandException$Error; 251
+Landroid/hardware/display/DisplayManagerGlobal$DisplayManagerCallback; 252
+Landroid/app/ActivityThread$ApplicationThread; 252
+Landroid/app/ActivityManager$MyUidObserver; 253
+Landroid/media/browse/MediaBrowser$ServiceCallbacks; 253
+Landroid/media/session/MediaController$CallbackStub; 253
+Landroid/media/session/MediaSessionManager$OnMediaKeyEventSessionChangedListener; 253
+Landroid/app/PendingIntent$CancelListener; 253
+Landroid/media/AudioManager$2; 253
+Landroid/database/ContentObserver$Transport; 253
+Landroid/media/session/MediaSessionManager$SessionsChangedWrapper$1; 253
+Landroid/content/ContentProvider$PipeDataWriter; 254
+Landroid/security/net/config/UserCertificateSource$NoPreloadHolder; 255
+Landroid/view/Window$Callback; 256
+Landroid/transition/TransitionManager;.sDefaultTransition:Landroid/transition/Transition;.mTransitions:Ljava/util/ArrayList;.elementData:[Ljava/lang/Object;.1:Landroid/transition/ChangeBounds;.mCurrentAnimators:Ljava/util/ArrayList; 256
+Landroid/transition/TransitionManager;.sDefaultTransition:Landroid/transition/Transition;.mTransitions:Ljava/util/ArrayList;.elementData:[Ljava/lang/Object;.2:Landroid/transition/Fade;.mCurrentAnimators:Ljava/util/ArrayList; 256
+Landroid/transition/TransitionManager;.sPendingTransitions:Ljava/util/ArrayList; 256
+Landroid/transition/TransitionManager;.sDefaultTransition:Landroid/transition/Transition;.mTransitions:Ljava/util/ArrayList;.elementData:[Ljava/lang/Object;.0:Landroid/transition/Fade;.mCurrentAnimators:Ljava/util/ArrayList; 256
+Landroid/view/AttachedSurfaceControl$OnBufferTransformHintChangedListener; 257
+Landroid/webkit/ValueCallback; 258
+Landroid/webkit/WebResourceRequest; 258
+Landroid/webkit/WebChromeClient$CustomViewCallback; 258
+Landroid/hardware/camera2/CameraCharacteristics;.INFO_SUPPORTED_HARDWARE_LEVEL:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 258
+Landroid/accounts/Account; 258
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 258
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/params/StreamConfigurationDuration; 259
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/params/HighSpeedVideoConfiguration; 259
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+I 259
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_CAPABILITIES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/params/StreamConfiguration; 259
+Z 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PIXEL_ARRAY_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.LENS_FOCAL_LENGTH:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_APERTURES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.DISTORTION_CORRECTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.EXTENSION_STRENGTH:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+J 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PHYSICAL_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.TONEMAP_PRESET_CURVE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+B 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_TRIGGER:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_EXPOSURE_COMPENSATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+[D 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_SESSION_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_EXPOSURE_TIME:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_CALIBRATION_TRANSFORM2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_TRANSFORM:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/content/res/Resources$Theme; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+F 260
+Landroid/hardware/camera2/CaptureRequest;.LENS_FILTER_DENSITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.LENS_OPTICAL_STABILIZATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.NOISE_REDUCTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_FRAME_DURATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_EXTENDED_SCENE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_OIS_DATA_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_TEST_PATTERN_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.HOT_PIXEL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_ANTIBANDING_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_LENS_SHADING_MAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SCALER_CROP_REGION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.LENS_FOCUS_DISTANCE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.TONEMAP_GAMMA:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_REFERENCE_ILLUMINANT2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_REFERENCE_ILLUMINANT1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+[F 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_ZOOM_RATIO:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_ABERRATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.TONEMAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_REQUEST_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SCALER_ROTATE_AND_CROP:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_GAINS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_COLOR_TRANSFORM1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_SENSITIVITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_FOCAL_LENGTHS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_OPTICAL_BLACK_REGIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.JPEG_QUALITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.FLASH_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_POST_RAW_SENSITIVITY_BOOST:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_WHITE_LEVEL:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_SETTINGS_OVERRIDE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+[Landroid/hardware/camera2/params/MeteringRectangle; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.LOGICAL_MULTI_CAMERA_PHYSICAL_IDS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_EXPOSURE_TIME_RANGE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Ljava/lang/Float; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_ENABLE_ZSL:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.INFO_DEVICE_STATE_ORIENTATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_CALIBRATION_TRANSFORM1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.EDGE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_CAPTURE_INTENT:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_ORIENTATION:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.JPEG_ORIENTATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_COLOR_TRANSFORM2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+[J 260
+Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Ljava/util/concurrent/Phaser; 260
+Landroid/hardware/camera2/CaptureRequest;.BLACK_LEVEL_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_SCENE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.JPEG_THUMBNAIL_SIZE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SHADING_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_FACE_DETECT_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_HOT_PIXEL_MAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AUTOFRAMING:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_TARGET_FPS_RANGE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_TEST_PATTERN_DATA:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_PRECAPTURE_TRIGGER:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.FLASH_STRENGTH_LEVEL:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_VIDEO_STABILIZATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Ljava/lang/Boolean; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_EFFECT_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.LENS_APERTURE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.JPEG_THUMBNAIL_QUALITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Ljava/lang/Long; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_PIXEL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+[Ljava/lang/String; 261
+[Z 262
+Ljava/lang/Class$Caches;.genericInterfaces:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap; 263
+Ljava/util/Map; 264
+Ljava/nio/Bits; 265
+Ljava/nio/DirectByteBuffer; 266
+Ljava/io/File; 267
+Ljava/nio/ByteBuffer; 268
+Ljava/io/InputStream; 269
+Landroid/os/ParcelFileDescriptor; 270
+Landroid/os/BinderProxy;.sProxyMap:Landroid/os/BinderProxy$ProxyMap; 271
+Landroid/app/PendingIntent; 272
+Landroid/content/Intent; 273
+Landroid/net/Uri$HierarchicalUri; 274
+Landroid/net/Uri$StringUri; 275
+Landroid/net/Uri$PathPart;.EMPTY:Landroid/net/Uri$PathPart; 276
+Lcom/android/internal/telephony/MccTable;.FALLBACKS:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.6:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 277
+Landroid/icu/text/DecimalFormatSymbols;.cachedLocaleData:Landroid/icu/impl/CacheBase;.map:Ljava/util/concurrent/ConcurrentHashMap; 278
+Llibcore/icu/DecimalFormatData;.CACHE:Ljava/util/concurrent/ConcurrentHashMap; 279
+Landroid/icu/impl/CurrencyData;.provider:Landroid/icu/impl/CurrencyData$CurrencyDisplayInfoProvider; 280
+Lcom/android/internal/infra/AndroidFuture; 281
+Lcom/android/internal/util/LatencyTracker$Action; 282
+Landroid/app/AppOpsManager$Mode; 283
+Landroid/view/accessibility/AccessibilityManager$AccessibilityServicesStateChangeListener; 284
+Landroid/annotation/IdRes; 285
+Landroid/content/pm/PackageItemInfo; 286
+Ljava/util/Random; 287
+Landroid/widget/RadioButton; 288
+Lcom/android/internal/policy/PhoneWindow$PanelFeatureState$SavedState; 289
+Landroid/graphics/Insets; 290
+Landroid/view/View;.sNextGeneratedId:Ljava/util/concurrent/atomic/AtomicInteger; 291
+Landroid/graphics/drawable/LayerDrawable; 292
+Landroid/animation/LayoutTransition; 293
+Llibcore/reflect/AnnotationFactory;.cache:Ljava/util/Map; 294
+Llibcore/reflect/AnnotationFactory;.cache:Ljava/util/Map;.table:[Ljava/util/WeakHashMap$Entry; 294
+Ljava/lang/reflect/Proxy;.proxyClassCache:Ljava/lang/reflect/WeakCache;.reverseMap:Ljava/util/concurrent/ConcurrentMap; 295
+Ljava/lang/reflect/Proxy$ProxyClassFactory;.nextUniqueNumber:Ljava/util/concurrent/atomic/AtomicLong; 295
+Ljava/lang/reflect/Proxy;.proxyClassCache:Ljava/lang/reflect/WeakCache;.map:Ljava/util/concurrent/ConcurrentMap; 296
+Ljava/lang/Object; 297
+Ljava/lang/invoke/MethodType;.internTable:Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;.map:Ljava/util/concurrent/ConcurrentMap; 298
+Ljava/nio/channels/SocketChannel;.dexCache:Ljava/lang/Object; 298
+Ljava/lang/invoke/MethodType;.objectOnlyTypes:[Ljava/lang/invoke/MethodType; 299
+Ljava/util/concurrent/ForkJoinTask; 300
+Ljava/util/concurrent/CompletableFuture; 301
+Landroid/app/Notification$BigTextStyle; 302
+Landroid/content/pm/ApplicationInfo; 303
+Ljava/security/Signature;.signatureInfo:Ljava/util/Map;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.13:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 304
+Lsun/security/x509/X500Name;.stateName_oid:Lsun/security/util/ObjectIdentifier; 305
+Lsun/security/x509/X500Name;.localityName_oid:Lsun/security/util/ObjectIdentifier; 306
+Lsun/security/x509/X500Name;.orgUnitName_oid:Lsun/security/util/ObjectIdentifier; 306
+Ljava/util/UUID; 307
+Landroid/app/slice/Slice; 308
+Ljava/util/Locale;.FRENCH:Ljava/util/Locale; 308
+Landroid/os/NullVibrator; 308
+Ldalvik/system/CloseGuard;.MESSAGE:Ljava/lang/String; 308
+Lsun/util/locale/BaseLocale$Cache;.CACHE:Lsun/util/locale/BaseLocale$Cache;.map:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.22:Ljava/util/concurrent/ConcurrentHashMap$Node;.val:Ljava/lang/Object;.referent:Ljava/lang/Object; 308
+Ljava/util/Locale$Cache;.LOCALECACHE:Ljava/util/Locale$Cache;.map:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.24:Ljava/util/concurrent/ConcurrentHashMap$Node;.val:Ljava/lang/Object;.referent:Ljava/lang/Object; 308
+Landroid/app/Activity$$ExternalSyntheticLambda0; 308
+Landroid/icu/impl/locale/BaseLocale;.CACHE:Landroid/icu/impl/locale/BaseLocale$Cache;._map:Ljava/util/concurrent/ConcurrentHashMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.0:Ljava/util/concurrent/ConcurrentHashMap$Node; 308
+Ljava/util/Locale;.ITALIAN:Ljava/util/Locale; 308
+Landroid/media/MediaRouter2Manager$Callback; 308
+Lsun/util/locale/BaseLocale$Cache;.CACHE:Lsun/util/locale/BaseLocale$Cache;.map:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.29:Ljava/util/concurrent/ConcurrentHashMap$Node;.val:Ljava/lang/Object;.referent:Ljava/lang/Object; 308
+Ljava/util/Locale;.GERMAN:Ljava/util/Locale; 309
+Landroid/icu/impl/StandardPlural; 310
+Landroid/icu/impl/number/range/StandardPluralRanges; 311
+Landroid/icu/impl/PluralRulesLoader;.loader:Landroid/icu/impl/PluralRulesLoader; 311
+Landroid/icu/impl/PluralRulesLoader;.loader:Landroid/icu/impl/PluralRulesLoader;.pluralRulesCache:Ljava/util/Map; 311
+Landroid/icu/text/PluralRules$Operand; 311
+Landroid/icu/util/Calendar;.PATTERN_CACHE:Landroid/icu/impl/ICUCache; 312
+Landroid/icu/impl/DateNumberFormat;.CACHE:Landroid/icu/impl/SimpleCache; 313
+Landroid/text/format/DateFormat; 314
+Landroid/view/View$OnDragListener; 315
+Landroid/hardware/input/InputManager$InputDeviceListener; 316
+Landroid/hardware/input/InputManagerGlobal; 317
+Landroid/hardware/SystemSensorManager; 318
+Lcom/android/internal/os/BackgroundThread; 319
+Ljava/lang/Throwable; 320
+Landroid/app/NotificationManager; 321
+Landroid/app/NotificationChannel; 322
+Landroid/content/SharedPreferences$OnSharedPreferenceChangeListener; 323
+Landroid/content/pm/VersionedPackage; 324
+Landroid/app/AppOpsManager; 325
+Ldalvik/system/ZipPathValidator; 326
+Landroid/content/pm/PackageManager;.sPackageInfoCache:Landroid/app/PropertyInvalidatedCache;.mSkips:[J 327
+Landroid/content/pm/PackageManager;.sApplicationInfoCache:Landroid/app/PropertyInvalidatedCache;.mSkips:[J 328
+Lsun/util/locale/BaseLocale$Cache;.CACHE:Lsun/util/locale/BaseLocale$Cache;.map:Ljava/util/concurrent/ConcurrentMap; 329
+Landroid/content/Context; 330
+Ljava/util/concurrent/Executor; 331
+Ljava/util/concurrent/ScheduledExecutorService; 332
+Ljava/util/concurrent/ExecutorService; 332
+Landroid/view/Window$OnFrameMetricsAvailableListener; 333
+Ljava/lang/annotation/Annotation; 334
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 335
+Ljava/util/concurrent/CancellationException; 336
+Ljava/lang/NoSuchMethodException; 337
+Landroid/os/strictmode/CustomViolation; 338
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.3:Ljava/util/WeakHashMap$Entry; 339
+Lcom/android/internal/policy/PhoneWindow; 340
+Landroid/view/autofill/AutofillValue; 340
+Landroid/widget/TextView$SavedState; 341
+Landroid/text/method/MetaKeyKeyListener;.SYM:Ljava/lang/Object; 342
+Landroid/text/method/MetaKeyKeyListener;.ALT:Ljava/lang/Object; 342
+Landroid/text/method/MetaKeyKeyListener;.SELECTING:Ljava/lang/Object; 342
+Landroid/text/method/MetaKeyKeyListener;.CAP:Ljava/lang/Object; 342
+Landroid/widget/PopupWindow$PopupBackgroundView; 343
+Landroid/widget/TextView;.TEMP_RECTF:Landroid/graphics/RectF; 343
+Landroid/text/method/ScrollingMovementMethod; 343
+Landroid/icu/impl/locale/UnicodeLocaleExtension;.EMPTY_SORTED_SET:Ljava/util/SortedSet;.m:Ljava/util/NavigableMap; 343
+Landroid/widget/PopupWindow$PopupDecorView; 343
+Landroid/widget/Editor$TextRenderNode; 343
+Landroid/widget/Editor$PositionListener; 344
+Landroid/text/style/SpellCheckSpan; 345
+Landroid/text/method/ArrowKeyMovementMethod; 346
+Landroid/text/method/TextKeyListener;.sInstance:[Landroid/text/method/TextKeyListener; 346
+Landroid/text/TextUtils$TruncateAt;.MARQUEE:Landroid/text/TextUtils$TruncateAt; 347
+Landroid/view/autofill/Helper; 348
+Lcom/android/internal/util/LatencyTracker; 349
+Lcom/android/internal/util/LatencyTracker$SLatencyTrackerHolder; 349
+Landroid/graphics/drawable/Icon; 350
+Landroid/text/style/AlignmentSpan; 351
+Landroid/text/MeasuredParagraph;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 352
+Landroid/text/MeasuredParagraph;.sPool:Landroid/util/Pools$SynchronizedPool; 352
+Landroid/icu/impl/ICUResourceBundleReader;.CACHE:Landroid/icu/impl/ICUResourceBundleReader$ReaderCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 353
+Landroid/location/ILocationManager$Stub;.dexCache:Ljava/lang/Object; 354
+Landroid/annotation/CurrentTimeMillisLong; 355
+Ljava/lang/reflect/Method; 356
+Lcom/android/internal/os/ZygoteInit; 356
+Landroid/database/DatabaseUtils; 356
+Landroid/os/HandlerThread; 356
+Ljava/security/Signature;.signatureInfo:Ljava/util/Map;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 357
+Ljava/security/Signature;.signatureInfo:Ljava/util/Map; 358
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.queue:Ljava/lang/ref/ReferenceQueue; 359
+Landroid/telephony/TelephonyRegistryManager; 360
+Landroid/graphics/HardwareRenderer; 361
+Landroid/os/BinderProxy; 362
+Landroid/app/compat/CompatChanges;.QUERY_CACHE:Landroid/app/compat/ChangeIdStateCache;.mCache:Ljava/util/LinkedHashMap; 363
+Landroid/app/compat/CompatChanges;.QUERY_CACHE:Landroid/app/compat/ChangeIdStateCache; 363
+Landroid/app/AlarmManager; 364
+Landroid/net/metrics/DhcpClientEvent; 365
+[I 366
+Landroid/media/MediaCodecList; 367
+Landroid/graphics/drawable/InsetDrawable; 368
+Landroid/widget/ProgressBar$SavedState; 369
+Landroid/widget/ScrollView$SavedState; 370
+Landroid/graphics/drawable/AnimatedVectorDrawable; 371
+Landroid/widget/ListView; 372
+Landroid/widget/AbsListView; 373
+Landroid/widget/AbsListView$SavedState; 373
+Landroid/widget/CompoundButton$SavedState; 374
+Landroid/widget/HorizontalScrollView$SavedState; 375
+Landroid/widget/HorizontalScrollView; 376
+Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.1:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 377
+Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.6:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 377
+Landroid/view/View$OnSystemUiVisibilityChangeListener; 378
+Ljava/util/AbstractMap; 379
+Landroid/telephony/euicc/EuiccCardManager$ResultCallback; 380
+Ljava/lang/Character$UnicodeBlock;.CJK_SYMBOLS_AND_PUNCTUATION:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.KANBUN:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.HANGUL_COMPATIBILITY_JAMO:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.KATAKANA:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.HANGUL_SYLLABLES:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.ENCLOSED_CJK_LETTERS_AND_MONTHS:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.HANGUL_JAMO:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.BOPOMOFO_EXTENDED:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY_FORMS:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.BOPOMOFO:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.HIRAGANA:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.HALFWIDTH_AND_FULLWIDTH_FORMS:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.KANGXI_RADICALS:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.CJK_RADICALS_SUPPLEMENT:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.KATAKANA_PHONETIC_EXTENSIONS:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT:Ljava/lang/Character$UnicodeBlock; 382
+Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY_IDEOGRAPHS:Ljava/lang/Character$UnicodeBlock; 382
+Ljava/lang/Character$UnicodeBlock;.CJK_UNIFIED_IDEOGRAPHS:Ljava/lang/Character$UnicodeBlock; 382
+Ljava/lang/Character$UnicodeBlock;.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A:Ljava/lang/Character$UnicodeBlock; 382
+Ljava/lang/Character$UnicodeBlock;.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B:Ljava/lang/Character$UnicodeBlock; 382
+Lcom/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry; 383
+Landroid/view/Window$DecorCallback; 383
+Landroid/view/inputmethod/EditorInfo; 383
+Landroid/view/MenuItem$OnActionExpandListener; 384
+Ljava/util/Locale;.JAPANESE:Ljava/util/Locale; 385
+Ljava/util/Locale;.KOREAN:Ljava/util/Locale; 385
+Lcom/android/internal/config/appcloning/AppCloningDeviceConfigHelper; 386
+Landroid/telecom/PhoneAccountHandle; 387
+Landroid/content/AsyncQueryHandler; 388
+Landroid/speech/RecognitionListener; 389
+Ljava/lang/InstantiationException; 390
+Ljava/util/concurrent/ExecutionException; 391
+Landroid/icu/text/DateIntervalInfo;.DIICACHE:Landroid/icu/impl/ICUCache; 392
+Landroid/text/format/DateIntervalFormat;.CACHED_FORMATTERS:Landroid/util/LruCache;.map:Ljava/util/LinkedHashMap; 392
+Landroid/icu/text/DateIntervalFormat;.LOCAL_PATTERN_CACHE:Landroid/icu/impl/ICUCache; 392
+Landroid/icu/impl/OlsonTimeZone; 392
+Landroid/text/format/DateIntervalFormat;.CACHED_FORMATTERS:Landroid/util/LruCache; 392
+Landroid/graphics/drawable/Drawable; 393
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 394
+Landroid/app/Activity; 395
+Landroid/icu/text/PluralRules$KeywordStatus;.INVALID:Landroid/icu/text/PluralRules$KeywordStatus;.name:Ljava/lang/String; 396
+Landroid/net/Uri; 396
+Lsun/util/calendar/CalendarSystem;.calendars:Ljava/util/concurrent/ConcurrentMap; 396
+Landroid/animation/PropertyValuesHolder$IntPropertyValuesHolder;.sJNISetterPropertyMap:Ljava/util/HashMap; 397
+Landroid/graphics/drawable/ShapeDrawable; 398
+Lcom/android/internal/widget/ActionBarContextView; 399
+Landroid/widget/Toolbar$SavedState; 399
+Lcom/android/internal/widget/ActionBarContainer; 399
+Lcom/android/internal/widget/ActionBarOverlayLayout; 399
+Lcom/android/internal/widget/ActionBarContainer$ActionBarBackgroundDrawable; 399
+Landroid/widget/ActionMenuPresenter$OverflowMenuButton; 400
+Landroid/widget/ActionMenuView; 401
+Landroid/content/res/Configuration; 402
+Ljava/util/IdentityHashMap;.NULL_KEY:Ljava/lang/Object; 403
+Ljava/util/concurrent/ForkJoinPool; 404
+Landroid/os/ResultReceiver; 405
+Ljava/util/concurrent/TimeoutException; 406
+Ljava/io/IOException; 407
+Landroid/accounts/AccountAuthenticatorResponse; 408
+Landroid/nfc/NfcAdapter; 409
+Landroid/nfc/NfcAdapter;.sNfcAdapters:Ljava/util/HashMap; 409
+Landroid/app/backup/BackupManager; 410
+Landroid/app/NotificationChannelGroup; 411
+Landroid/content/pm/ParceledListSlice; 411
+Landroid/os/FileObserver; 412
+Landroid/os/UserHandle; 413
+Landroid/content/pm/PackageManager$NameNotFoundException; 414
+[Ljava/lang/Integer; 415
+Landroid/animation/PropertyValuesHolder;.sSetterPropertyMap:Ljava/util/HashMap; 415
+Landroid/content/LocusId; 416
+Landroid/view/contentcapture/ContentCaptureContext; 416
+Landroid/telephony/ims/RegistrationManager;.IMS_REG_TO_ACCESS_TYPE_MAP:Ljava/util/Map;.table:[Ljava/lang/Object;.18:Ljava/lang/Integer; 417
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.4:Ljava/util/concurrent/ConcurrentHashMap$Node; 418
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 418
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.2:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 418
+Lcom/android/internal/telephony/cdnr/CarrierDisplayNameResolver;.EF_SOURCE_PRIORITY:Ljava/util/List;.a:[Ljava/lang/Object;.9:Ljava/lang/Integer; 418
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.56:Ljava/util/concurrent/ConcurrentHashMap$Node; 418
+Lcom/android/internal/telephony/cdnr/CarrierDisplayNameResolver;.EF_SOURCE_PRIORITY:Ljava/util/List;.a:[Ljava/lang/Object;.5:Ljava/lang/Integer; 418
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap; 418
+Landroid/widget/EditText; 419
+Landroid/widget/CheckedTextView; 420
+Landroid/os/strictmode/UnsafeIntentLaunchViolation; 421
+Landroid/app/Service; 422
+Ldalvik/system/BlockGuard; 423
+Landroid/hardware/devicestate/DeviceStateManagerGlobal; 424
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 425
+Landroid/hardware/camera2/marshal/MarshalRegistry;.sMarshalerMap:Ljava/util/HashMap; 425
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_FACING:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 425
+Landroid/content/ClipboardManager$OnPrimaryClipChangedListener; 426
+Landroid/icu/text/BreakIterator;.iterCache:[Landroid/icu/impl/CacheValue; 427
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.13:Ljava/util/WeakHashMap$Entry; 428
+Landroid/icu/text/Collator; 429
+Landroid/icu/impl/number/parse/NanMatcher;.DEFAULT:Landroid/icu/impl/number/parse/NanMatcher;.uniSet:Landroid/icu/text/UnicodeSet;.strings:Ljava/util/SortedSet;.c:Ljava/util/Collection;.m:Ljava/util/NavigableMap; 430
+Ljava/io/FileNotFoundException; 431
+Landroid/os/BaseBundle; 432
+Landroid/service/watchdog/ExplicitHealthCheckService$PackageConfig; 433
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.116:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.12:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.90:Ljava/lang/String; 434
+Landroid/icu/text/MessageFormat;.rootLocale:Ljava/util/Locale;.baseLocale:Lsun/util/locale/BaseLocale;.language:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.385:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.107:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.112:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.480:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.550:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.143:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._obsoleteLanguages:[Ljava/lang/String;.1:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.473:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.138:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.204:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.71:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.12:Ljava/lang/String; 434
+Landroid/icu/impl/duration/impl/DataRecord$ETimeLimit;.names:[Ljava/lang/String;.1:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.9:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.99:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages3:[Ljava/lang/String;.152:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.256:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.170:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.220:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.461:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._replacementLanguages:[Ljava/lang/String;.5:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.190:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.157:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._obsoleteCountries:[Ljava/lang/String;.4:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.196:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.117:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.5:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.499:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.199:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.18:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.324:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.101:Ljava/lang/String; 434
+Landroid/icu/impl/locale/UnicodeLocaleExtension;.CA_JAPANESE:Landroid/icu/impl/locale/UnicodeLocaleExtension;._keywords:Ljava/util/SortedMap;.root:Ljava/util/TreeMap$TreeMapEntry;.key:Ljava/lang/Object; 434
+Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.3:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.140:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.105:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.37:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.5:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.22:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.103:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.412:Ljava/lang/String; 434
+Landroid/icu/impl/duration/impl/DataRecord$EMilliSupport;.names:[Ljava/lang/String;.1:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.124:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.232:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.219:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.179:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.523:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.75:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.486:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.166:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.112:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.119:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.160:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.298:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.257:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.182:Ljava/lang/String; 434
+Landroid/icu/impl/units/UnitPreferences;.measurementSystem:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.5:Ljava/util/HashMap$Node;.next:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.47:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.180:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.111:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.358:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.96:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._obsoleteLanguages:[Ljava/lang/String;.0:Ljava/lang/String; 434
+Landroid/icu/text/DateFormat;.HOUR_GENERIC_TZ:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.67:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.254:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.222:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.55:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.349:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.16:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.352:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.443:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.478:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.19:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.401:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.137:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.65:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.474:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.168:Ljava/lang/String; 434
+Landroid/icu/impl/units/UnitPreferences;.measurementSystem:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.15:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.111:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages3:[Ljava/lang/String;.545:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.30:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.469:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.21:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.69:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.56:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.519:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._replacementLanguages:[Ljava/lang/String;.4:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.107:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.290:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.59:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.220:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.186:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.516:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.181:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.199:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.396:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.117:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.227:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.331:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.447:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.151:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.144:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.132:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.230:Ljava/lang/String; 434
+Landroid/icu/text/DateFormat;.MINUTE_SECOND:Ljava/lang/String; 434
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 435
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.head:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 436
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 437
+Landroid/graphics/drawable/ColorStateListDrawable; 438
+Ljava/lang/SecurityException; 439
+Ljava/lang/RuntimeException; 440
+Landroid/media/audiopolicy/AudioProductStrategy; 441
+Landroid/os/PersistableBundle; 442
+Landroid/content/pm/ShortcutInfo; 442
+Landroid/icu/text/TimeZoneFormat;._tzfCache:Landroid/icu/text/TimeZoneFormat$TimeZoneFormatCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 443
+Landroid/graphics/LeakyTypefaceStorage;.sStorage:Ljava/util/ArrayList; 443
+Landroid/graphics/LeakyTypefaceStorage;.sTypefaceMap:Landroid/util/ArrayMap; 443
+Landroid/text/TextWatcher; 444
+Landroid/view/accessibility/AccessibilityManager$TouchExplorationStateChangeListener; 445
+Ljavax/net/SocketFactory; 446
+Ljava/util/Collections; 447
+Ljava/lang/Exception; 448
+Landroid/os/UserManager; 449
+Landroid/os/RemoteException; 450
+Landroid/content/AttributionSource; 451
+Lcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory$DnsAdapter; 452
+Lcom/android/okhttp/Protocol;.HTTP_2:Lcom/android/okhttp/Protocol; 452
+Ljava/net/Inet4Address; 452
+Lcom/android/okhttp/Protocol;.SPDY_3:Lcom/android/okhttp/Protocol; 452
+Lcom/android/okhttp/OkHttpClient; 452
+Landroid/os/storage/VolumeInfo; 453
+Landroid/os/storage/DiskInfo; 453
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mMap:Landroid/util/ArrayMap; 454
+Ljava/nio/file/StandardOpenOption;.WRITE:Ljava/nio/file/StandardOpenOption; 455
+Ljava/nio/file/StandardOpenOption;.APPEND:Ljava/nio/file/StandardOpenOption; 456
+Ljava/util/logging/FileHandler; 457
+Ljava/nio/file/StandardOpenOption;.CREATE_NEW:Ljava/nio/file/StandardOpenOption; 457
+Ljava/util/logging/FileHandler;.locks:Ljava/util/Set;.map:Ljava/util/HashMap; 457
+Lsun/nio/ch/SharedFileLockTable;.queue:Ljava/lang/ref/ReferenceQueue; 458
+Ljavax/net/ServerSocketFactory; 458
+Landroid/os/AsyncTask; 459
+Landroid/os/strictmode/UnbufferedIoViolation; 460
+Landroid/app/usage/AppStandbyInfo; 461
+Landroid/text/format/DateUtils; 462
+Landroid/security/IKeyChainService; 463
+Landroid/util/Log$TerribleFailure; 464
+Lcom/android/internal/os/RuntimeInit$KillApplicationHandler; 464
+Ljava/util/Timer;.nextSerialNumber:Ljava/util/concurrent/atomic/AtomicInteger; 465
+Landroid/telephony/ims/stub/ImsConfigImplBase$ImsConfigStub; 466
+Landroid/telephony/ims/stub/ImsRegistrationImplBase$1; 466
+Landroid/telephony/ims/ImsUtListener; 466
+Landroid/telephony/ims/feature/MmTelFeature$1; 466
+Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 467
+Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray; 467
+Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray;.mKeys:[I 467
+Landroid/telephony/ims/aidl/IImsConfig$Stub$Proxy; 468
+Landroid/telephony/ims/aidl/IImsRegistration$Stub$Proxy; 468
+Landroid/telephony/NetworkService; 469
+Landroid/telephony/TelephonyCallback$ServiceStateListener; 470
+Landroid/telephony/TelephonyCallback$PhysicalChannelConfigListener; 471
+Landroid/telephony/TelephonyCallback$RadioPowerStateListener; 471
+Lsun/security/x509/X500Name;.internedOIDs:Ljava/util/Map; 472
+Lsun/security/x509/X500Name;.internedOIDs:Ljava/util/Map;.table:[Ljava/util/HashMap$Node; 472
+Landroid/media/MediaCodec; 473
+Ljava/nio/file/StandardOpenOption;.CREATE:Ljava/nio/file/StandardOpenOption; 474
+Ljava/nio/file/NoSuchFileException; 475
+Ljava/text/DateFormatSymbols;.cachedInstances:Ljava/util/concurrent/ConcurrentMap; 476
+Ljava/util/Currency;.instances:Ljava/util/concurrent/ConcurrentMap; 476
+Ljava/util/Calendar;.cachedLocaleData:Ljava/util/concurrent/ConcurrentMap; 476
+Ljava/text/SimpleDateFormat;.cachedNumberFormatData:Ljava/util/concurrent/ConcurrentMap; 476
+Landroid/app/UriGrantsManager;.IUriGrantsManagerSingleton:Landroid/util/Singleton; 477
+Landroid/content/ContentProviderProxy; 478
+Landroid/os/DeadObjectException; 479
+Landroid/app/slice/SliceSpec; 479
+Landroid/database/sqlite/SQLiteDatabase; 480
+Ljava/util/Locale;.CHINA:Ljava/util/Locale; 481
+Ljava/util/Locale;.TAIWAN:Ljava/util/Locale; 481
+Ljava/util/Locale;.KOREA:Ljava/util/Locale; 481
+Ljava/util/Scanner; 482
+Ljava/math/BigDecimal; 483
+Ljava/security/interfaces/RSAPrivateCrtKey; 483
+Ljava/security/interfaces/RSAPrivateKey; 483
+Lcom/android/server/backup/AccountSyncSettingsBackupHelper;.KEY_ACCOUNT_TYPE:Ljava/lang/String; 483
+Landroid/util/UtilConfig; 484
+Ljava/net/ResponseCache; 485
+Landroid/content/ReceiverCallNotAllowedException; 486
+Landroid/app/ReceiverRestrictedContext; 487
+Landroid/os/strictmode/CredentialProtectedWhileLockedViolation; 488
+Landroid/app/Application; 489
+Ljava/util/NoSuchElementException; 490
+Landroid/os/Messenger; 491
+Landroid/telephony/TelephonyCallback$DataEnabledListener; 491
+Landroid/system/StructLinger; 492
diff --git a/config/preloaded-classes b/config/preloaded-classes
index fd4e3df..0a77877 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -6265,8 +6265,6 @@
android.os.VibratorInfo$FrequencyProfile
android.os.VibratorInfo
android.os.VibratorManager
-android.os.VintfObject
-android.os.VintfRuntimeInfo
android.os.WorkSource$1
android.os.WorkSource$WorkChain$1
android.os.WorkSource$WorkChain
diff --git a/core/api/Android.bp b/core/api/Android.bp
index 907916a..77594b7 100644
--- a/core/api/Android.bp
+++ b/core/api/Android.bp
@@ -97,20 +97,53 @@
srcs: ["test-lint-baseline.txt"],
}
-java_api_contribution {
- name: "api-stubs-docs-non-updatable-public-stubs",
- api_surface: "public",
- api_file: "current.txt",
- visibility: [
- "//build/orchestrator/apis",
- ],
+// Exportable stub artifacts
+filegroup {
+ name: "non-updatable-exportable-current.txt",
+ srcs: [":api-stubs-docs-non-updatable{.exportable.api.txt}"],
}
-java_api_contribution {
- name: "frameworks-base-core-api-module-lib-stubs",
- api_surface: "module-lib",
- api_file: "module-lib-current.txt",
- visibility: [
- "//build/orchestrator/apis",
- ],
+filegroup {
+ name: "non-updatable-exportable-removed.txt",
+ srcs: [":api-stubs-docs-non-updatable{.exportable.removed-api.txt}"],
+}
+
+filegroup {
+ name: "non-updatable-exportable-system-current.txt",
+ srcs: [":system-api-stubs-docs-non-updatable{.exportable.api.txt}"],
+}
+
+filegroup {
+ name: "non-updatable-exportable-system-removed.txt",
+ srcs: [":system-api-stubs-docs-non-updatable{.exportable.removed-api.txt}"],
+}
+
+filegroup {
+ name: "non-updatable-exportable-module-lib-current.txt",
+ srcs: [":module-lib-api-stubs-docs-non-updatable{.exportable.api.txt}"],
+}
+
+filegroup {
+ name: "non-updatable-exportable-module-lib-removed.txt",
+ srcs: [":module-lib-api-stubs-docs-non-updatable{.exportable.removed-api.txt}"],
+}
+
+filegroup {
+ name: "non-updatable-exportable-test-current.txt",
+ srcs: [":test-api-stubs-docs-non-updatable{.exportable.api.txt}"],
+}
+
+filegroup {
+ name: "non-updatable-exportable-test-removed.txt",
+ srcs: [":test-api-stubs-docs-non-updatable{.exportable.removed-api.txt}"],
+}
+
+filegroup {
+ name: "non-updatable-exportable-system-server-current.txt",
+ srcs: [":services-non-updatable-stubs{.exportable.api.txt}"],
+}
+
+filegroup {
+ name: "non-updatable-exportable-system-server-removed.txt",
+ srcs: [":services-non-updatable-stubs{.exportable.removed-api.txt}"],
}
diff --git a/core/api/current.txt b/core/api/current.txt
index c600df1..2900bc8 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -193,6 +193,7 @@
field public static final String MANAGE_DEVICE_POLICY_SYSTEM_APPS = "android.permission.MANAGE_DEVICE_POLICY_SYSTEM_APPS";
field public static final String MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS = "android.permission.MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS";
field public static final String MANAGE_DEVICE_POLICY_SYSTEM_UPDATES = "android.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES";
+ field @FlaggedApi("com.android.net.thread.platform.flags.thread_user_restriction_enabled") public static final String MANAGE_DEVICE_POLICY_THREAD_NETWORK = "android.permission.MANAGE_DEVICE_POLICY_THREAD_NETWORK";
field public static final String MANAGE_DEVICE_POLICY_TIME = "android.permission.MANAGE_DEVICE_POLICY_TIME";
field public static final String MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING = "android.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING";
field public static final String MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER = "android.permission.MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER";
@@ -12738,7 +12739,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 @FlaggedApi("com.android.net.thread.flags.thread_enabled") public static final String FEATURE_THREAD_NETWORK = "android.hardware.thread_network";
+ field @FlaggedApi("com.android.net.thread.platform.flags.thread_enabled_platform") 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";
@@ -16384,7 +16385,6 @@
}
public final class RecordingCanvas extends android.graphics.Canvas {
- method public final void drawMesh(@NonNull android.graphics.Mesh, android.graphics.BlendMode, @NonNull android.graphics.Paint);
}
public final class Rect implements android.os.Parcelable {
@@ -22552,6 +22552,7 @@
method @NonNull public static android.view.Surface createPersistentInputSurface();
method public int dequeueInputBuffer(long);
method public int dequeueOutputBuffer(@NonNull android.media.MediaCodec.BufferInfo, long);
+ method @FlaggedApi("android.media.codec.null_output_surface") public void detachOutputSurface();
method protected void finalize();
method public void flush();
method @NonNull public String getCanonicalName();
@@ -22573,7 +22574,9 @@
method @NonNull public java.util.List<java.lang.String> getSupportedVendorParameters();
method @Nullable public static android.media.Image mapHardwareBuffer(@NonNull android.hardware.HardwareBuffer);
method public void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException;
+ method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public void queueInputBuffers(int, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>);
method public void queueSecureInputBuffer(int, int, @NonNull android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException;
+ method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public void queueSecureInputBuffers(int, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>, @NonNull java.util.ArrayDeque<android.media.MediaCodec.CryptoInfo>);
method public void release();
method public void releaseOutputBuffer(int, boolean);
method public void releaseOutputBuffer(int, long);
@@ -22598,6 +22601,7 @@
field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
field public static final int BUFFER_FLAG_PARTIAL_FRAME = 8; // 0x8
field @Deprecated public static final int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1
+ field @FlaggedApi("android.media.codec.null_output_surface") public static final int CONFIGURE_FLAG_DETACHED_SURFACE = 8; // 0x8
field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1
field public static final int CONFIGURE_FLAG_USE_BLOCK_MODEL = 2; // 0x2
field public static final int CONFIGURE_FLAG_USE_CRYPTO_ASYNC = 4; // 0x4
@@ -22610,6 +22614,8 @@
field public static final String PARAMETER_KEY_HDR10_PLUS_INFO = "hdr10-plus-info";
field public static final String PARAMETER_KEY_LOW_LATENCY = "low-latency";
field public static final String PARAMETER_KEY_OFFSET_TIME = "time-offset-us";
+ field @FlaggedApi("android.media.codec.region_of_interest") public static final String PARAMETER_KEY_QP_OFFSET_MAP = "qp-offset-map";
+ field @FlaggedApi("android.media.codec.region_of_interest") public static final String PARAMETER_KEY_QP_OFFSET_RECTS = "qp-offset-rects";
field public static final String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync";
field public static final String PARAMETER_KEY_SUSPEND = "drop-input-frames";
field public static final String PARAMETER_KEY_SUSPEND_TIME = "drop-start-time-us";
@@ -22634,6 +22640,7 @@
method public abstract void onError(@NonNull android.media.MediaCodec, @NonNull android.media.MediaCodec.CodecException);
method public abstract void onInputBufferAvailable(@NonNull android.media.MediaCodec, int);
method public abstract void onOutputBufferAvailable(@NonNull android.media.MediaCodec, int, @NonNull android.media.MediaCodec.BufferInfo);
+ method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public void onOutputBuffersAvailable(@NonNull android.media.MediaCodec, int, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>);
method public abstract void onOutputFormatChanged(@NonNull android.media.MediaCodec, @NonNull android.media.MediaFormat);
}
@@ -22721,6 +22728,7 @@
}
public static final class MediaCodec.OutputFrame {
+ method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") @NonNull public java.util.ArrayDeque<android.media.MediaCodec.BufferInfo> getBufferInfos();
method @NonNull public java.util.Set<java.lang.String> getChangedKeys();
method public int getFlags();
method @NonNull public android.media.MediaFormat getFormat();
@@ -22744,6 +22752,8 @@
method @NonNull public android.media.MediaCodec.QueueRequest setIntegerParameter(@NonNull String, int);
method @NonNull public android.media.MediaCodec.QueueRequest setLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, int, int);
method @NonNull public android.media.MediaCodec.QueueRequest setLongParameter(@NonNull String, long);
+ method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") @NonNull public android.media.MediaCodec.QueueRequest setMultiFrameEncryptedLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>, @NonNull java.util.ArrayDeque<android.media.MediaCodec.CryptoInfo>);
+ method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") @NonNull public android.media.MediaCodec.QueueRequest setMultiFrameLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, @NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>);
method @NonNull public android.media.MediaCodec.QueueRequest setPresentationTimeUs(long);
method @NonNull public android.media.MediaCodec.QueueRequest setStringParameter(@NonNull String, @NonNull String);
}
@@ -22752,12 +22762,16 @@
method @NonNull public String getCanonicalName();
method public android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(String);
method @NonNull public String getName();
+ method @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public int getSecurityModel();
method public String[] getSupportedTypes();
method public boolean isAlias();
method public boolean isEncoder();
method public boolean isHardwareAccelerated();
method public boolean isSoftwareOnly();
method public boolean isVendor();
+ field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_MEMORY_SAFE = 1; // 0x1
+ field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_SANDBOXED = 0; // 0x0
+ field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2; // 0x2
}
public static final class MediaCodecInfo.AudioCapabilities {
@@ -22838,15 +22852,19 @@
field @Deprecated public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
field @Deprecated public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
field public static final String FEATURE_AdaptivePlayback = "adaptive-playback";
+ field @FlaggedApi("android.media.codec.null_output_surface") public static final String FEATURE_DetachedSurface = "detached-surface";
+ field @FlaggedApi("android.media.codec.dynamic_color_aspects") public static final String FEATURE_DynamicColorAspects = "dynamic-color-aspects";
field public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp";
field public static final String FEATURE_EncodingStatistics = "encoding-statistics";
field public static final String FEATURE_FrameParsing = "frame-parsing";
field public static final String FEATURE_HdrEditing = "hdr-editing";
+ field @FlaggedApi("android.media.codec.hlg_editing") public static final String FEATURE_HlgEditing = "hlg-editing";
field public static final String FEATURE_IntraRefresh = "intra-refresh";
field public static final String FEATURE_LowLatency = "low-latency";
field public static final String FEATURE_MultipleFrames = "multiple-frames";
field public static final String FEATURE_PartialFrame = "partial-frame";
field public static final String FEATURE_QpBounds = "qp-bounds";
+ field @FlaggedApi("android.media.codec.region_of_interest") public static final String FEATURE_Roi = "region-of-interest";
field public static final String FEATURE_SecurePlayback = "secure-playback";
field public static final String FEATURE_TunneledPlayback = "tunneled-playback";
field public int[] colorFormats;
@@ -23588,6 +23606,9 @@
field public static final int COLOR_TRANSFER_LINEAR = 1; // 0x1
field public static final int COLOR_TRANSFER_SDR_VIDEO = 3; // 0x3
field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6
+ field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_MEMORY_SAFE = 2; // 0x2
+ field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_SANDBOXED = 1; // 0x1
+ field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 4; // 0x4
field public static final String KEY_AAC_DRC_ALBUM_MODE = "aac-drc-album-mode";
field public static final String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level";
field public static final String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level";
@@ -23603,6 +23624,8 @@
field public static final String KEY_AUDIO_SESSION_ID = "audio-session-id";
field public static final String KEY_BITRATE_MODE = "bitrate-mode";
field public static final String KEY_BIT_RATE = "bitrate";
+ field @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public static final String KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE = "buffer-batch-max-output-size";
+ field @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public static final String KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE = "buffer-batch-threshold-output-size";
field public static final String KEY_CAPTION_SERVICE_NUMBER = "caption-service-number";
field public static final String KEY_CAPTURE_RATE = "capture-rate";
field public static final String KEY_CHANNEL_COUNT = "channel-count";
@@ -23631,6 +23654,7 @@
field public static final String KEY_HDR10_PLUS_INFO = "hdr10-plus-info";
field public static final String KEY_HDR_STATIC_INFO = "hdr-static-info";
field public static final String KEY_HEIGHT = "height";
+ field @FlaggedApi("com.android.media.codec.flags.codec_importance") public static final String KEY_IMPORTANCE = "importance";
field public static final String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
field public static final String KEY_IS_ADTS = "is-adts";
field public static final String KEY_IS_AUTOSELECT = "is-autoselect";
@@ -23666,6 +23690,7 @@
field public static final String KEY_REPEAT_PREVIOUS_FRAME_AFTER = "repeat-previous-frame-after";
field public static final String KEY_ROTATION = "rotation-degrees";
field public static final String KEY_SAMPLE_RATE = "sample-rate";
+ field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final String KEY_SECURITY_MODEL = "security-model";
field public static final String KEY_SLICE_HEIGHT = "slice-height";
field public static final String KEY_SLOW_MOTION_MARKERS = "slow-motion-markers";
field public static final String KEY_STRIDE = "stride";
@@ -29040,435 +29065,6 @@
}
-package android.nfc {
-
- public final class AvailableNfcAntenna implements android.os.Parcelable {
- ctor public AvailableNfcAntenna(int, int);
- method public int describeContents();
- method public int getLocationX();
- method public int getLocationY();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.nfc.AvailableNfcAntenna> CREATOR;
- }
-
- public class FormatException extends java.lang.Exception {
- ctor public FormatException();
- ctor public FormatException(String);
- ctor public FormatException(String, Throwable);
- }
-
- public final class NdefMessage implements android.os.Parcelable {
- ctor public NdefMessage(byte[]) throws android.nfc.FormatException;
- ctor public NdefMessage(android.nfc.NdefRecord, android.nfc.NdefRecord...);
- ctor public NdefMessage(android.nfc.NdefRecord[]);
- method public int describeContents();
- method public int getByteArrayLength();
- method public android.nfc.NdefRecord[] getRecords();
- method public byte[] toByteArray();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.nfc.NdefMessage> CREATOR;
- }
-
- public final class NdefRecord implements android.os.Parcelable {
- ctor public NdefRecord(short, byte[], byte[], byte[]);
- ctor @Deprecated public NdefRecord(byte[]) throws android.nfc.FormatException;
- method public static android.nfc.NdefRecord createApplicationRecord(String);
- method public static android.nfc.NdefRecord createExternal(String, String, byte[]);
- method public static android.nfc.NdefRecord createMime(String, byte[]);
- method public static android.nfc.NdefRecord createTextRecord(String, String);
- method public static android.nfc.NdefRecord createUri(android.net.Uri);
- method public static android.nfc.NdefRecord createUri(String);
- method public int describeContents();
- method public byte[] getId();
- method public byte[] getPayload();
- method public short getTnf();
- method public byte[] getType();
- method @Deprecated public byte[] toByteArray();
- method public String toMimeType();
- method public android.net.Uri toUri();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.nfc.NdefRecord> CREATOR;
- field public static final byte[] RTD_ALTERNATIVE_CARRIER;
- field public static final byte[] RTD_HANDOVER_CARRIER;
- field public static final byte[] RTD_HANDOVER_REQUEST;
- field public static final byte[] RTD_HANDOVER_SELECT;
- field public static final byte[] RTD_SMART_POSTER;
- field public static final byte[] RTD_TEXT;
- field public static final byte[] RTD_URI;
- field public static final short TNF_ABSOLUTE_URI = 3; // 0x3
- field public static final short TNF_EMPTY = 0; // 0x0
- field public static final short TNF_EXTERNAL_TYPE = 4; // 0x4
- field public static final short TNF_MIME_MEDIA = 2; // 0x2
- field public static final short TNF_UNCHANGED = 6; // 0x6
- field public static final short TNF_UNKNOWN = 5; // 0x5
- field public static final short TNF_WELL_KNOWN = 1; // 0x1
- }
-
- public final class NfcAdapter {
- method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean allowTransaction();
- method public void disableForegroundDispatch(android.app.Activity);
- method public void disableReaderMode(android.app.Activity);
- method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean disallowTransaction();
- method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]);
- method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
- method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
- method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo();
- method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
- method public boolean isEnabled();
- method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean isObserveModeSupported();
- method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionEnabled();
- method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported();
- method public boolean isSecureNfcEnabled();
- method public boolean isSecureNfcSupported();
- field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
- field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
- field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
- field public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
- field public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
- field @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT) public static final String ACTION_TRANSACTION_DETECTED = "android.nfc.action.TRANSACTION_DETECTED";
- field public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
- field public static final String EXTRA_AID = "android.nfc.extra.AID";
- field public static final String EXTRA_DATA = "android.nfc.extra.DATA";
- field public static final String EXTRA_ID = "android.nfc.extra.ID";
- field public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
- field public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON = "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON";
- field public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
- field public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
- field public static final String EXTRA_TAG = "android.nfc.extra.TAG";
- field public static final int FLAG_READER_NFC_A = 1; // 0x1
- field public static final int FLAG_READER_NFC_B = 2; // 0x2
- field public static final int FLAG_READER_NFC_BARCODE = 16; // 0x10
- field public static final int FLAG_READER_NFC_F = 4; // 0x4
- field public static final int FLAG_READER_NFC_V = 8; // 0x8
- field public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 256; // 0x100
- field public static final int FLAG_READER_SKIP_NDEF_CHECK = 128; // 0x80
- field public static final int PREFERRED_PAYMENT_CHANGED = 2; // 0x2
- field public static final int PREFERRED_PAYMENT_LOADED = 1; // 0x1
- field public static final int PREFERRED_PAYMENT_UPDATED = 3; // 0x3
- field public static final int STATE_OFF = 1; // 0x1
- field public static final int STATE_ON = 3; // 0x3
- field public static final int STATE_TURNING_OFF = 4; // 0x4
- field public static final int STATE_TURNING_ON = 2; // 0x2
- }
-
- @Deprecated public static interface NfcAdapter.CreateBeamUrisCallback {
- method @Deprecated public android.net.Uri[] createBeamUris(android.nfc.NfcEvent);
- }
-
- @Deprecated public static interface NfcAdapter.CreateNdefMessageCallback {
- method @Deprecated public android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent);
- }
-
- @Deprecated public static interface NfcAdapter.OnNdefPushCompleteCallback {
- method @Deprecated public void onNdefPushComplete(android.nfc.NfcEvent);
- }
-
- public static interface NfcAdapter.OnTagRemovedListener {
- method public void onTagRemoved();
- }
-
- public static interface NfcAdapter.ReaderCallback {
- method public void onTagDiscovered(android.nfc.Tag);
- }
-
- public final class NfcAntennaInfo implements android.os.Parcelable {
- ctor public NfcAntennaInfo(int, int, boolean, @NonNull java.util.List<android.nfc.AvailableNfcAntenna>);
- method public int describeContents();
- method @NonNull public java.util.List<android.nfc.AvailableNfcAntenna> getAvailableNfcAntennas();
- method public int getDeviceHeight();
- method public int getDeviceWidth();
- method public boolean isDeviceFoldable();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.nfc.NfcAntennaInfo> CREATOR;
- }
-
- public final class NfcEvent {
- field public final android.nfc.NfcAdapter nfcAdapter;
- field public final int peerLlcpMajorVersion;
- field public final int peerLlcpMinorVersion;
- }
-
- public final class NfcManager {
- method public android.nfc.NfcAdapter getDefaultAdapter();
- }
-
- public final class Tag implements android.os.Parcelable {
- method public int describeContents();
- method public byte[] getId();
- method public String[] getTechList();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.nfc.Tag> CREATOR;
- }
-
- public class TagLostException extends java.io.IOException {
- ctor public TagLostException();
- ctor public TagLostException(String);
- }
-
-}
-
-package android.nfc.cardemulation {
-
- public final class CardEmulation {
- method public boolean categoryAllowsForegroundPreference(String);
- method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public java.util.List<java.lang.String> getAidsForPreferredPaymentService();
- method public java.util.List<java.lang.String> getAidsForService(android.content.ComponentName, String);
- method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public CharSequence getDescriptionForPreferredPaymentService();
- method public static android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
- method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getRouteDestinationForPreferredPaymentService();
- method public int getSelectionModeForCategory(String);
- method public boolean isDefaultServiceForAid(android.content.ComponentName, String);
- method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
- method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>);
- method public boolean removeAidsForService(android.content.ComponentName, String);
- method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
- method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
- method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setServiceObserveModeDefault(@NonNull android.content.ComponentName, boolean);
- method public boolean supportsAidPrefixRegistration();
- method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
- method public boolean unsetPreferredService(android.app.Activity);
- field public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
- field public static final String CATEGORY_OTHER = "other";
- field public static final String CATEGORY_PAYMENT = "payment";
- field public static final String EXTRA_CATEGORY = "category";
- field public static final String EXTRA_SERVICE_COMPONENT = "component";
- field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1
- field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2
- field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
- }
-
- public abstract class HostApduService extends android.app.Service {
- ctor public HostApduService();
- method public final void notifyUnhandled();
- method public final android.os.IBinder onBind(android.content.Intent);
- method public abstract void onDeactivated(int);
- method public abstract byte[] processCommandApdu(byte[], android.os.Bundle);
- method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void processPollingFrames(@NonNull java.util.List<android.os.Bundle>);
- method public final void sendResponseApdu(byte[]);
- field public static final int DEACTIVATION_DESELECTED = 1; // 0x1
- field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_DATA_KEY = "android.nfc.cardemulation.DATA";
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_GAIN_KEY = "android.nfc.cardemulation.GAIN";
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_TIMESTAMP_KEY = "android.nfc.cardemulation.TIMESTAMP";
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_A = 65; // 0x0041 'A'
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_B = 66; // 0x0042 'B'
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_F = 70; // 0x0046 'F'
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_TYPE_KEY = "android.nfc.cardemulation.TYPE";
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_OFF = 88; // 0x0058 'X'
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_ON = 79; // 0x004f 'O'
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_UNKNOWN = 85; // 0x0055 'U'
- field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE";
- field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service";
- }
-
- public abstract class HostNfcFService extends android.app.Service {
- ctor public HostNfcFService();
- method public final android.os.IBinder onBind(android.content.Intent);
- method public abstract void onDeactivated(int);
- method public abstract byte[] processNfcFPacket(byte[], android.os.Bundle);
- method public final void sendResponsePacket(byte[]);
- field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0
- field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_NFCF_SERVICE";
- field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_nfcf_service";
- }
-
- public final class NfcFCardEmulation {
- method public boolean disableService(android.app.Activity) throws java.lang.RuntimeException;
- method public boolean enableService(android.app.Activity, android.content.ComponentName) throws java.lang.RuntimeException;
- method public static android.nfc.cardemulation.NfcFCardEmulation getInstance(android.nfc.NfcAdapter);
- method public String getNfcid2ForService(android.content.ComponentName) throws java.lang.RuntimeException;
- method public String getSystemCodeForService(android.content.ComponentName) throws java.lang.RuntimeException;
- method public boolean registerSystemCodeForService(android.content.ComponentName, String) throws java.lang.RuntimeException;
- method public boolean setNfcid2ForService(android.content.ComponentName, String) throws java.lang.RuntimeException;
- method public boolean unregisterSystemCodeForService(android.content.ComponentName) throws java.lang.RuntimeException;
- }
-
- public abstract class OffHostApduService extends android.app.Service {
- ctor public OffHostApduService();
- field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE";
- field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.off_host_apdu_service";
- }
-
-}
-
-package android.nfc.tech {
-
- public final class IsoDep implements android.nfc.tech.TagTechnology {
- method public void close() throws java.io.IOException;
- method public void connect() throws java.io.IOException;
- method public static android.nfc.tech.IsoDep get(android.nfc.Tag);
- method public byte[] getHiLayerResponse();
- method public byte[] getHistoricalBytes();
- method public int getMaxTransceiveLength();
- method public android.nfc.Tag getTag();
- method public int getTimeout();
- method public boolean isConnected();
- method public boolean isExtendedLengthApduSupported();
- method public void setTimeout(int);
- method public byte[] transceive(byte[]) throws java.io.IOException;
- }
-
- public final class MifareClassic implements android.nfc.tech.TagTechnology {
- method public boolean authenticateSectorWithKeyA(int, byte[]) throws java.io.IOException;
- method public boolean authenticateSectorWithKeyB(int, byte[]) throws java.io.IOException;
- method public int blockToSector(int);
- method public void close() throws java.io.IOException;
- method public void connect() throws java.io.IOException;
- method public void decrement(int, int) throws java.io.IOException;
- method public static android.nfc.tech.MifareClassic get(android.nfc.Tag);
- method public int getBlockCount();
- method public int getBlockCountInSector(int);
- method public int getMaxTransceiveLength();
- method public int getSectorCount();
- method public int getSize();
- method public android.nfc.Tag getTag();
- method public int getTimeout();
- method public int getType();
- method public void increment(int, int) throws java.io.IOException;
- method public boolean isConnected();
- method public byte[] readBlock(int) throws java.io.IOException;
- method public void restore(int) throws java.io.IOException;
- method public int sectorToBlock(int);
- method public void setTimeout(int);
- method public byte[] transceive(byte[]) throws java.io.IOException;
- method public void transfer(int) throws java.io.IOException;
- method public void writeBlock(int, byte[]) throws java.io.IOException;
- field public static final int BLOCK_SIZE = 16; // 0x10
- field public static final byte[] KEY_DEFAULT;
- field public static final byte[] KEY_MIFARE_APPLICATION_DIRECTORY;
- field public static final byte[] KEY_NFC_FORUM;
- field public static final int SIZE_1K = 1024; // 0x400
- field public static final int SIZE_2K = 2048; // 0x800
- field public static final int SIZE_4K = 4096; // 0x1000
- field public static final int SIZE_MINI = 320; // 0x140
- field public static final int TYPE_CLASSIC = 0; // 0x0
- field public static final int TYPE_PLUS = 1; // 0x1
- field public static final int TYPE_PRO = 2; // 0x2
- field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
- }
-
- public final class MifareUltralight implements android.nfc.tech.TagTechnology {
- method public void close() throws java.io.IOException;
- method public void connect() throws java.io.IOException;
- method public static android.nfc.tech.MifareUltralight get(android.nfc.Tag);
- method public int getMaxTransceiveLength();
- method public android.nfc.Tag getTag();
- method public int getTimeout();
- method public int getType();
- method public boolean isConnected();
- method public byte[] readPages(int) throws java.io.IOException;
- method public void setTimeout(int);
- method public byte[] transceive(byte[]) throws java.io.IOException;
- method public void writePage(int, byte[]) throws java.io.IOException;
- field public static final int PAGE_SIZE = 4; // 0x4
- field public static final int TYPE_ULTRALIGHT = 1; // 0x1
- field public static final int TYPE_ULTRALIGHT_C = 2; // 0x2
- field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
- }
-
- public final class Ndef implements android.nfc.tech.TagTechnology {
- method public boolean canMakeReadOnly();
- method public void close() throws java.io.IOException;
- method public void connect() throws java.io.IOException;
- method public static android.nfc.tech.Ndef get(android.nfc.Tag);
- method public android.nfc.NdefMessage getCachedNdefMessage();
- method public int getMaxSize();
- method public android.nfc.NdefMessage getNdefMessage() throws android.nfc.FormatException, java.io.IOException;
- method public android.nfc.Tag getTag();
- method public String getType();
- method public boolean isConnected();
- method public boolean isWritable();
- method public boolean makeReadOnly() throws java.io.IOException;
- method public void writeNdefMessage(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
- field public static final String MIFARE_CLASSIC = "com.nxp.ndef.mifareclassic";
- field public static final String NFC_FORUM_TYPE_1 = "org.nfcforum.ndef.type1";
- field public static final String NFC_FORUM_TYPE_2 = "org.nfcforum.ndef.type2";
- field public static final String NFC_FORUM_TYPE_3 = "org.nfcforum.ndef.type3";
- field public static final String NFC_FORUM_TYPE_4 = "org.nfcforum.ndef.type4";
- }
-
- public final class NdefFormatable implements android.nfc.tech.TagTechnology {
- method public void close() throws java.io.IOException;
- method public void connect() throws java.io.IOException;
- method public void format(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
- method public void formatReadOnly(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
- method public static android.nfc.tech.NdefFormatable get(android.nfc.Tag);
- method public android.nfc.Tag getTag();
- method public boolean isConnected();
- }
-
- public final class NfcA implements android.nfc.tech.TagTechnology {
- method public void close() throws java.io.IOException;
- method public void connect() throws java.io.IOException;
- method public static android.nfc.tech.NfcA get(android.nfc.Tag);
- method public byte[] getAtqa();
- method public int getMaxTransceiveLength();
- method public short getSak();
- method public android.nfc.Tag getTag();
- method public int getTimeout();
- method public boolean isConnected();
- method public void setTimeout(int);
- method public byte[] transceive(byte[]) throws java.io.IOException;
- }
-
- public final class NfcB implements android.nfc.tech.TagTechnology {
- method public void close() throws java.io.IOException;
- method public void connect() throws java.io.IOException;
- method public static android.nfc.tech.NfcB get(android.nfc.Tag);
- method public byte[] getApplicationData();
- method public int getMaxTransceiveLength();
- method public byte[] getProtocolInfo();
- method public android.nfc.Tag getTag();
- method public boolean isConnected();
- method public byte[] transceive(byte[]) throws java.io.IOException;
- }
-
- public final class NfcBarcode implements android.nfc.tech.TagTechnology {
- method public void close() throws java.io.IOException;
- method public void connect() throws java.io.IOException;
- method public static android.nfc.tech.NfcBarcode get(android.nfc.Tag);
- method public byte[] getBarcode();
- method public android.nfc.Tag getTag();
- method public int getType();
- method public boolean isConnected();
- field public static final int TYPE_KOVIO = 1; // 0x1
- field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
- }
-
- public final class NfcF implements android.nfc.tech.TagTechnology {
- method public void close() throws java.io.IOException;
- method public void connect() throws java.io.IOException;
- method public static android.nfc.tech.NfcF get(android.nfc.Tag);
- method public byte[] getManufacturer();
- method public int getMaxTransceiveLength();
- method public byte[] getSystemCode();
- method public android.nfc.Tag getTag();
- method public int getTimeout();
- method public boolean isConnected();
- method public void setTimeout(int);
- method public byte[] transceive(byte[]) throws java.io.IOException;
- }
-
- public final class NfcV implements android.nfc.tech.TagTechnology {
- method public void close() throws java.io.IOException;
- method public void connect() throws java.io.IOException;
- method public static android.nfc.tech.NfcV get(android.nfc.Tag);
- method public byte getDsfId();
- method public int getMaxTransceiveLength();
- method public byte getResponseFlags();
- method public android.nfc.Tag getTag();
- method public boolean isConnected();
- method public byte[] transceive(byte[]) throws java.io.IOException;
- }
-
- public interface TagTechnology extends java.io.Closeable {
- method public void connect() throws java.io.IOException;
- method public android.nfc.Tag getTag();
- method public boolean isConnected();
- }
-
-}
-
package android.opengl {
public class EGL14 {
@@ -34020,6 +33616,7 @@
field public static final String DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI = "no_sharing_admin_configured_wifi";
field public static final String DISALLOW_SMS = "no_sms";
field public static final String DISALLOW_SYSTEM_ERROR_DIALOGS = "no_system_error_dialogs";
+ field @FlaggedApi("com.android.net.thread.platform.flags.thread_user_restriction_enabled") public static final String DISALLOW_THREAD_NETWORK = "no_thread_network";
field public static final String DISALLOW_ULTRA_WIDEBAND_RADIO = "no_ultra_wideband_radio";
field public static final String DISALLOW_UNIFIED_PASSWORD = "no_unified_password";
field public static final String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
@@ -39579,7 +39176,7 @@
method @Nullable public java.util.Date getKeyValidityStart();
method @NonNull public String getKeystoreAlias();
method public int getMaxUsageCount();
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
+ method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
method public int getPurposes();
method @NonNull public String[] getSignaturePaddings();
method public int getUserAuthenticationType();
@@ -39587,7 +39184,7 @@
method public boolean isDevicePropertiesAttestationIncluded();
method @NonNull public boolean isDigestsSpecified();
method public boolean isInvalidatedByBiometricEnrollment();
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified();
+ method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public boolean isMgf1DigestsSpecified();
method public boolean isRandomizedEncryptionRequired();
method public boolean isStrongBoxBacked();
method public boolean isUnlockedDeviceRequired();
@@ -39619,7 +39216,7 @@
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForOriginationEnd(java.util.Date);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityStart(java.util.Date);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMaxUsageCount(int);
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...);
+ method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean);
@@ -39650,6 +39247,7 @@
method @Deprecated public boolean isInsideSecureHardware();
method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isTrustedUserPresenceRequired();
+ method @FlaggedApi("android.security.keyinfo_unlocked_device_required") public boolean isUnlockedDeviceRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
method public boolean isUserAuthenticationValidWhileOnBody();
@@ -39724,14 +39322,14 @@
method @Nullable public java.util.Date getKeyValidityForOriginationEnd();
method @Nullable public java.util.Date getKeyValidityStart();
method public int getMaxUsageCount();
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
+ method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
method public int getPurposes();
method @NonNull public String[] getSignaturePaddings();
method public int getUserAuthenticationType();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isDigestsSpecified();
method public boolean isInvalidatedByBiometricEnrollment();
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified();
+ method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public boolean isMgf1DigestsSpecified();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUnlockedDeviceRequired();
method public boolean isUserAuthenticationRequired();
@@ -39753,7 +39351,7 @@
method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date);
method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date);
method @NonNull public android.security.keystore.KeyProtection.Builder setMaxUsageCount(int);
- method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...);
+ method @FlaggedApi("android.security.mgf1_digest_setter_v2") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...);
method @NonNull public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
method @NonNull public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
method @NonNull public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean);
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 91c082a..76bc016 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -356,11 +356,6 @@
package android.nfc {
- public class NfcFrameworkInitializer {
- method public static void registerServiceWrappers();
- method public static void setNfcServiceManager(@NonNull android.nfc.NfcServiceManager);
- }
-
public class NfcServiceManager {
method @NonNull public android.nfc.NfcServiceManager.ServiceRegisterer getNfcManagerServiceRegisterer();
}
@@ -381,7 +376,9 @@
package android.os {
public class ArtModuleServiceManager {
+ method @FlaggedApi("android.content.pm.use_art_service_v2") @NonNull public android.os.ArtModuleServiceManager.ServiceRegisterer getArtdPreRebootServiceRegisterer();
method @NonNull public android.os.ArtModuleServiceManager.ServiceRegisterer getArtdServiceRegisterer();
+ method @FlaggedApi("android.content.pm.use_art_service_v2") @NonNull public android.os.ArtModuleServiceManager.ServiceRegisterer getDexoptChrootSetupServiceRegisterer();
}
public static final class ArtModuleServiceManager.ServiceRegisterer {
diff --git a/core/api/removed.txt b/core/api/removed.txt
index 8b3696a..1fa1e89 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -252,22 +252,6 @@
}
-package android.nfc {
-
- public final class NfcAdapter {
- method @Deprecated public void disableForegroundNdefPush(android.app.Activity);
- method @Deprecated public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
- method @Deprecated public boolean invokeBeam(android.app.Activity);
- method @Deprecated public boolean isNdefPushEnabled();
- method @Deprecated public void setBeamPushUris(android.net.Uri[], android.app.Activity);
- method @Deprecated public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
- method @Deprecated public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
- method @Deprecated public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
- method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
- }
-
-}
-
package android.os {
public class BatteryManager {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 95dc07f..12802e4 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -298,7 +298,7 @@
field public static final String RECOVER_KEYSTORE = "android.permission.RECOVER_KEYSTORE";
field public static final String REGISTER_CALL_PROVIDER = "android.permission.REGISTER_CALL_PROVIDER";
field public static final String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER";
- field @FlaggedApi("com.android.net.flags.register_nsd_offload_engine") public static final String REGISTER_NSD_OFFLOAD_ENGINE = "android.permission.REGISTER_NSD_OFFLOAD_ENGINE";
+ field @FlaggedApi("android.net.platform.flags.register_nsd_offload_engine") public static final String REGISTER_NSD_OFFLOAD_ENGINE = "android.permission.REGISTER_NSD_OFFLOAD_ENGINE";
field public static final String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION";
field public static final String REGISTER_STATS_PULL_ATOM = "android.permission.REGISTER_STATS_PULL_ATOM";
field public static final String REMOTE_DISPLAY_PROVIDER = "android.permission.REMOTE_DISPLAY_PROVIDER";
@@ -357,7 +357,7 @@
field public static final String SYSTEM_APPLICATION_OVERLAY = "android.permission.SYSTEM_APPLICATION_OVERLAY";
field public static final String SYSTEM_CAMERA = "android.permission.SYSTEM_CAMERA";
field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
- field @FlaggedApi("com.android.net.thread.flags.thread_enabled") public static final String THREAD_NETWORK_PRIVILEGED = "android.permission.THREAD_NETWORK_PRIVILEGED";
+ field @FlaggedApi("com.android.net.thread.platform.flags.thread_enabled_platform") public static final String THREAD_NETWORK_PRIVILEGED = "android.permission.THREAD_NETWORK_PRIVILEGED";
field public static final String TIS_EXTENSION_INTERFACE = "android.permission.TIS_EXTENSION_INTERFACE";
field public static final String TOGGLE_AUTOMOTIVE_PROJECTION = "android.permission.TOGGLE_AUTOMOTIVE_PROJECTION";
field public static final String TRIGGER_LOST_MODE = "android.permission.TRIGGER_LOST_MODE";
@@ -3482,7 +3482,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 @FlaggedApi("com.android.net.thread.flags.thread_enabled") public static final String THREAD_NETWORK_SERVICE = "thread_network";
+ field @FlaggedApi("com.android.net.thread.platform.flags.thread_enabled_platform") 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";
@@ -3860,6 +3860,8 @@
method public void setInstallAsInstantApp(boolean);
method public void setInstallAsVirtualPreload();
method public void setRequestDowngrade(boolean);
+ method @FlaggedApi("android.content.pm.recoverability_detection") @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void setRollbackImpactLevel(int);
+ method @FlaggedApi("android.content.pm.rollback_lifetime") @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void setRollbackLifetimeMillis(long);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
}
@@ -4022,6 +4024,9 @@
field public static final int ROLLBACK_DATA_POLICY_RESTORE = 0; // 0x0
field public static final int ROLLBACK_DATA_POLICY_RETAIN = 2; // 0x2
field public static final int ROLLBACK_DATA_POLICY_WIPE = 1; // 0x1
+ field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_HIGH = 1; // 0x1
+ field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_LOW = 0; // 0x0
+ field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_ONLY_MANUAL = 2; // 0x2
field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN = 0; // 0x0
field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE = 1; // 0x1
field public static final int SYSTEM_APP_STATE_INSTALLED = 2; // 0x2
@@ -10236,42 +10241,6 @@
}
-package android.nfc {
-
- public final class NfcAdapter {
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean addNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler, String[]);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable();
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable(boolean);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
- method @FlaggedApi("android.nfc.enable_nfc_reader_option") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableReaderOption(boolean);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
- method @FlaggedApi("android.nfc.enable_nfc_mainline") public int getAdapterState();
- method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int);
- method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
- method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagIntentAppPreferenceSupported();
- 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 @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC = "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC";
- field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff
- field public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0; // 0x0
- field public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2; // 0xfffffffe
- }
-
- public static interface NfcAdapter.ControllerAlwaysOnListener {
- method public void onControllerAlwaysOnChanged(boolean);
- }
-
- public static interface NfcAdapter.NfcUnlockHandler {
- method public boolean onUnlockAttempted(android.nfc.Tag);
- }
-
-}
-
package android.nfc.cardemulation {
@FlaggedApi("android.nfc.enable_nfc_mainline") public final class AidGroup implements android.os.Parcelable {
@@ -10303,8 +10272,8 @@
method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<java.lang.String> getSubsetAids();
method @FlaggedApi("android.nfc.enable_nfc_mainline") public int getUid();
method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean hasCategory(@NonNull String);
+ method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean isCategoryOtherServiceEnabled();
method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean isOnHost();
- method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean isOtherServiceEnabled();
method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public CharSequence loadAppLabel(@NonNull android.content.pm.PackageManager);
method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public android.graphics.drawable.Drawable loadBanner(@NonNull android.content.pm.PackageManager);
method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public android.graphics.drawable.Drawable loadIcon(@NonNull android.content.pm.PackageManager);
@@ -10313,17 +10282,13 @@
method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean requiresScreenOn();
method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean requiresUnlock();
method @FlaggedApi("android.nfc.enable_nfc_mainline") public void resetOffHostSecureElement();
+ method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setCategoryOtherServiceEnabled(boolean);
method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setDynamicAidGroup(@NonNull android.nfc.cardemulation.AidGroup);
method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setOffHostSecureElement(@NonNull String);
- method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setOtherServiceEnabled(boolean);
method @FlaggedApi("android.nfc.enable_nfc_mainline") public void writeToParcel(@NonNull android.os.Parcel, int);
field @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public static final android.os.Parcelable.Creator<android.nfc.cardemulation.ApduServiceInfo> CREATOR;
}
- public final class CardEmulation {
- method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int);
- }
-
@FlaggedApi("android.nfc.enable_nfc_mainline") public final class NfcFServiceInfo implements android.os.Parcelable {
ctor @FlaggedApi("android.nfc.enable_nfc_mainline") public NfcFServiceInfo(@NonNull android.content.pm.PackageManager, @NonNull android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method @FlaggedApi("android.nfc.enable_nfc_mainline") public int describeContents();
@@ -10925,7 +10890,7 @@
method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static int rebootAndApply(@NonNull android.content.Context, @NonNull String, boolean) throws java.io.IOException;
method @RequiresPermission(allOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootWipeAb(android.content.Context, java.io.File, String) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException;
- method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException;
+ method @Deprecated public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException;
field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_INVALID_PACKAGE_NAME = 2000; // 0x7d0
field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_LSKF_NOT_CAPTURED = 3000; // 0xbb8
field public static final int RESUME_ON_REBOOT_REBOOT_ERROR_PROVIDER_PREPARATION_FAILURE = 5000; // 0x1388
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 1e9e9be..9eddab5 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -173,16 +173,6 @@
SAM-compatible parameters (such as parameter 1, "sessionListener", in android.media.session.MediaSessionManager.addOnActiveSessionsChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.session.MediaSessionManager#addOnSession2TokensChangedListener(android.media.session.MediaSessionManager.OnSession2TokensChangedListener, android.os.Handler):
SAM-compatible parameters (such as parameter 1, "listener", in android.media.session.MediaSessionManager.addOnSession2TokensChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.nfc.NfcAdapter#enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle):
- SAM-compatible parameters (such as parameter 2, "callback", in android.nfc.NfcAdapter.enableReaderMode) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.nfc.NfcAdapter#ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler):
- SAM-compatible parameters (such as parameter 3, "tagRemovedListener", in android.nfc.NfcAdapter.ignore) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.nfc.NfcAdapter#setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity):
- SAM-compatible parameters (such as parameter 1, "callback", in android.nfc.NfcAdapter.setBeamPushUrisCallback) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.nfc.NfcAdapter#setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...):
- SAM-compatible parameters (such as parameter 1, "callback", in android.nfc.NfcAdapter.setNdefPushMessageCallback) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.nfc.NfcAdapter#setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...):
- SAM-compatible parameters (such as parameter 1, "callback", in android.nfc.NfcAdapter.setOnNdefPushCompleteCallback) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.os.Binder#attachInterface(android.os.IInterface, String):
SAM-compatible parameters (such as parameter 1, "owner", in android.os.Binder.attachInterface) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.os.Binder#linkToDeath(android.os.IBinder.DeathRecipient, int):
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 1c10356..2c5acf1 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -140,17 +140,6 @@
}
-package android.nfc {
-
- public final class NfcAdapter {
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush();
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
- method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
- field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
- }
-
-}
-
package android.os {
public class Build {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index d01706d..32b031b 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -154,6 +154,7 @@
field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
field public static final int PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK = 8; // 0x8
field public static final int PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK = 32; // 0x20
+ field public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 5; // 0x5
field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4
field public static final int PROCESS_STATE_TOP = 2; // 0x2
field public static final int STOP_USER_ON_SWITCH_DEFAULT = -1; // 0xffffffff
@@ -1147,6 +1148,10 @@
package android.content.rollback {
+ public final class RollbackInfo implements android.os.Parcelable {
+ method @FlaggedApi("android.content.pm.recoverability_detection") public int getRollbackImpactLevel();
+ }
+
public final class RollbackManager {
method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long);
method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
@@ -1629,6 +1634,7 @@
method @NonNull public java.util.List<java.lang.String> getKeyboardLayoutDescriptorsForInputDevice(@NonNull android.view.InputDevice);
method @NonNull public String getKeyboardLayoutTypeForLayoutDescriptor(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public java.util.Map<java.lang.Integer,java.lang.Integer> getModifierKeyRemapping();
+ method public int getMousePointerSpeed();
method @RequiresPermission(android.Manifest.permission.REMAP_MODIFIER_KEYS) public void remapModifierKey(int, int);
method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void removeKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String);
method public void removeUniqueIdAssociation(@NonNull String);
@@ -1638,6 +1644,7 @@
public class InputSettings {
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void setMaximumObscuringOpacityForTouch(@NonNull android.content.Context, @FloatRange(from=0, to=1) float);
+ field public static final int DEFAULT_POINTER_SPEED = 0; // 0x0
}
}
@@ -2582,7 +2589,6 @@
method @NonNull public static String convert(@NonNull java.util.UUID);
method @Nullable public String getCloudMediaProvider();
method public boolean isAppIoBlocked(@NonNull java.util.UUID, int, int, int);
- method public static boolean isUserKeyUnlocked(int);
field public static final String CACHE_RESERVE_PERCENT_HIGH_KEY = "cache_reserve_percent_high";
field public static final String CACHE_RESERVE_PERCENT_LOW_KEY = "cache_reserve_percent_low";
field public static final String STORAGE_THRESHOLD_PERCENT_HIGH_KEY = "storage_threshold_percent_high";
@@ -2790,6 +2796,10 @@
field public static final String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
}
+ public static final class Settings.System extends android.provider.Settings.NameValueTable {
+ field public static final String POINTER_SPEED = "pointer_speed";
+ }
+
public static final class Telephony.Sms.Intents {
field public static final String SMS_CARRIER_PROVISION_ACTION = "android.provider.Telephony.SMS_CARRIER_PROVISION";
}
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index 37464a0..3abd9fe 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -1221,8 +1221,6 @@
Classes holding a set of parameters should be called `FooParams`, was `ContentCaptureOptions`
-VisiblySynchronized: PsiThisExpression:
- Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.content.res.AssetManager.getApkPaths()
VisiblySynchronized: android.content.res.AssetManager#getApkPaths():
Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.content.res.AssetManager.getApkPaths()
VisiblySynchronized: android.content.res.AssetManager#getLastResourceResolution():
diff --git a/core/java/Android.bp b/core/java/Android.bp
index d0b958e..0ad621d 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -14,20 +14,12 @@
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: [
"**/*.java",
"**/*.aidl",
+ ":framework-nfc-non-updatable-sources",
],
visibility: ["//frameworks/base"],
}
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index f33d299..4823f44 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1311,8 +1311,9 @@
if (!node.mEnded) {
float durationScale = ValueAnimator.getDurationScale();
durationScale = durationScale == 0 ? 1 : durationScale;
- node.mEnded = node.mAnimation.pulseAnimationFrame(
- (long) (animPlayTime * durationScale));
+ if (node.mAnimation.pulseAnimationFrame((long) (animPlayTime * durationScale))) {
+ node.mEnded = true;
+ }
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 66d04a3..f72a9de 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -705,6 +705,8 @@
/** @hide Process is hosting a foreground service due to a system binding. */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @SuppressLint("UnflaggedApi") // @TestApi without associated feature.
+ @TestApi
public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE =
ProcessStateEnum.BOUND_FOREGROUND_SERVICE;
@@ -3541,7 +3543,7 @@
* foreground. This may be running a window that is behind the current
* foreground (so paused and with its state saved, not interacting with
* the user, but visible to them to some degree); it may also be running
- * other services under the system's control that it inconsiders important.
+ * other services under the system's control that it considers important.
*/
public static final int IMPORTANCE_VISIBLE = 200;
@@ -3613,9 +3615,9 @@
public static final int IMPORTANCE_CANT_SAVE_STATE = 350;
/**
- * Constant for {@link #importance}: This process process contains
- * cached code that is expendable, not actively running any app components
- * we care about.
+ * Constant for {@link #importance}: This process contains cached code
+ * that is expendable, not actively running any app components we care
+ * about.
*/
public static final int IMPORTANCE_CACHED = 400;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index ccd83f7..667d3e6 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -4338,19 +4338,19 @@
*/
private @Nullable NoteOpEvent getLastRejectEvent(@UidState int fromUidState,
@UidState int toUidState, @OpFlags int flags) {
- NoteOpEvent lastAccessEvent = null;
+ NoteOpEvent lastRejectEvent = null;
for (AttributedOpEntry attributionEntry : mAttributedOpEntries.values()) {
- NoteOpEvent lastAttributionAccessEvent = attributionEntry.getLastRejectEvent(
+ NoteOpEvent lastAttributionRejectEvent = attributionEntry.getLastRejectEvent(
fromUidState, toUidState, flags);
- if (lastAccessEvent == null || (lastAttributionAccessEvent != null
- && lastAttributionAccessEvent.getNoteTime()
- > lastAccessEvent.getNoteTime())) {
- lastAccessEvent = lastAttributionAccessEvent;
+ if (lastRejectEvent == null || (lastAttributionRejectEvent != null
+ && lastAttributionRejectEvent.getNoteTime()
+ > lastRejectEvent.getNoteTime())) {
+ lastRejectEvent = lastAttributionRejectEvent;
}
}
- return lastAccessEvent;
+ return lastRejectEvent;
}
/**
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index d859f3f..17177ff 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -460,6 +460,15 @@
*/
public static final int SUBREASON_SDK_SANDBOX_NOT_NEEDED = 28;
+ /**
+ * The process was killed by the [kernel] Out-of-memory (OOM) killer; this
+ * would be set only when the reason is {@link #REASON_LOW_MEMORY}.
+ *
+ * For internal use only.
+ * @hide
+ */
+ public static final int SUBREASON_OOM_KILL = 30;
+
// If there is any OEM code which involves additional app kill reasons, it should
// be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000.
@@ -635,6 +644,7 @@
SUBREASON_KILL_BACKGROUND,
SUBREASON_PACKAGE_UPDATE,
SUBREASON_UNDELIVERED_BROADCAST,
+ SUBREASON_OOM_KILL,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SubReason {}
@@ -1360,6 +1370,8 @@
return "PACKAGE UPDATE";
case SUBREASON_UNDELIVERED_BROADCAST:
return "UNDELIVERED BROADCAST";
+ case SUBREASON_OOM_KILL:
+ return "OOM KILL";
default:
return "UNKNOWN";
}
diff --git a/core/java/android/app/COMPONENT_CALLER_OWNERS b/core/java/android/app/COMPONENT_CALLER_OWNERS
new file mode 100644
index 0000000..f8fdeae
--- /dev/null
+++ b/core/java/android/app/COMPONENT_CALLER_OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 315013
+brufino@google.com
+mpgroover@google.com
+
+include /services/core/java/com/android/server/uri/OWNERS
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index c072feb..1073478 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -717,28 +717,28 @@
/**
* Returns whether the device is currently locked for the user.
* <p>
- * This returns the device locked state for the {@link Context}'s user. If this user is the
- * current user, then the device is considered "locked" when the lock screen is showing (i.e.
- * {@link #isKeyguardLocked()} returns {@code true}) and is not trivially dismissible (e.g. with
- * swipe), and the user has a PIN, pattern, or password.
+ * This method returns the device locked state for the {@link Context}'s user. The device is
+ * considered to be locked for a user when the user's apps are currently inaccessible and some
+ * form of lock screen authentication is required to regain access to them. The lock screen
+ * authentication typically uses PIN, pattern, password, or biometric. Some devices may support
+ * additional methods, such as unlock using a paired smartwatch. "Swipe" does not count as
+ * authentication; if the lock screen is dismissible with swipe, for example due to the lock
+ * screen being set to Swipe or due to the device being kept unlocked by being near a trusted
+ * bluetooth device or in a trusted location, the device is considered unlocked.
+ * <div class="note">
* <p>
- * Note: the above definition implies that a user with no PIN, pattern, or password is never
- * considered locked, even if the lock screen is showing and requesting a SIM card PIN. The
- * device PIN and SIM PIN are separate. Also, the user is not considered locked if face
- * authentication has just completed or a trust agent is keeping the device unlocked, since in
- * these cases the lock screen is dismissible with swipe.
+ * <b>Note:</b> In the case of multiple full users, each user can have their own lock screen
+ * authentication configured. The device-locked state may differ between different users. For
+ * example, the device may be unlocked for the current user, but locked for a non-current user
+ * if lock screen authentication would be required to access that user's apps after switching to
+ * that user.
* <p>
- * For a user that is not the current user but can be switched to (usually this means "another
- * full user"), and that has a PIN, pattern, or password, the device is always considered
- * locked.
- * <p>
- * For a profile with a unified challenge, the device locked state is the same as that of the
- * parent user.
- * <p>
- * For a profile with a separate challenge, the device becomes unlocked when the profile's PIN,
- * pattern, password, or biometric is verified. It becomes locked when the parent user becomes
- * locked, the screen turns off, the device reboots, the device policy controller locks the
- * profile, or the timeout set by the device policy controller expires.
+ * In the case of a profile, when the device goes to the main lock screen, up to two layers of
+ * authentication may be required to regain access to the profile's apps: one to unlock the main
+ * lock screen, and one to unlock the profile (when a separate profile challenge is required).
+ * For a profile, the device is considered to be locked as long as any challenge remains, either
+ * the parent user's challenge (when applicable) or the profile's challenge (when applicable).
+ * </div>
*
* @return {@code true} if the device is currently locked for the user
* @see #isKeyguardLocked()
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ced3554..bd50958 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -7363,6 +7363,7 @@
/**
* @hide
*/
+ @SuppressWarnings("HiddenAbstractMethod")
public abstract boolean areNotificationsVisiblyDifferent(Style other);
/**
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index 164bdbe..32de385 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -31,6 +31,7 @@
per-file SystemServiceRegistry.java = file:/services/core/java/com/android/server/am/OWNERS
per-file *UserSwitchObserver* = file:/services/core/java/com/android/server/am/OWNERS
per-file *UiAutomation* = file:/services/accessibility/OWNERS
+per-file *UiAutomation* = file:/core/java/android/permission/OWNERS
per-file GameManager* = file:/GAME_MANAGER_OWNERS
per-file GameMode* = file:/GAME_MANAGER_OWNERS
per-file GameState* = file:/GAME_MANAGER_OWNERS
@@ -55,6 +56,13 @@
per-file Broadcast* = file:/BROADCASTS_OWNERS
per-file ReceiverInfo* = file:/BROADCASTS_OWNERS
+# ComponentCaller
+per-file ComponentCaller.java = file:COMPONENT_CALLER_OWNERS
+
+# GrammaticalInflectionManager
+per-file *GrammaticalInflection* = file:/services/core/java/com/android/server/grammaticalinflection/OWNERS
+per-file grammatical_inflection_manager.aconfig = file:/services/core/java/com/android/server/grammaticalinflection/OWNERS
+
# KeyguardManager
per-file KeyguardManager.java = file:/services/core/java/com/android/server/locksettings/OWNERS
@@ -81,6 +89,10 @@
per-file IInstantAppResolver.aidl = file:/services/core/java/com/android/server/pm/OWNERS
per-file InstantAppResolveInfo.aidl = file:/services/core/java/com/android/server/pm/OWNERS
+# BackgroundInstallControlManager
+per-file BackgroundInstallControlManager.java = file:/services/core/java/com/android/server/pm/BACKGROUND_INSTALL_OWNERS
+per-file background_install_control_manager.aconfig = file:/services/core/java/com/android/server/pm/BACKGROUND_INSTALL_OWNERS
+
# ResourcesManager
per-file ResourcesManager.java = file:RESOURCES_OWNERS
diff --git a/core/java/android/app/contextualsearch/OWNERS b/core/java/android/app/contextualsearch/OWNERS
new file mode 100644
index 0000000..0c2612c
--- /dev/null
+++ b/core/java/android/app/contextualsearch/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/contextualsearch/OWNERS
diff --git a/core/java/android/app/ondeviceintelligence/OWNERS b/core/java/android/app/ondeviceintelligence/OWNERS
new file mode 100644
index 0000000..6932ba2
--- /dev/null
+++ b/core/java/android/app/ondeviceintelligence/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 1363385
+
+sandeepbandaru@google.com
+shivanker@google.com
+hackz@google.com
+volnov@google.com
+
diff --git a/core/java/android/app/wearable/OWNERS b/core/java/android/app/wearable/OWNERS
index 073e2d7..497eaf0 100644
--- a/core/java/android/app/wearable/OWNERS
+++ b/core/java/android/app/wearable/OWNERS
@@ -1,3 +1,5 @@
charliewang@google.com
+hackz@google.com
oni@google.com
+tomchan@google.com
volnov@google.com
\ No newline at end of file
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 2200af6..c5356fe 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -182,7 +182,7 @@
*
* @param context A Context object which should be some mock instance (like the
* instance of {@link android.test.mock.MockContext}).
- * @param readPermission The read permision you want this instance should have in the
+ * @param readPermission The read permission you want this instance should have in the
* test, which is available via {@link #getReadPermission()}.
* @param writePermission The write permission you want this instance should have
* in the test, which is available via {@link #getWritePermission()}.
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index b2cd7e9..a97ca0a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -387,7 +387,7 @@
* {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
* <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in
* the arguments {@link Bundle}, the Content framework will attempt to
- * synthesize an QUERY_ARG_SQL* argument using the corresponding
+ * synthesize a QUERY_ARG_SQL* argument using the corresponding
* QUERY_ARG_SORT* values.
*/
public static final String QUERY_ARG_SORT_COLUMNS = "android:query-arg-sort-columns";
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 95fc3ac..6d54223 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4767,7 +4767,7 @@
* @see android.net.thread.ThreadNetworkManager
* @hide
*/
- @FlaggedApi("com.android.net.thread.flags.thread_enabled")
+ @FlaggedApi(com.android.net.thread.platform.flags.Flags.FLAG_THREAD_ENABLED_PLATFORM)
@SystemApi
public static final String THREAD_NETWORK_SERVICE = "thread_network";
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index f946754..01ea4e9 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -664,7 +664,7 @@
* has at least one HTTP or HTTPS data URI pattern defined, and optionally
* does not define any non-http/https data URI patterns.
*
- * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
+ * This will check if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
* the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
* data scheme is "http" or "https".
*
@@ -705,7 +705,7 @@
}
// We get here if:
- // 1) onlyWebSchemes and no non-web schemes were found, i.e success; or
+ // 1) onlyWebSchemes and no non-web schemes were found, i.e. success; or
// 2) !onlyWebSchemes and no http/https schemes were found, i.e. failure.
return onlyWebSchemes;
}
@@ -715,7 +715,7 @@
*
* @return True if the filter needs to be automatically verified. False otherwise.
*
- * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
+ * This will check if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
* the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
* data scheme is "http" or "https".
*
diff --git a/core/java/android/content/OWNERS b/core/java/android/content/OWNERS
index 90c3d04..a37408b 100644
--- a/core/java/android/content/OWNERS
+++ b/core/java/android/content/OWNERS
@@ -4,6 +4,7 @@
per-file *Content* = file:/services/core/java/com/android/server/am/OWNERS
per-file *Sync* = file:/services/core/java/com/android/server/am/OWNERS
per-file IntentFilter.java = file:/PACKAGE_MANAGER_OWNERS
+per-file UriRelativeFilter* = file:/PACKAGE_MANAGER_OWNERS
per-file IntentFilter.java = file:/services/core/java/com/android/server/am/OWNERS
per-file Intent.java = file:/INTENT_OWNERS
per-file AutofillOptions* = file:/core/java/android/service/autofill/OWNERS
diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS
index 0a7d079..a5acb38 100644
--- a/core/java/android/content/pm/OWNERS
+++ b/core/java/android/content/pm/OWNERS
@@ -3,9 +3,22 @@
file:/PACKAGE_MANAGER_OWNERS
per-file PackageParser.java = set noparent
-per-file PackageParser.java = chiuwinson@google.com,patb@google.com
+per-file PackageParser.java = file:/PACKAGE_MANAGER_OWNERS
+
+# Bug component: 166829 = per-file *Capability*
per-file *Capability* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
+# Bug component: 166829 = per-file *Shortcut*
per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
+
+# Bug component: 860423 = per-file *Launcher*
per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS
+
+# Bug component: 578329 = per-file *UserInfo*
per-file UserInfo* = file:/MULTIUSER_OWNERS
+# Bug component: 578329 = per-file *UserProperties*
per-file *UserProperties* = file:/MULTIUSER_OWNERS
+# Bug component: 578329 = per-file *multiuser*
+per-file *multiuser* = file:/MULTIUSER_OWNERS
+
+# Bug component: 1219020 = per-file *BackgroundInstallControl*
+per-file *BackgroundInstallControl* = file:/services/core/java/com/android/server/pm/BACKGROUND_INSTALL_OWNERS
\ No newline at end of file
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 462df07..6ca6194 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -34,6 +34,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.CurrentTimeMillisLong;
import android.annotation.DurationMillisLong;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -2370,6 +2371,10 @@
public DataLoaderParams dataLoaderParams;
/** {@hide} */
public int rollbackDataPolicy = PackageManager.ROLLBACK_DATA_POLICY_RESTORE;
+ /** @hide */
+ public long rollbackLifetimeMillis = 0;
+ /** {@hide} */
+ public int rollbackImpactLevel = PackageManager.ROLLBACK_USER_IMPACT_LOW;
/** {@hide} */
public boolean forceQueryableOverride;
/** {@hide} */
@@ -2424,6 +2429,8 @@
dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel);
}
rollbackDataPolicy = source.readInt();
+ rollbackLifetimeMillis = source.readLong();
+ rollbackImpactLevel = source.readInt();
requireUserAction = source.readInt();
packageSource = source.readInt();
applicationEnabledSettingPersistent = source.readBoolean();
@@ -2456,6 +2463,8 @@
ret.requiredInstalledVersionCode = requiredInstalledVersionCode;
ret.dataLoaderParams = dataLoaderParams;
ret.rollbackDataPolicy = rollbackDataPolicy;
+ ret.rollbackLifetimeMillis = rollbackLifetimeMillis;
+ ret.rollbackImpactLevel = rollbackImpactLevel;
ret.requireUserAction = requireUserAction;
ret.packageSource = packageSource;
ret.applicationEnabledSettingPersistent = applicationEnabledSettingPersistent;
@@ -2737,12 +2746,7 @@
*/
@SystemApi
public void setEnableRollback(boolean enable) {
- if (enable) {
- installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
- } else {
- installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
- }
- rollbackDataPolicy = PackageManager.ROLLBACK_DATA_POLICY_RESTORE;
+ setEnableRollback(enable, PackageManager.ROLLBACK_DATA_POLICY_RESTORE);
}
/**
@@ -2766,10 +2770,59 @@
installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
} else {
installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
+ rollbackLifetimeMillis = 0;
}
rollbackDataPolicy = dataPolicy;
}
+ /**
+ * If rollback enabled for this session (via {@link #setEnableRollback}, set period
+ * after which rollback files will be deleted due to expiration
+ * {@link RollbackManagerServiceImpl#deleteRollback}.
+ *
+ * <p>For multi-package installs, this value must be set on the parent session.
+ * Child session rollback lifetime will be ignored.
+ *
+ * @param lifetimeMillis period after which rollback expires
+ * @throws IllegalArgumentException if lifetimeMillis is negative or rollback is not
+ * enabled via setEnableRollback.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
+ @FlaggedApi(Flags.FLAG_ROLLBACK_LIFETIME)
+ public void setRollbackLifetimeMillis(@DurationMillisLong long lifetimeMillis) {
+ if (lifetimeMillis < 0) {
+ throw new IllegalArgumentException("rollbackLifetimeMillis can't be negative.");
+ }
+ if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
+ throw new IllegalArgumentException(
+ "Can't set rollbackLifetimeMillis when rollback is not enabled");
+ }
+ rollbackLifetimeMillis = lifetimeMillis;
+ }
+
+ /**
+ * rollbackImpactLevel is a measure of impact a rollback has on the user. This can take one
+ * of 3 values:
+ * <ul>
+ * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_LOW} (default)</li>
+ * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_HIGH} (1)</li>
+ * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_ONLY_MANUAL} (2)</li>
+ * </ul>
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
+ @FlaggedApi(Flags.FLAG_RECOVERABILITY_DETECTION)
+ public void setRollbackImpactLevel(@PackageManager.RollbackImpactLevel int impactLevel) {
+ if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
+ throw new IllegalArgumentException(
+ "Can't set rollbackImpactLevel when rollback is not enabled");
+ }
+ rollbackImpactLevel = impactLevel;
+ }
/**
* @deprecated use {@link #setRequestDowngrade(boolean)}.
@@ -3124,6 +3177,8 @@
pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
pw.printPair("dataLoaderParams", dataLoaderParams);
pw.printPair("rollbackDataPolicy", rollbackDataPolicy);
+ pw.printPair("rollbackLifetimeMillis", rollbackLifetimeMillis);
+ pw.printPair("rollbackImpactLevel", rollbackImpactLevel);
pw.printPair("applicationEnabledSettingPersistent",
applicationEnabledSettingPersistent);
pw.printHexPair("developmentInstallFlags", developmentInstallFlags);
@@ -3165,6 +3220,8 @@
dest.writeParcelable(null, flags);
}
dest.writeInt(rollbackDataPolicy);
+ dest.writeLong(rollbackLifetimeMillis);
+ dest.writeInt(rollbackImpactLevel);
dest.writeInt(requireUserAction);
dest.writeInt(packageSource);
dest.writeBoolean(applicationEnabledSettingPersistent);
@@ -3358,6 +3415,12 @@
/** {@hide} */
public int rollbackDataPolicy;
+ /** @hide */
+ public long rollbackLifetimeMillis;
+
+ /** {@hide} */
+ public int rollbackImpactLevel;
+
/** {@hide} */
public int requireUserAction;
@@ -3425,6 +3488,8 @@
isCommitted = source.readBoolean();
isPreapprovalRequested = source.readBoolean();
rollbackDataPolicy = source.readInt();
+ rollbackLifetimeMillis = source.readLong();
+ rollbackImpactLevel = source.readInt();
createdMillis = source.readLong();
requireUserAction = source.readInt();
installerUid = source.readInt();
@@ -4048,6 +4113,8 @@
dest.writeBoolean(isCommitted);
dest.writeBoolean(isPreapprovalRequested);
dest.writeInt(rollbackDataPolicy);
+ dest.writeLong(rollbackLifetimeMillis);
+ dest.writeInt(rollbackImpactLevel);
dest.writeLong(createdMillis);
dest.writeInt(requireUserAction);
dest.writeInt(installerUid);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c8ba47b..92bfcef 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1429,6 +1429,44 @@
public static final int ROLLBACK_DATA_POLICY_RETAIN = 2;
/** @hide */
+ @IntDef(prefix = {"ROLLBACK_USER_IMPACT_"}, value = {
+ ROLLBACK_USER_IMPACT_LOW,
+ ROLLBACK_USER_IMPACT_HIGH,
+ ROLLBACK_USER_IMPACT_ONLY_MANUAL,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RollbackImpactLevel {}
+
+ /**
+ * Rollback will be performed automatically in response to native crashes on startup or
+ * persistent service crashes. More suitable for apps that do not store any user data.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION)
+ public static final int ROLLBACK_USER_IMPACT_LOW = 0;
+
+ /**
+ * Rollback will be performed automatically only when the device is found to be unrecoverable.
+ * More suitable for apps that store user data and have higher impact on user.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION)
+ public static final int ROLLBACK_USER_IMPACT_HIGH = 1;
+
+ /**
+ * Rollback will not be performed automatically. It can be triggered externally.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION)
+ public static final int ROLLBACK_USER_IMPACT_ONLY_MANUAL = 2;
+
+ /** @hide */
@IntDef(flag = true, prefix = { "INSTALL_" }, value = {
INSTALL_REPLACE_EXISTING,
INSTALL_ALLOW_TEST,
@@ -3718,7 +3756,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")
+ @FlaggedApi(com.android.net.thread.platform.flags.Flags.FLAG_THREAD_ENABLED_PLATFORM)
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_THREAD_NETWORK = "android.hardware.thread_network";
@@ -4276,6 +4314,10 @@
* the Android Keystore backed by an isolated execution environment. The version indicates
* which features are implemented in the isolated execution environment:
* <ul>
+ * <li>300: Ability to include a second IMEI in the ID attestation record, see
+ * {@link android.app.admin.DevicePolicyManager#ID_TYPE_IMEI}.
+ * <li>200: Hardware support for Curve 25519 (including both Ed25519 signature generation and
+ * X25519 key agreement).
* <li>100: Hardware support for ECDH (see {@link javax.crypto.KeyAgreement}) and support
* for app-generated attestation keys (see {@link
* android.security.keystore.KeyGenParameterSpec.Builder#setAttestKeyAlias(String)}).
@@ -4305,6 +4347,11 @@
* StrongBox</a>. If this feature has a version, the version number indicates which features are
* implemented in StrongBox:
* <ul>
+ * <li>300: Ability to include a second IMEI in the ID attestation record, see
+ * {@link android.app.admin.DevicePolicyManager#ID_TYPE_IMEI}.
+ * <li>200: No new features for StrongBox (the Android Keystore environment backed by an
+ * isolated execution environment has gained support for Curve 25519 in this version, but
+ * the implementation backed by a dedicated secure processor is not expected to implement it).
* <li>100: Hardware support for ECDH (see {@link javax.crypto.KeyAgreement}) and support
* for app-generated attestation keys (see {@link
* android.security.keystore.KeyGenParameterSpec.Builder#setAttestKeyAlias(String)}).
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 5242533..ab8fd5e 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -6,3 +6,19 @@
description: "Feature flag to enable the features that rely on new ART Service APIs that are in the VIC version of the ART module."
bug: "304741685"
}
+
+flag {
+ name: "rollback_lifetime"
+ namespace: "package_manager_service"
+ description: "Feature flag to enable custom rollback lifetime during install."
+ bug: "299670324"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "recoverability_detection"
+ namespace: "package_manager_service"
+ description: "Feature flag to enable recoverability detection feature. It includes GMS core rollback and improvements to rescue party."
+ bug: "291135724"
+ is_fixed_read_only: true
+}
\ No newline at end of file
diff --git a/core/java/android/content/pm/verify/domain/OWNERS b/core/java/android/content/pm/verify/domain/OWNERS
index c669112..b451fe4 100644
--- a/core/java/android/content/pm/verify/domain/OWNERS
+++ b/core/java/android/content/pm/verify/domain/OWNERS
@@ -1,5 +1,4 @@
# Bug component: 36137
+include /PACKAGE_MANAGER_OWNERS
-chiuwinson@google.com
-patb@google.com
-toddke@google.com
\ No newline at end of file
+wloh@google.com
\ No newline at end of file
diff --git a/core/java/android/content/res/flags.aconfig b/core/java/android/content/res/flags.aconfig
new file mode 100644
index 0000000..b0e2342
--- /dev/null
+++ b/core/java/android/content/res/flags.aconfig
@@ -0,0 +1,19 @@
+package: "android.content.res"
+
+flag {
+ name: "default_locale"
+ namespace: "resource_manager"
+ description: "Feature flag for default locale in LocaleConfig"
+ bug: "117306409"
+ # fixed_read_only or device wont boot because of permission issues accessing flags during boot
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "manifest_flagging"
+ namespace: "resource_manager"
+ description: "Feature flag for flagging manifest entries"
+ bug: "297373084"
+ # This flag is read in PackageParser at boot time, and in aapt2 which is a build tool.
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/content/rollback/OWNERS b/core/java/android/content/rollback/OWNERS
index 3093fd6..8e5a0d8 100644
--- a/core/java/android/content/rollback/OWNERS
+++ b/core/java/android/content/rollback/OWNERS
@@ -1,5 +1,5 @@
-# Bug component: 557916
+# Bug component: 819107
-narayan@google.com
-nandana@google.com
-olilan@google.com
+ancr@google.com
+harshitmahajan@google.com
+robertogil@google.com
diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java
index a363718..d128055 100644
--- a/core/java/android/content/rollback/RollbackInfo.java
+++ b/core/java/android/content/rollback/RollbackInfo.java
@@ -16,8 +16,12 @@
package android.content.rollback;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.content.pm.Flags;
+import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -25,17 +29,14 @@
import java.util.List;
/**
- * Information about a set of packages that can be, or already have been
- * rolled back together.
+ * Information about a set of packages that can be, or already have been rolled back together.
*
* @hide
*/
@SystemApi
public final class RollbackInfo implements Parcelable {
- /**
- * A unique identifier for the rollback.
- */
+ /** A unique identifier for the rollback. */
private final int mRollbackId;
private final List<PackageRollbackInfo> mPackages;
@@ -44,15 +45,39 @@
private final boolean mIsStaged;
private int mCommittedSessionId;
+ private int mRollbackImpactLevel;
/** @hide */
- public RollbackInfo(int rollbackId, List<PackageRollbackInfo> packages, boolean isStaged,
- List<VersionedPackage> causePackages, int committedSessionId) {
+ public RollbackInfo(
+ int rollbackId,
+ List<PackageRollbackInfo> packages,
+ boolean isStaged,
+ List<VersionedPackage> causePackages,
+ int committedSessionId,
+ @PackageManager.RollbackImpactLevel int rollbackImpactLevel) {
this.mRollbackId = rollbackId;
this.mPackages = packages;
this.mIsStaged = isStaged;
this.mCausePackages = causePackages;
this.mCommittedSessionId = committedSessionId;
+ this.mRollbackImpactLevel = rollbackImpactLevel;
+ }
+
+ /** @hide */
+ public RollbackInfo(
+ int rollbackId,
+ List<PackageRollbackInfo> packages,
+ boolean isStaged,
+ List<VersionedPackage> causePackages,
+ int committedSessionId) {
+ // If impact level is not set default to 0
+ this(
+ rollbackId,
+ packages,
+ isStaged,
+ causePackages,
+ committedSessionId,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
}
private RollbackInfo(Parcel in) {
@@ -61,34 +86,28 @@
mIsStaged = in.readBoolean();
mCausePackages = in.createTypedArrayList(VersionedPackage.CREATOR);
mCommittedSessionId = in.readInt();
+ mRollbackImpactLevel = in.readInt();
}
- /**
- * Returns a unique identifier for this rollback.
- */
+ /** Returns a unique identifier for this rollback. */
public int getRollbackId() {
return mRollbackId;
}
- /**
- * Returns the list of package that are rolled back.
- */
+ /** Returns the list of package that are rolled back. */
@NonNull
public List<PackageRollbackInfo> getPackages() {
return mPackages;
}
- /**
- * Returns true if this rollback requires reboot to take effect after
- * being committed.
- */
+ /** Returns true if this rollback requires reboot to take effect after being committed. */
public boolean isStaged() {
return mIsStaged;
}
/**
- * Returns the session ID for the committed rollback for staged rollbacks.
- * Only applicable for rollbacks that have been committed.
+ * Returns the session ID for the committed rollback for staged rollbacks. Only applicable for
+ * rollbacks that have been committed.
*/
public int getCommittedSessionId() {
return mCommittedSessionId;
@@ -96,6 +115,7 @@
/**
* Sets the session ID for the committed rollback for staged rollbacks.
+ *
* @hide
*/
public void setCommittedSessionId(int sessionId) {
@@ -103,15 +123,40 @@
}
/**
- * Gets the list of package versions that motivated this rollback.
- * As provided to {@link #commitRollback} when the rollback was committed.
- * This is only applicable for rollbacks that have been committed.
+ * Gets the list of package versions that motivated this rollback. As provided to {@link
+ * #commitRollback} when the rollback was committed. This is only applicable for rollbacks that
+ * have been committed.
*/
@NonNull
public List<VersionedPackage> getCausePackages() {
return mCausePackages;
}
+ /**
+ * Get rollback impact level. Refer {@link
+ * android.content.pm.PackageInstaller.SessionParams#setRollbackImpactLevel(int)} for more info
+ * on impact level.
+ *
+ * @hide
+ */
+ @TestApi
+ @FlaggedApi(Flags.FLAG_RECOVERABILITY_DETECTION)
+ public @PackageManager.RollbackImpactLevel int getRollbackImpactLevel() {
+ return mRollbackImpactLevel;
+ }
+
+ /**
+ * Set rollback impact level. Refer {@link
+ * android.content.pm.PackageInstaller.SessionParams#setRollbackImpactLevel(int)} for more info
+ * on impact level.
+ *
+ * @hide
+ */
+ public void setRollbackImpactLevel(
+ @PackageManager.RollbackImpactLevel int rollbackImpactLevel) {
+ mRollbackImpactLevel = rollbackImpactLevel;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -124,16 +169,17 @@
out.writeBoolean(mIsStaged);
out.writeTypedList(mCausePackages);
out.writeInt(mCommittedSessionId);
+ out.writeInt(mRollbackImpactLevel);
}
public static final @android.annotation.NonNull Parcelable.Creator<RollbackInfo> CREATOR =
new Parcelable.Creator<RollbackInfo>() {
- public RollbackInfo createFromParcel(Parcel in) {
- return new RollbackInfo(in);
- }
+ public RollbackInfo createFromParcel(Parcel in) {
+ return new RollbackInfo(in);
+ }
- public RollbackInfo[] newArray(int size) {
- return new RollbackInfo[size];
- }
- };
+ public RollbackInfo[] newArray(int size) {
+ return new RollbackInfo[size];
+ }
+ };
}
diff --git a/core/java/android/database/Cursor.java b/core/java/android/database/Cursor.java
index afa1c20..c00c18c 100644
--- a/core/java/android/database/Cursor.java
+++ b/core/java/android/database/Cursor.java
@@ -510,7 +510,7 @@
Bundle getExtras();
/**
- * This is an out-of-band way for the the user of a cursor to communicate with the cursor. The
+ * This is an out-of-band way for the user of a cursor to communicate with the cursor. The
* structure of each bundle is entirely defined by the cursor.
*
* <p>One use of this is to tell a cursor that it should retry its network request after it
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index c3fae55..059e99f 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -63,6 +63,9 @@
// active keyboard layout.
int getKeyCodeForKeyLocation(int deviceId, in int locationKeyCode);
+ // Returns the mouse pointer speed.
+ int getMousePointerSpeed();
+
// Temporarily changes the pointer speed.
void tryPointerSpeed(int speed);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index a0cceae..08fc5c2 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.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.SystemService;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
@@ -835,6 +836,28 @@
}
/**
+ * Returns the mouse pointer speed.
+ *
+ * <p>The pointer speed is a value between {@link InputSettings#MIN_POINTER_SPEED} and
+ * {@link InputSettings#MAX_POINTER_SPEED}, the default value being
+ * {@link InputSettings#DEFAULT_POINTER_SPEED}.
+ *
+ * <p> Note that while setting the mouse pointer speed, it's possible that the input reader has
+ * only received this value and has not yet completed reconfiguring itself with this value.
+ *
+ * @hide
+ */
+ @SuppressLint("UnflaggedApi") // TestApi without associated feature.
+ @TestApi
+ public int getMousePointerSpeed() {
+ try {
+ return mIm.getMousePointerSpeed();
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Changes the mouse pointer speed temporarily, but does not save the setting.
* <p>
* Requires {@link android.Manifest.permission#SET_POINTER_SPEED}.
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index 33960c0..042b0b7 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -48,8 +48,8 @@
/**
* Pointer Speed: The default pointer speed (0).
- * @hide
*/
+ @SuppressLint("UnflaggedApi") // TestApi without associated feature.
public static final int DEFAULT_POINTER_SPEED = 0;
/**
diff --git a/core/java/android/hardware/radio/OWNERS b/core/java/android/hardware/radio/OWNERS
index 302fdd7..51a85e4 100644
--- a/core/java/android/hardware/radio/OWNERS
+++ b/core/java/android/hardware/radio/OWNERS
@@ -1,4 +1,3 @@
xuweilin@google.com
oscarazu@google.com
ericjeong@google.com
-keunyoung@google.com
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index b69410c..a86396c 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -196,7 +196,8 @@
}
/**
- * Retrieves the input stream for this instance.
+ * Retrieves the input stream for this instance. Closing this stream is equivalent to closing
+ * the entire socket and its associated streams using {@link #close()}.
*
* @return input stream
* @throws IOException if socket has been closed or cannot be created.
@@ -207,7 +208,8 @@
}
/**
- * Retrieves the output stream for this instance.
+ * Retrieves the output stream for this instance. Closing this stream is equivalent to closing
+ * the entire socket and its associated streams using {@link #close()}.
*
* @return output stream
* @throws IOException if socket has been closed or cannot be created.
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 365f913..594ec18 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -16,6 +16,7 @@
package android.net;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.ActivityManager.procStateToString;
import static android.content.pm.PackageManager.GET_SIGNATURES;
@@ -170,6 +171,8 @@
public static final String FIREWALL_CHAIN_NAME_RESTRICTED = "restricted";
/** @hide */
public static final String FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY = "low_power_standby";
+ /** @hide */
+ public static final String FIREWALL_CHAIN_NAME_BACKGROUND = "background";
private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
@@ -180,6 +183,9 @@
/** @hide */
public static final int TOP_THRESHOLD_STATE = ActivityManager.PROCESS_STATE_BOUND_TOP;
+ /** @hide */
+ public static final int BACKGROUND_THRESHOLD_STATE = ActivityManager.PROCESS_STATE_TOP_SLEEPING;
+
/**
* {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
* applies to.
@@ -264,6 +270,16 @@
* @hide
*/
public static final int ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST = 1 << 6;
+
+ /**
+ * Flag to indicate that the app is exempt from always-on background network restrictions.
+ * Note that this is explicitly different to the flag NOT_FOREGROUND which is used to grant
+ * shared exception to apps from power restrictions like doze, battery saver and app-standby.
+ *
+ * @hide
+ */
+ public static final int ALLOWED_REASON_NOT_IN_BACKGROUND = 1 << 7;
+
/**
* Flag to indicate that app is exempt from certain metered network restrictions because user
* explicitly exempted it.
@@ -822,6 +838,21 @@
}
/**
+ * This is currently only used as an implementation detail for
+ * {@link com.android.server.net.NetworkPolicyManagerService}.
+ * Only put here to be together with other isProcStateAllowed* methods.
+ *
+ * @hide
+ */
+ public static boolean isProcStateAllowedNetworkWhileBackground(@Nullable UidState uidState) {
+ if (uidState == null) {
+ return false;
+ }
+ return uidState.procState < BACKGROUND_THRESHOLD_STATE
+ || (uidState.capability & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0;
+ }
+
+ /**
* Returns true if {@param procState} is considered foreground and as such will be allowed
* to access network when the device is in data saver mode. Otherwise, false.
* @hide
diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig
index 0ad1804..9f9aef8 100644
--- a/core/java/android/net/flags.aconfig
+++ b/core/java/android/net/flags.aconfig
@@ -1,50 +1,25 @@
-package: "com.android.net.flags"
+package: "android.net.platform.flags"
+
+# This file contains aconfig flags used from platform code
+# Flags used for module APIs must be in aconfig files under each modules
flag {
- name: "track_multiple_network_activities"
- namespace: "android_core_networking"
- description: "NetworkActivityTracker tracks multiple networks including non default networks"
- bug: "267870186"
+ name: "ipsec_transform_state"
+ namespace: "core_networking_ipsec"
+ description: "The flag controls the access for getIpSecTransformState and IpSecTransformState"
+ bug: "308011229"
}
flag {
- name: "forbidden_capability"
- namespace: "android_core_networking"
- description: "This flag controls the forbidden capability API"
- bug: "302997505"
-}
-
-flag {
- name: "set_data_saver_via_cm"
- namespace: "android_core_networking"
- description: "Set data saver through ConnectivityManager API"
- bug: "297836825"
-}
-
-flag {
- name: "support_is_uid_networking_blocked"
- namespace: "android_core_networking"
- description: "This flag controls whether isUidNetworkingBlocked is supported"
- bug: "297836825"
-}
-
-flag {
- name: "basic_background_restrictions_enabled"
- namespace: "android_core_networking"
- description: "Block network access for apps in a low importance background state"
- bug: "304347838"
+ name: "powered_off_finding_platform"
+ namespace: "nearby"
+ description: "Controls whether the Powered Off Finding feature is enabled"
+ bug: "307898240"
}
flag {
name: "register_nsd_offload_engine"
namespace: "android_core_networking"
- description: "The flag controls the access for registerOffloadEngine API in NsdManager"
+ description: "Flag for registerOffloadEngine API in NsdManager"
bug: "294777050"
}
-
-flag {
- name: "ipsec_transform_state"
- namespace: "android_core_networking_ipsec"
- description: "The flag controls the access for getIpSecTransformState and IpSecTransformState"
- bug: "308011229"
-}
diff --git a/core/java/android/net/thread/OWNERS b/core/java/android/net/thread/OWNERS
new file mode 100644
index 0000000..55c307b
--- /dev/null
+++ b/core/java/android/net/thread/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 1203089
+
+include platform/packages/modules/ThreadNetwork:/OWNERS
diff --git a/core/java/android/net/thread/flags.aconfig b/core/java/android/net/thread/flags.aconfig
new file mode 100644
index 0000000..d679f9c
--- /dev/null
+++ b/core/java/android/net/thread/flags.aconfig
@@ -0,0 +1,18 @@
+package: "com.android.net.thread.platform.flags"
+
+# This file contains aconfig flags used from platform code
+# Flags used for module APIs must be in aconfig files under each modules
+
+flag {
+ name: "thread_user_restriction_enabled"
+ namespace: "thread_network"
+ description: "Controls whether user restriction on thread networks is enabled"
+ bug: "307679182"
+}
+
+flag {
+ name: "thread_enabled_platform"
+ namespace: "thread_network"
+ description: "Controls whether the Android Thread feature is enabled"
+ bug: "301473012"
+}
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 70cf973..83b7eda 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -80,8 +80,6 @@
* <p>The VCN will only migrate to a Carrier WiFi network that has a signal strength greater
* than, or equal to this threshold.
*
- * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup.
- *
* @hide
*/
@NonNull
@@ -94,14 +92,39 @@
* <p>If the VCN's selected Carrier WiFi network has a signal strength less than this threshold,
* the VCN will attempt to migrate away from the Carrier WiFi network.
*
- * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup.
- *
* @hide
*/
@NonNull
public static final String VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY =
"vcn_network_selection_wifi_exit_rssi_threshold";
+ /**
+ * Key for the interval to poll IpSecTransformState for packet loss monitoring
+ *
+ * @hide
+ */
+ @NonNull
+ public static final String VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY =
+ "vcn_network_selection_poll_ipsec_state_interval_seconds";
+
+ /**
+ * Key for the threshold of IPSec packet loss rate
+ *
+ * @hide
+ */
+ @NonNull
+ public static final String VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY =
+ "vcn_network_selection_ipsec_packet_loss_percent_threshold";
+
+ /**
+ * Key for the list of timeouts in minute to stop penalizing an underlying network candidate
+ *
+ * @hide
+ */
+ @NonNull
+ public static final String VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY =
+ "vcn_network_selection_penalty_timeout_minutes_list";
+
// TODO: Add separate signal strength thresholds for 2.4 GHz and 5GHz
/**
@@ -115,6 +138,20 @@
"vcn_restricted_transports";
/**
+ * Key for number of seconds to wait before entering safe mode
+ *
+ * <p>A VcnGatewayConnection will enter safe mode when it takes over the configured timeout to
+ * enter {@link ConnectedState}.
+ *
+ * <p>Defaults to 30, unless overridden by carrier config
+ *
+ * @hide
+ */
+ @NonNull
+ public static final String VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY =
+ "vcn_safe_mode_timeout_seconds_key";
+
+ /**
* Key for maximum number of parallel SAs for tunnel aggregation
*
* <p>If set to a value > 1, multiple tunnels will be set up, and inbound traffic will be
@@ -134,7 +171,11 @@
new String[] {
VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
+ VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY,
+ VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY,
+ VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY,
VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
+ VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY,
VCN_TUNNEL_AGGREGATION_SA_COUNT_MAX_KEY,
};
diff --git a/core/java/android/net/vcn/flags.aconfig b/core/java/android/net/vcn/flags.aconfig
index 6956916..7afd721 100644
--- a/core/java/android/net/vcn/flags.aconfig
+++ b/core/java/android/net/vcn/flags.aconfig
@@ -5,4 +5,18 @@
namespace: "vcn"
description: "Feature flag for safe mode configurability"
bug: "276358140"
+}
+
+flag {
+ name: "safe_mode_timeout_config"
+ namespace: "vcn"
+ description: "Feature flag for adjustable safe mode timeout"
+ bug: "317406085"
+}
+
+flag{
+ name: "network_metric_monitor"
+ namespace: "vcn"
+ description: "Feature flag for enabling network metric monitor"
+ bug: "282996138"
}
\ No newline at end of file
diff --git a/core/java/android/nfc/OWNERS b/core/java/android/nfc/OWNERS
deleted file mode 100644
index 35e9713..0000000
--- a/core/java/android/nfc/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 48448
-include platform/packages/apps/Nfc:/OWNERS
diff --git a/core/java/android/nfc/TEST_MAPPING b/core/java/android/nfc/TEST_MAPPING
deleted file mode 100644
index 5b5ea37..0000000
--- a/core/java/android/nfc/TEST_MAPPING
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "presubmit": [
- {
- "name": "NfcManagerTests"
- },
- {
- "name": "CtsNfcTestCases"
- }
- ]
-}
diff --git a/core/java/android/os/ArtModuleServiceManager.java b/core/java/android/os/ArtModuleServiceManager.java
index 0009e61..e0b631d 100644
--- a/core/java/android/os/ArtModuleServiceManager.java
+++ b/core/java/android/os/ArtModuleServiceManager.java
@@ -15,9 +15,11 @@
*/
package android.os;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.content.pm.Flags;
/**
* Provides a way to register and obtain the system service binder objects managed by the ART
@@ -60,4 +62,18 @@
public ServiceRegisterer getArtdServiceRegisterer() {
return new ServiceRegisterer("artd");
}
+
+ /** Returns {@link ServiceRegisterer} for the "artd_pre_reboot" service. */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_USE_ART_SERVICE_V2)
+ public ServiceRegisterer getArtdPreRebootServiceRegisterer() {
+ return new ServiceRegisterer("artd_pre_reboot");
+ }
+
+ /** Returns {@link ServiceRegisterer} for the "dexopt_chroot_setup" service. */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_USE_ART_SERVICE_V2)
+ public ServiceRegisterer getDexoptChrootSetupServiceRegisterer() {
+ return new ServiceRegisterer("dexopt_chroot_setup");
+ }
}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 218d4bb..0c753a5 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -309,7 +309,11 @@
* If the current thread is not currently executing an incoming transaction,
* then its own PID is returned.
*
- * Warning: oneway transactions do not receive PID.
+ * Warning: oneway transactions do not receive PID. Even if you expect
+ * a transaction to be synchronous, a misbehaving client could send it
+ * as a asynchronous call and result in a 0 PID here. Additionally, if
+ * there is a race and the calling process dies, the PID may still be
+ * 0 for a synchronous call.
*/
@CriticalNative
public static final native int getCallingPid();
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index a9b7257..5871717 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1315,9 +1315,7 @@
if (IS_ENG) return true;
if (IS_TREBLE_ENABLED) {
- // If we can run this code, the device should already pass AVB.
- // So, we don't need to check AVB here.
- int result = VintfObject.verifyWithoutAvb();
+ int result = VintfObject.verifyBuildAtBoot();
if (result != 0) {
Slog.e(TAG, "Vendor interface is incompatible, error="
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 5b24dca..3de8628 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -25,6 +25,7 @@
import static android.system.OsConstants.EINVAL;
import static android.system.OsConstants.ENOSYS;
import static android.system.OsConstants.F_OK;
+import static android.system.OsConstants.EIO;
import static android.system.OsConstants.O_ACCMODE;
import static android.system.OsConstants.O_APPEND;
import static android.system.OsConstants.O_CREAT;
@@ -37,6 +38,7 @@
import static android.system.OsConstants.SPLICE_F_MOVE;
import static android.system.OsConstants.S_ISFIFO;
import static android.system.OsConstants.S_ISREG;
+import static android.system.OsConstants.S_ISSOCK;
import static android.system.OsConstants.W_OK;
import android.annotation.NonNull;
@@ -459,6 +461,8 @@
}
} else if (S_ISFIFO(st_in.st_mode) || S_ISFIFO(st_out.st_mode)) {
return copyInternalSplice(in, out, count, signal, executor, listener);
+ } else if (S_ISSOCK(st_in.st_mode) || S_ISSOCK(st_out.st_mode)) {
+ return copyInternalSpliceSocket(in, out, count, signal, executor, listener);
}
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
@@ -509,6 +513,86 @@
}
return progress;
}
+ /**
+ * Requires one of input or output to be a socket file.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static long copyInternalSpliceSocket(FileDescriptor in, FileDescriptor out, long count,
+ CancellationSignal signal, Executor executor, ProgressListener listener)
+ throws ErrnoException {
+ long progress = 0;
+ long checkpoint = 0;
+ long countToRead = count;
+ long countInPipe = 0;
+ long t;
+
+ FileDescriptor[] pipes = Os.pipe();
+
+ while (countToRead > 0 || countInPipe > 0) {
+ if (countToRead > 0) {
+ t = Os.splice(in, null, pipes[1], null, Math.min(countToRead, COPY_CHECKPOINT_BYTES),
+ SPLICE_F_MOVE | SPLICE_F_MORE);
+ if (t < 0) {
+ // splice error
+ Slog.e(TAG, "splice error, fdIn --> pipe, copy size:" + count +
+ ", copied:" + progress +
+ ", read:" + (count - countToRead) +
+ ", in pipe:" + countInPipe);
+ break;
+ } else if (t == 0) {
+ // end of input, input count larger than real size
+ Slog.w(TAG, "Reached the end of the input file. The size to be copied exceeds the actual size, copy size:" + count +
+ ", copied:" + progress +
+ ", read:" + (count - countToRead) +
+ ", in pipe:" + countInPipe);
+ countToRead = 0;
+ } else {
+ countInPipe += t;
+ countToRead -= t;
+ }
+ }
+
+ if (countInPipe > 0) {
+ t = Os.splice(pipes[0], null, out, null, Math.min(countInPipe, COPY_CHECKPOINT_BYTES),
+ SPLICE_F_MOVE | SPLICE_F_MORE);
+ // The data is already in the pipeline, so the return value will not be zero.
+ // If it is 0, it means an error has occurred. So here use t<=0.
+ if (t <= 0) {
+ Slog.e(TAG, "splice error, pipe --> fdOut, copy size:" + count +
+ ", copied:" + progress +
+ ", read:" + (count - countToRead) +
+ ", in pipe: " + countInPipe);
+ throw new ErrnoException("splice, pipe --> fdOut", EIO);
+ } else {
+ progress += t;
+ checkpoint += t;
+ countInPipe -= t;
+ }
+ }
+
+ if (checkpoint >= COPY_CHECKPOINT_BYTES) {
+ if (signal != null) {
+ signal.throwIfCanceled();
+ }
+ if (executor != null && listener != null) {
+ final long progressSnapshot = progress;
+ executor.execute(() -> {
+ listener.onProgress(progressSnapshot);
+ });
+ }
+ checkpoint = 0;
+ }
+ }
+ if (executor != null && listener != null) {
+ final long progressSnapshot = progress;
+ executor.execute(() -> {
+ listener.onProgress(progressSnapshot);
+ });
+ }
+ return progress;
+ }
/**
* Requires both input and output to be a regular file.
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 8fcff78..3149de4 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -673,6 +673,7 @@
if (anglePkg.isEmpty()) {
return;
}
+ intent.setPackage(anglePkg);
context.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
@Override
diff --git a/core/java/android/os/HidlSupport.java b/core/java/android/os/HidlSupport.java
index 91b796a..7716055 100644
--- a/core/java/android/os/HidlSupport.java
+++ b/core/java/android/os/HidlSupport.java
@@ -218,6 +218,13 @@
@SystemApi
public static native int getPidIfSharable();
+ /**
+ * Return true if HIDL is supported on this device and false if not.
+ *
+ * @hide
+ */
+ public static native boolean isHidlSupported();
+
/** @hide */
public HidlSupport() {}
}
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index feed208..bc19655 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -18,6 +18,7 @@
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.util.Log;
import libcore.util.NativeAllocationRegistry;
@@ -78,6 +79,17 @@
String iface,
String serviceName)
throws RemoteException, NoSuchElementException {
+ if (!HidlSupport.isHidlSupported()
+ && (iface.equals("android.hidl.manager@1.0::IServiceManager")
+ || iface.equals("android.hidl.manager@1.1::IServiceManager")
+ || iface.equals("android.hidl.manager@1.2::IServiceManager"))) {
+ Log.i(
+ TAG,
+ "Replacing Java hwservicemanager with a fake HwNoService"
+ + " because HIDL is not supported on this device.");
+ return new HwNoService();
+ }
+
return getService(iface, serviceName, false /* retry */);
}
/**
diff --git a/core/java/android/os/HwNoService.java b/core/java/android/os/HwNoService.java
new file mode 100644
index 0000000..0840314
--- /dev/null
+++ b/core/java/android/os/HwNoService.java
@@ -0,0 +1,142 @@
+/*
+ * 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.os;
+
+import android.hidl.manager.V1_2.IServiceManager;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * A fake hwservicemanager that is used locally when HIDL isn't supported on the device.
+ *
+ * @hide
+ */
+final class HwNoService extends IServiceManager.Stub implements IHwBinder, IHwInterface {
+ private static final String TAG = "HwNoService";
+
+ /** @hide */
+ @Override
+ public String toString() {
+ return "[HwNoService]";
+ }
+
+ @Override
+ public android.hidl.base.V1_0.IBase get(String fqName, String name)
+ throws android.os.RemoteException {
+ Log.i(TAG, "get " + fqName + "/" + name + " with no hwservicemanager");
+ return null;
+ }
+
+ @Override
+ public boolean add(String name, android.hidl.base.V1_0.IBase service)
+ throws android.os.RemoteException {
+ Log.i(TAG, "get " + name + " with no hwservicemanager");
+ return false;
+ }
+
+ @Override
+ public byte getTransport(String fqName, String name) throws android.os.RemoteException {
+ Log.i(TAG, "getTransoport " + fqName + "/" + name + " with no hwservicemanager");
+ return 0x0;
+ }
+
+ @Override
+ public java.util.ArrayList<String> list() throws android.os.RemoteException {
+ Log.i(TAG, "list with no hwservicemanager");
+ return new ArrayList<String>();
+ }
+
+ @Override
+ public java.util.ArrayList<String> listByInterface(String fqName)
+ throws android.os.RemoteException {
+ Log.i(TAG, "listByInterface with no hwservicemanager");
+ return new ArrayList<String>();
+ }
+
+ @Override
+ public boolean registerForNotifications(
+ String fqName, String name, android.hidl.manager.V1_0.IServiceNotification callback)
+ throws android.os.RemoteException {
+ Log.i(TAG, "registerForNotifications with no hwservicemanager");
+ return true;
+ }
+
+ @Override
+ public ArrayList<android.hidl.manager.V1_0.IServiceManager.InstanceDebugInfo> debugDump()
+ throws android.os.RemoteException {
+ Log.i(TAG, "debugDump with no hwservicemanager");
+ return new ArrayList<android.hidl.manager.V1_0.IServiceManager.InstanceDebugInfo>();
+ }
+
+ @Override
+ public void registerPassthroughClient(String fqName, String name)
+ throws android.os.RemoteException {
+ Log.i(TAG, "registerPassthroughClient with no hwservicemanager");
+ }
+
+ @Override
+ public boolean unregisterForNotifications(
+ String fqName, String name, android.hidl.manager.V1_0.IServiceNotification callback)
+ throws android.os.RemoteException {
+ Log.i(TAG, "unregisterForNotifications with no hwservicemanager");
+ return true;
+ }
+
+ @Override
+ public boolean registerClientCallback(
+ String fqName,
+ String name,
+ android.hidl.base.V1_0.IBase server,
+ android.hidl.manager.V1_2.IClientCallback cb)
+ throws android.os.RemoteException {
+ Log.i(
+ TAG,
+ "registerClientCallback for " + fqName + "/" + name + " with no hwservicemanager");
+ return true;
+ }
+
+ @Override
+ public boolean unregisterClientCallback(
+ android.hidl.base.V1_0.IBase server, android.hidl.manager.V1_2.IClientCallback cb)
+ throws android.os.RemoteException {
+ Log.i(TAG, "unregisterClientCallback with no hwservicemanager");
+ return true;
+ }
+
+ @Override
+ public boolean addWithChain(
+ String name, android.hidl.base.V1_0.IBase service, java.util.ArrayList<String> chain)
+ throws android.os.RemoteException {
+ Log.i(TAG, "addWithChain with no hwservicemanager");
+ return true;
+ }
+
+ @Override
+ public java.util.ArrayList<String> listManifestByInterface(String fqName)
+ throws android.os.RemoteException {
+ Log.i(TAG, "listManifestByInterface for " + fqName + " with no hwservicemanager");
+ return new ArrayList<String>();
+ }
+
+ @Override
+ public boolean tryUnregister(String fqName, String name, android.hidl.base.V1_0.IBase service)
+ throws android.os.RemoteException {
+ Log.i(TAG, "tryUnregister for " + fqName + "/" + name + " with no hwservicemanager");
+ return true;
+ }
+}
diff --git a/core/java/android/os/ISystemConfig.aidl b/core/java/android/os/ISystemConfig.aidl
index 61b24aa..b7649ba 100644
--- a/core/java/android/os/ISystemConfig.aidl
+++ b/core/java/android/os/ISystemConfig.aidl
@@ -52,4 +52,9 @@
* @see SystemConfigManager#getDefaultVrComponents
*/
List<ComponentName> getDefaultVrComponents();
+
+ /**
+ * @see SystemConfigManager#getPreventUserDisablePackages
+ */
+ List<String> getPreventUserDisablePackages();
}
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 463be37..9c165f7 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -83,8 +83,19 @@
# PerformanceHintManager
per-file PerformanceHintManager.java = file:/ADPF_OWNERS
+per-file WorkDuration.java = file:/ADPF_OWNERS
# IThermal interfaces
per-file IThermal* = file:/THERMAL_OWNERS
per-file CoolingDevice.java = file:/THERMAL_OWNERS
per-file Temperature.java = file:/THERMAL_OWNERS
+
+# SecurityStateManager
+per-file *SecurityStateManager* = file:/SECURITY_STATE_OWNERS
+
+# SystemConfig
+per-file ISystemConfig.aidl = file:/PACKAGE_MANAGER_OWNERS
+per-file SystemConfigManager.java = file:/PACKAGE_MANAGER_OWNERS
+
+# ProfilingService
+per-file ProfilingServiceManager.java = file:/PERFORMANCE_OWNERS
diff --git a/core/java/android/os/OomKillRecord.java b/core/java/android/os/OomKillRecord.java
new file mode 100644
index 0000000..151a65f
--- /dev/null
+++ b/core/java/android/os/OomKillRecord.java
@@ -0,0 +1,63 @@
+/*
+ * 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.os;
+
+
+/**
+ * Expected data to get back from the OOM event's file.
+ * Note that this should be equivalent to the struct <b>OomKill</b> inside
+ * <pre>
+ * system/memory/libmeminfo/libmemevents/include/memevents.h
+ * </pre>
+ *
+ * @hide
+ */
+public final class OomKillRecord {
+ private long mTimeStampInMillis;
+ private int mPid;
+ private int mUid;
+ private String mProcessName;
+ private short mOomScoreAdj;
+
+ public OomKillRecord(long timeStampInMillis, int pid, int uid,
+ String processName, short oomScoreAdj) {
+ this.mTimeStampInMillis = timeStampInMillis;
+ this.mPid = pid;
+ this.mUid = uid;
+ this.mProcessName = processName;
+ this.mOomScoreAdj = oomScoreAdj;
+ }
+
+ public long getTimestampMilli() {
+ return mTimeStampInMillis;
+ }
+
+ public int getPid() {
+ return mPid;
+ }
+
+ public int getUid() {
+ return mUid;
+ }
+
+ public String getProcessName() {
+ return mProcessName;
+ }
+
+ public short getOomScoreAdj() {
+ return mOomScoreAdj;
+ }
+}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 04525e8..bccea93 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1471,7 +1471,15 @@
@UnsupportedAppUsage
public static final native long getPss(int pid);
- /** @hide */
+ /**
+ * Gets the total Rss value for a given process, in bytes.
+ *
+ * @param pid the process to the Rss for
+ * @return an ordered array containing multiple values, they are:
+ * [total_rss, file, anon, swap, shmem].
+ * or NULL if the value cannot be determined
+ * @hide
+ */
public static final native long[] getRss(int pid);
/**
@@ -1505,7 +1513,7 @@
* fully removed, otherwise system resources may leak.
* @hide
*/
- public static final native int sendSignalToProcessGroup(int uid, int pid, int signal);
+ public static final native boolean sendSignalToProcessGroup(int uid, int pid, int signal);
/**
* Freeze the cgroup for the given UID.
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index a3b836a..d002fe1 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -18,8 +18,6 @@
import static android.view.Display.DEFAULT_DISPLAY;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -47,11 +45,8 @@
import android.util.Log;
import android.view.Display;
-import libcore.io.Streams;
-
import java.io.ByteArrayInputStream;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
@@ -73,7 +68,6 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-import java.util.zip.ZipInputStream;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
@@ -423,72 +417,43 @@
} finally {
raf.close();
}
-
- // Additionally verify the package compatibility.
- if (!readAndVerifyPackageCompatibilityEntry(packageFile)) {
- throw new SignatureException("package compatibility verification failed");
- }
}
/**
* Verifies the compatibility entry from an {@link InputStream}.
*
- * @return the verification result.
+ * @param inputStream The stream that contains the package compatibility info.
+ * @throws IOException Never.
+ * @return {@code true}.
+ * @deprecated This function no longer checks {@code inputStream} and
+ * unconditionally returns true. Instead, check compatibility when the
+ * OTA package is generated.
*/
- @UnsupportedAppUsage
+ @Deprecated
+ @UnsupportedAppUsage(
+ publicAlternatives = "Use {@code true} directly",
+ maxTargetSdk = Build.VERSION_CODES.VANILLA_ICE_CREAM)
private static boolean verifyPackageCompatibility(InputStream inputStream) throws IOException {
- ArrayList<String> list = new ArrayList<>();
- ZipInputStream zis = new ZipInputStream(inputStream);
- ZipEntry entry;
- while ((entry = zis.getNextEntry()) != null) {
- long entrySize = entry.getSize();
- if (entrySize > Integer.MAX_VALUE || entrySize < 0) {
- throw new IOException(
- "invalid entry size (" + entrySize + ") in the compatibility file");
- }
- byte[] bytes = new byte[(int) entrySize];
- Streams.readFully(zis, bytes);
- list.add(new String(bytes, UTF_8));
- }
- if (list.isEmpty()) {
- throw new IOException("no entries found in the compatibility file");
- }
- return (VintfObject.verify(list.toArray(new String[list.size()])) == 0);
- }
-
- /**
- * Reads and verifies the compatibility entry in an OTA zip package. The compatibility entry is
- * a zip file (inside the OTA package zip).
- *
- * @return {@code true} if the entry doesn't exist or verification passes.
- */
- private static boolean readAndVerifyPackageCompatibilityEntry(File packageFile)
- throws IOException {
- try (ZipFile zip = new ZipFile(packageFile)) {
- ZipEntry entry = zip.getEntry("compatibility.zip");
- if (entry == null) {
- return true;
- }
- InputStream inputStream = zip.getInputStream(entry);
- return verifyPackageCompatibility(inputStream);
- }
+ return true;
}
/**
* Verifies the package compatibility info against the current system.
*
* @param compatibilityFile the {@link File} that contains the package compatibility info.
- * @throws IOException if there were any errors reading the compatibility file.
- * @return the compatibility verification result.
+ * @throws IOException Never.
+ * @return {@code true}
+ * @deprecated This function no longer checks {@code compatibilityFile} and
+ * unconditionally returns true. Instead, check compatibility when the
+ * OTA package is generated.
*
* {@hide}
*/
+ @Deprecated
@SystemApi
@SuppressLint("RequiresPermission")
public static boolean verifyPackageCompatibility(File compatibilityFile) throws IOException {
- try (InputStream inputStream = new FileInputStream(compatibilityFile)) {
- return verifyPackageCompatibility(inputStream);
- }
+ return true;
}
/**
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index d12e3b2..4205b2c 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -2440,11 +2440,12 @@
/** @hide */
public static void onVmPolicyViolation(Violation violation, boolean forceDeath) {
- final boolean penaltyDropbox = (sVmPolicy.mask & PENALTY_DROPBOX) != 0;
- final boolean penaltyDeath = ((sVmPolicy.mask & PENALTY_DEATH) != 0) || forceDeath;
- final boolean penaltyLog = (sVmPolicy.mask & PENALTY_LOG) != 0;
+ final VmPolicy vmPolicy = getVmPolicy();
+ final boolean penaltyDropbox = (vmPolicy.mask & PENALTY_DROPBOX) != 0;
+ final boolean penaltyDeath = ((vmPolicy.mask & PENALTY_DEATH) != 0) || forceDeath;
+ final boolean penaltyLog = (vmPolicy.mask & PENALTY_LOG) != 0;
- final int penaltyMask = (sVmPolicy.mask & PENALTY_ALL);
+ final int penaltyMask = (vmPolicy.mask & PENALTY_ALL);
final ViolationInfo info = new ViolationInfo(violation, penaltyMask);
// Erase stuff not relevant for process-wide violations
@@ -2497,10 +2498,10 @@
// If penaltyDeath, we can't guarantee this callback finishes before the process dies for
// all executors. penaltyDeath supersedes penaltyCallback.
- if (sVmPolicy.mListener != null && sVmPolicy.mCallbackExecutor != null) {
- final OnVmViolationListener listener = sVmPolicy.mListener;
+ if (vmPolicy.mListener != null && vmPolicy.mCallbackExecutor != null) {
+ final OnVmViolationListener listener = vmPolicy.mListener;
try {
- sVmPolicy.mCallbackExecutor.execute(
+ vmPolicy.mCallbackExecutor.execute(
() -> {
// Lift violated policy to prevent infinite recursion.
VmPolicy oldPolicy = allowVmViolations();
diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java
index 77843d9..21ffbf1 100644
--- a/core/java/android/os/SystemConfigManager.java
+++ b/core/java/android/os/SystemConfigManager.java
@@ -161,4 +161,18 @@
}
return Collections.emptyList();
}
+
+ /**
+ * Return the packages that are prevented from being disabled, where if
+ * disabled it would result in a non-functioning system or similar.
+ * @hide
+ */
+ @NonNull
+ public List<String> getPreventUserDisablePackages() {
+ try {
+ return mInterface.getPreventUserDisablePackages();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/os/UpdateEngineStable.java b/core/java/android/os/UpdateEngineStable.java
new file mode 100644
index 0000000..9e2593e
--- /dev/null
+++ b/core/java/android/os/UpdateEngineStable.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.os;
+
+import android.annotation.IntDef;
+
+/**
+ * UpdateEngineStable handles calls to the update engine stalbe which takes care of A/B OTA updates.
+ * This interface has lesser functionalities than UpdateEngine and doesn't allow cancel.
+ *
+ * <p>The minimal flow is:
+ *
+ * <ol>
+ * <li>Create a new UpdateEngineStable instance.
+ * <li>Call {@link #bind}, provide callback function.
+ * <li>Call {@link #applyPayloadFd}.
+ * </ol>
+ *
+ * The APIs defined in this class and UpdateEngineStableCallback class must be in sync with the ones
+ * in {@code system/update_engine/stable/android/os/IUpdateEngineStable.aidl} and {@code
+ * ssystem/update_engine/stable/android/os/IUpdateEngineStableCallback.aidl}.
+ *
+ * @hide
+ */
+public class UpdateEngineStable {
+ private static final String TAG = "UpdateEngineStable";
+
+ private static final String UPDATE_ENGINE_STABLE_SERVICE =
+ "android.os.UpdateEngineStableService";
+
+ /**
+ * Error codes from update engine upon finishing a call to {@link applyPayloadFd}. Values will
+ * be passed via the callback function {@link
+ * UpdateEngineStableCallback#onPayloadApplicationComplete}. Values must agree with the ones in
+ * {@code system/update_engine/common/error_code.h}.
+ */
+ /** @hide */
+ @IntDef(
+ value = {
+ UpdateEngine.ErrorCodeConstants.SUCCESS,
+ UpdateEngine.ErrorCodeConstants.ERROR,
+ UpdateEngine.ErrorCodeConstants.FILESYSTEM_COPIER_ERROR,
+ UpdateEngine.ErrorCodeConstants.POST_INSTALL_RUNNER_ERROR,
+ UpdateEngine.ErrorCodeConstants.PAYLOAD_MISMATCHED_TYPE_ERROR,
+ UpdateEngine.ErrorCodeConstants.INSTALL_DEVICE_OPEN_ERROR,
+ UpdateEngine.ErrorCodeConstants.KERNEL_DEVICE_OPEN_ERROR,
+ UpdateEngine.ErrorCodeConstants.DOWNLOAD_TRANSFER_ERROR,
+ UpdateEngine.ErrorCodeConstants.PAYLOAD_HASH_MISMATCH_ERROR,
+ UpdateEngine.ErrorCodeConstants.PAYLOAD_SIZE_MISMATCH_ERROR,
+ UpdateEngine.ErrorCodeConstants.DOWNLOAD_PAYLOAD_VERIFICATION_ERROR,
+ UpdateEngine.ErrorCodeConstants.PAYLOAD_TIMESTAMP_ERROR,
+ UpdateEngine.ErrorCodeConstants.UPDATED_BUT_NOT_ACTIVE,
+ UpdateEngine.ErrorCodeConstants.NOT_ENOUGH_SPACE,
+ UpdateEngine.ErrorCodeConstants.DEVICE_CORRUPTED,
+ })
+ public @interface ErrorCode {}
+
+ private final IUpdateEngineStable mUpdateEngineStable;
+ private IUpdateEngineStableCallback mUpdateEngineStableCallback = null;
+ private final Object mUpdateEngineStableCallbackLock = new Object();
+
+ /**
+ * Creates a new instance.
+ *
+ * @hide
+ */
+ public UpdateEngineStable() {
+ mUpdateEngineStable =
+ IUpdateEngineStable.Stub.asInterface(
+ ServiceManager.getService(UPDATE_ENGINE_STABLE_SERVICE));
+ if (mUpdateEngineStable == null) {
+ throw new IllegalStateException("Failed to find " + UPDATE_ENGINE_STABLE_SERVICE);
+ }
+ }
+
+ /**
+ * Prepares this instance for use. The callback will be notified on any status change, and when
+ * the update completes. A handler can be supplied to control which thread runs the callback, or
+ * null.
+ *
+ * @hide
+ */
+ public boolean bind(final UpdateEngineStableCallback callback, final Handler handler) {
+ synchronized (mUpdateEngineStableCallbackLock) {
+ mUpdateEngineStableCallback =
+ new IUpdateEngineStableCallback.Stub() {
+ @Override
+ public void onStatusUpdate(final int status, final float percent) {
+ if (handler != null) {
+ handler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ callback.onStatusUpdate(status, percent);
+ }
+ });
+ } else {
+ callback.onStatusUpdate(status, percent);
+ }
+ }
+
+ @Override
+ public void onPayloadApplicationComplete(final int errorCode) {
+ if (handler != null) {
+ handler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ callback.onPayloadApplicationComplete(errorCode);
+ }
+ });
+ } else {
+ callback.onPayloadApplicationComplete(errorCode);
+ }
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return super.VERSION;
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return super.HASH;
+ }
+ };
+
+ try {
+ return mUpdateEngineStable.bind(mUpdateEngineStableCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Equivalent to {@code bind(callback, null)}.
+ *
+ * @hide
+ */
+ public boolean bind(final UpdateEngineStableCallback callback) {
+ return bind(callback, null);
+ }
+
+ /**
+ * Applies payload from given ParcelFileDescriptor. Usage is same as UpdateEngine#applyPayload
+ *
+ * @hide
+ */
+ public void applyPayloadFd(
+ ParcelFileDescriptor fd, long offset, long size, String[] headerKeyValuePairs) {
+ try {
+ mUpdateEngineStable.applyPayloadFd(fd, offset, size, headerKeyValuePairs);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unbinds the last bound callback function.
+ *
+ * @hide
+ */
+ public boolean unbind() {
+ synchronized (mUpdateEngineStableCallbackLock) {
+ if (mUpdateEngineStableCallback == null) {
+ return true;
+ }
+ try {
+ boolean result = mUpdateEngineStable.unbind(mUpdateEngineStableCallback);
+ mUpdateEngineStableCallback = null;
+ return result;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+}
diff --git a/core/java/android/os/UpdateEngineStableCallback.java b/core/java/android/os/UpdateEngineStableCallback.java
new file mode 100644
index 0000000..4bcfb4ba
--- /dev/null
+++ b/core/java/android/os/UpdateEngineStableCallback.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.os;
+
+/**
+ * Callback function for UpdateEngineStable. Used to keep the caller up to date with progress, so
+ * the UI (if any) can be updated.
+ *
+ * <p>The APIs defined in this class and UpdateEngineStable class must be in sync with the ones in
+ * system/update_engine/stable/android/os/IUpdateEngineStable.aidl and
+ * system/update_engine/stable/android/os/IUpdateEngineStableCallback.aidl.
+ *
+ * <p>{@hide}
+ */
+public abstract class UpdateEngineStableCallback {
+
+ /**
+ * Invoked when anything changes. The value of {@code status} will be one of the values from
+ * {@link UpdateEngine.UpdateStatusConstants}, and {@code percent} will be valid
+ *
+ * @hide
+ */
+ public abstract void onStatusUpdate(int status, float percent);
+
+ /**
+ * Invoked when the payload has been applied, whether successfully or unsuccessfully. The value
+ * of {@code errorCode} will be one of the values from {@link UpdateEngine.ErrorCodeConstants}.
+ *
+ * @hide
+ */
+ public abstract void onPayloadApplicationComplete(@UpdateEngineStable.ErrorCode int errorCode);
+}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 97b53d7..ca87410 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1847,6 +1847,30 @@
"no_near_field_communication_radio";
/**
+ * This user restriction specifies if Thread network is disallowed on the device. If Thread
+ * network is disallowed it cannot be turned on via Settings.
+ *
+ * <p>This restriction can only be set by a device owner or a profile owner of an
+ * organization-owned managed profile on the parent profile.
+ * In both cases, the restriction applies globally on the device and will turn off the
+ * Thread network radio if it's currently on and prevent the radio from being turned
+ * on in the future.
+ *
+ * <p> <a href="https://www.threadgroup.org">Thread</a> is a low-power and low-latency wireless
+ * mesh networking protocol built on IPv6.
+ *
+ * <p>Default is <code>false</code>.
+ *
+ * <p>Key for user restrictions.
+ * <p>Type: Boolean
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ */
+ @FlaggedApi(com.android.net.thread.platform.flags.Flags.FLAG_THREAD_USER_RESTRICTION_ENABLED)
+ public static final String DISALLOW_THREAD_NETWORK = "no_thread_network";
+
+ /**
* List of key values that can be passed into the various user restriction related methods
* in {@link UserManager} & {@link DevicePolicyManager}.
* Note: This is slightly different from the real set of user restrictions listed in {@link
@@ -1931,6 +1955,7 @@
DISALLOW_ULTRA_WIDEBAND_RADIO,
DISALLOW_GRANT_ADMIN,
DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO,
+ DISALLOW_THREAD_NETWORK,
})
@Retention(RetentionPolicy.SOURCE)
public @interface UserRestrictionKey {}
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index 1f11197..5056557 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -18,7 +18,6 @@
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.util.Slog;
import java.util.Map;
@@ -32,6 +31,10 @@
private static final String LOG_TAG = "VintfObject";
+ static {
+ System.loadLibrary("vintf_jni");
+ }
+
/**
* Slurps all device information (both manifests and both matrices)
* and report them.
@@ -44,44 +47,8 @@
public static native String[] report();
/**
- * Verify that the given metadata for an OTA package is compatible with
- * this device.
- *
- * @param packageInfo a list of serialized form of HalManifest's /
- * CompatibilityMatri'ces (XML).
- * @return = 0 if success (compatible)
- * > 0 if incompatible
- * < 0 if any error (mount partition fails, illformed XML, etc.)
- *
- * @deprecated Checking compatibility against an OTA package is no longer
- * supported because the format of VINTF metadata in the OTA package may not
- * be recognized by the current system.
- *
- * <p>
- * <ul>
- * <li>This function always returns 0 for non-empty {@code packageInfo}.
- * </li>
- * <li>This function returns the result of {@link #verifyWithoutAvb} for
- * null or empty {@code packageInfo}.</li>
- * </ul>
- *
- * @hide
- */
- @Deprecated
- public static int verify(String[] packageInfo) {
- if (packageInfo != null && packageInfo.length > 0) {
- Slog.w(LOG_TAG, "VintfObject.verify() with non-empty packageInfo is deprecated. "
- + "Skipping compatibility checks for update package.");
- return 0;
- }
- Slog.w(LOG_TAG, "VintfObject.verify() is deprecated. Call verifyWithoutAvb() instead.");
- return verifyWithoutAvb();
- }
-
- /**
- * Verify Vintf compatibility on the device without checking AVB
- * (Android Verified Boot). It is useful to verify a running system
- * image where AVB check is irrelevant.
+ * Verify Vintf compatibility on the device at boot time. Certain checks
+ * like kernel checks, AVB checks are disabled.
*
* @return = 0 if success (compatible)
* > 0 if incompatible
@@ -89,7 +56,7 @@
*
* @hide
*/
- public static native int verifyWithoutAvb();
+ public static native int verifyBuildAtBoot();
/**
* @return a list of HAL names and versions that is supported by this
diff --git a/core/java/android/os/VintfRuntimeInfo.java b/core/java/android/os/VintfRuntimeInfo.java
index f17039b..e729063 100644
--- a/core/java/android/os/VintfRuntimeInfo.java
+++ b/core/java/android/os/VintfRuntimeInfo.java
@@ -28,6 +28,10 @@
private VintfRuntimeInfo() {}
+ static {
+ System.loadLibrary("vintf_jni");
+ }
+
/**
* @return /sys/fs/selinux/policyvers, via security_policyvers() native call
*
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 3cb5c60..c0539d6 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -71,7 +71,7 @@
*/
public class ZygoteProcess {
- private static final int ZYGOTE_CONNECT_TIMEOUT_MS = 20000;
+ private static final int ZYGOTE_CONNECT_TIMEOUT_MS = 60000;
/**
* Use a relatively short delay, because for app zygote, this is in the critical path of
diff --git a/core/java/android/os/incremental/OWNERS b/core/java/android/os/incremental/OWNERS
index 47eee64..a925564 100644
--- a/core/java/android/os/incremental/OWNERS
+++ b/core/java/android/os/incremental/OWNERS
@@ -1,6 +1,4 @@
# Bug component: 554432
-alexbuy@google.com
-schfan@google.com
-toddke@google.com
+include /PACKAGE_MANAGER_OWNERS
+
zyy@google.com
-patb@google.com
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 3ecf74e..54ed73c 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -134,16 +134,16 @@
@EnforcePermission("MOUNT_UNMOUNT_FILESYSTEMS")
void setDebugFlags(int flags, int mask) = 60;
@EnforcePermission("STORAGE_INTERNAL")
- void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) = 61;
+ void createUserStorageKeys(int userId, boolean ephemeral) = 61;
@EnforcePermission("STORAGE_INTERNAL")
void destroyUserStorageKeys(int userId) = 62;
@EnforcePermission("STORAGE_INTERNAL")
- void unlockCeStorage(int userId, int serialNumber, in byte[] secret) = 63;
+ void unlockCeStorage(int userId, in byte[] secret) = 63;
@EnforcePermission("STORAGE_INTERNAL")
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;
+ void prepareUserStorage(in String volumeUuid, int userId, int flags) = 66;
@EnforcePermission("STORAGE_INTERNAL")
void destroyUserStorage(in String volumeUuid, int userId, int flags) = 67;
@EnforcePermission("STORAGE_INTERNAL")
diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS
index bf22dcc..a26fb62 100644
--- a/core/java/android/os/storage/OWNERS
+++ b/core/java/android/os/storage/OWNERS
@@ -3,14 +3,17 @@
# Please assign new bugs to android-storage-triage@, not to individual people
# Android Storage Team
+aibra@google.com
+akgaurav@google.com
alukin@google.com
ankitavyas@google.com
dipankarb@google.com
gargshivam@google.com
+ishneet@google.com
krishang@google.com
+oeissa@google.com
riyaghai@google.com
sahanas@google.com
-sergeynv@google.com
shikhamalhotra@google.com
shubhisaxena@google.com
tylersaunders@google.com
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 4b9bd47..4c3f330 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1602,14 +1602,13 @@
* 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) {
+ public void createUserStorageKeys(int userId, boolean ephemeral) {
try {
- mStorageManager.createUserStorageKeys(userId, serialNumber, ephemeral);
+ mStorageManager.createUserStorageKeys(userId, ephemeral);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1653,9 +1652,9 @@
}
/** {@hide} */
- public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
+ public void prepareUserStorage(String volumeUuid, int userId, int flags) {
try {
- mStorageManager.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
+ mStorageManager.prepareUserStorage(volumeUuid, userId, flags);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1670,12 +1669,6 @@
}
}
- /** {@hide} */
- @TestApi
- public static boolean isUserKeyUnlocked(int userId) {
- return isCeStorageUnlocked(userId);
- }
-
/**
* Returns true if the user's credential-encrypted (CE) storage is unlocked.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2cc850d..82d33a9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5651,8 +5651,10 @@
* +7 = fastest
* @hide
*/
+ @SuppressLint({"NoSettingsProvider", "UnflaggedApi"}) // TestApi without associated feature.
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@Readable
+ @TestApi
public static final String POINTER_SPEED = "pointer_speed";
/**
@@ -12961,6 +12963,16 @@
@Readable
public static final String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
+
+ /**
+ * Whether to boot with 16K page size compatible kernel
+ * 1 = Boot with 16K kernel
+ * 0 = Boot with 4K kernel (default)
+ * @hide
+ */
+ @Readable
+ public static final String ENABLE_16K_PAGES = "enable_16k_pages";
+
/** Timeout for package verification.
* @hide */
@Readable
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 59b945c..db48bad 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -366,11 +366,13 @@
* <p>
* As of Android 11 apps will need specific permission to query other packages. To use
* this method an app must include in their AndroidManifest:
+ * <pre>{@code
* <queries>
* <intent>
* <action android:name="android.provider.Telephony.SMS_DELIVER"/>
* </intent>
* </queries>
+ * }</pre>
* Which will allow them to query packages which declare intent filters that include
* the {@link android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION} intent.
* </p>
diff --git a/core/java/android/security/OWNERS b/core/java/android/security/OWNERS
index 533d459..8bd6c85 100644
--- a/core/java/android/security/OWNERS
+++ b/core/java/android/security/OWNERS
@@ -1,7 +1,7 @@
# Bug component: 36824
brambonne@google.com
-brufino@google.com
+eranm@google.com
jeffv@google.com
per-file *NetworkSecurityPolicy.java = file:net/OWNERS
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index b56bef3..5e7edda 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -15,10 +15,11 @@
}
flag {
- name: "mgf1_digest_setter"
+ name: "mgf1_digest_setter_v2"
namespace: "hardware_backed_security"
description: "Feature flag for mgf1 digest setter in key generation and import parameters."
bug: "308378912"
+ is_fixed_read_only: true
}
flag {
@@ -30,6 +31,13 @@
}
flag {
+ name: "keyinfo_unlocked_device_required"
+ namespace: "hardware_backed_security"
+ description: "Add the API android.security.keystore.KeyInfo#isUnlockedDeviceRequired()"
+ bug: "296475382"
+}
+
+flag {
name: "deprecate_fsv_sig"
namespace: "hardware_backed_security"
description: "Feature flag for deprecating .fsv_sig"
@@ -50,3 +58,18 @@
description: "Collect sepolicy hash from sysfs"
bug: "308471499"
}
+
+flag {
+ name: "frp_enforcement"
+ namespace: "hardware_backed_security"
+ description: "This flag controls whether PDB enforces FRP"
+ bug: "290312729"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "report_primary_auth_attempts"
+ namespace: "biometrics"
+ description: "Report primary auth attempts from LockSettingsService"
+ bug: "285053096"
+}
diff --git a/core/java/android/security/responsible_apis_flags.aconfig b/core/java/android/security/responsible_apis_flags.aconfig
new file mode 100644
index 0000000..0bae459
--- /dev/null
+++ b/core/java/android/security/responsible_apis_flags.aconfig
@@ -0,0 +1,43 @@
+package: "android.security"
+
+flag {
+ name: "extend_ecm_to_all_settings"
+ namespace: "responsible_apis"
+ description: "Allow all app settings to be restrictable via configuration"
+ bug: "297372999"
+}
+
+flag {
+ name: "asm_restrictions_enabled"
+ namespace: "responsible_apis"
+ description: "Enables ASM restrictions for activity starts and finishes"
+ bug: "230590090"
+}
+
+flag {
+ name: "asm_toasts_enabled"
+ namespace: "responsible_apis"
+ description: "Enables toasts when ASM restrictions are triggered"
+ bug: "230590090"
+}
+
+flag {
+ name: "content_uri_permission_apis"
+ namespace: "responsible_apis"
+ description: "Enables the content URI permission APIs"
+ bug: "293467489"
+}
+
+flag {
+ name: "enforce_intent_filter_match"
+ namespace: "responsible_apis"
+ description: "Make delivered intents match components' intent filters"
+ bug: "293560872"
+}
+
+flag {
+ name: "block_null_action_intents"
+ namespace: "responsible_apis"
+ description: "Do not allow intents without an action to match any intent filters"
+ bug: "293560872"
+}
diff --git a/core/java/android/service/contextualsearch/OWNERS b/core/java/android/service/contextualsearch/OWNERS
new file mode 100644
index 0000000..463adf4
--- /dev/null
+++ b/core/java/android/service/contextualsearch/OWNERS
@@ -0,0 +1,3 @@
+srazdan@google.com
+volnov@google.com
+hackz@google.com
diff --git a/core/java/android/service/ondeviceintelligence/OWNERS b/core/java/android/service/ondeviceintelligence/OWNERS
new file mode 100644
index 0000000..09774f7
--- /dev/null
+++ b/core/java/android/service/ondeviceintelligence/OWNERS
@@ -0,0 +1 @@
+file:/core/java/android/app/ondeviceintelligence/OWNERS
diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS
index ec44100..763c79e 100644
--- a/core/java/android/service/voice/OWNERS
+++ b/core/java/android/service/voice/OWNERS
@@ -4,4 +4,4 @@
# The owner here should not be assist owner
liangyuchen@google.com
-tuanng@google.com
+adudani@google.com
diff --git a/core/java/android/service/wearable/OWNERS b/core/java/android/service/wearable/OWNERS
index 073e2d7..eca48b7 100644
--- a/core/java/android/service/wearable/OWNERS
+++ b/core/java/android/service/wearable/OWNERS
@@ -1,3 +1 @@
-charliewang@google.com
-oni@google.com
-volnov@google.com
\ No newline at end of file
+include /core/java/android/app/wearable/OWNERS
\ No newline at end of file
diff --git a/core/java/android/tracing/OWNERS b/core/java/android/tracing/OWNERS
index 2ebe2e9..f67844d 100644
--- a/core/java/android/tracing/OWNERS
+++ b/core/java/android/tracing/OWNERS
@@ -1,6 +1,4 @@
carmenjackson@google.com
kevinjeon@google.com
-pablogamito@google.com
-natanieljr@google.com
-keanmariotti@google.com
+include platform/development:/tools/winscope/OWNERS
include platform/external/perfetto:/OWNERS
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index a436e08a..2eece6d 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -69,6 +69,7 @@
private final String mName;
private final int mVendorId;
private final int mProductId;
+ private final int mDeviceBus;
private final String mDescriptor;
private final InputDeviceIdentifier mIdentifier;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -468,8 +469,8 @@
* Called by native code
*/
private InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
- int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
- KeyCharacterMap keyCharacterMap, @Nullable String keyboardLanguageTag,
+ int productId, int deviceBus, String descriptor, boolean isExternal, int sources,
+ int keyboardType, KeyCharacterMap keyCharacterMap, @Nullable String keyboardLanguageTag,
@Nullable String keyboardLayoutType, boolean hasVibrator, boolean hasMicrophone,
boolean hasButtonUnderPad, boolean hasSensor, boolean hasBattery, int usiVersionMajor,
int usiVersionMinor, int associatedDisplayId) {
@@ -479,6 +480,7 @@
mName = name;
mVendorId = vendorId;
mProductId = productId;
+ mDeviceBus = deviceBus;
mDescriptor = descriptor;
mIsExternal = isExternal;
mSources = sources;
@@ -512,6 +514,7 @@
mName = in.readString();
mVendorId = in.readInt();
mProductId = in.readInt();
+ mDeviceBus = in.readInt();
mDescriptor = in.readString();
mIsExternal = in.readInt() != 0;
mSources = in.readInt();
@@ -551,6 +554,7 @@
private String mName = "";
private int mVendorId = 0;
private int mProductId = 0;
+ private int mDeviceBus = 0;
private String mDescriptor = "";
private boolean mIsExternal = false;
private int mSources = 0;
@@ -604,6 +608,12 @@
return this;
}
+ /** @see InputDevice#getDeviceBus() */
+ public Builder setDeviceBus(int deviceBus) {
+ mDeviceBus = deviceBus;
+ return this;
+ }
+
/** @see InputDevice#getDescriptor() */
public Builder setDescriptor(String descriptor) {
mDescriptor = descriptor;
@@ -705,6 +715,7 @@
mName,
mVendorId,
mProductId,
+ mDeviceBus,
mDescriptor,
mIsExternal,
mSources,
@@ -846,6 +857,21 @@
}
/**
+ * Gets the device bus used by given device, if available.
+ * <p>
+ * The device bus is the communication system used for transferring data
+ * (e.g. USB, Bluetooth etc.). This value comes from the kernel (from input.h).
+ * A value of 0 will be assigned where the device bus is not available.
+ * </p>
+ *
+ * @return The device bus of a given device
+ * @hide
+ */
+ public int getDeviceBus() {
+ return mDeviceBus;
+ }
+
+ /**
* Gets the input device descriptor, which is a stable identifier for an input device.
* <p>
* An input device descriptor uniquely identifies an input device. Its value
@@ -1444,6 +1470,7 @@
out.writeString(mName);
out.writeInt(mVendorId);
out.writeInt(mProductId);
+ out.writeInt(mDeviceBus);
out.writeString(mDescriptor);
out.writeInt(mIsExternal ? 1 : 0);
out.writeInt(mSources);
diff --git a/core/java/android/view/MotionPredictor.java b/core/java/android/view/MotionPredictor.java
index 27af300..db2efaa 100644
--- a/core/java/android/view/MotionPredictor.java
+++ b/core/java/android/view/MotionPredictor.java
@@ -20,6 +20,8 @@
import android.annotation.Nullable;
import android.content.Context;
+import com.android.internal.annotations.VisibleForTesting;
+
import libcore.util.NativeAllocationRegistry;
/**
@@ -57,11 +59,21 @@
* @param context The context for the predictions
*/
public MotionPredictor(@NonNull Context context) {
- mIsPredictionEnabled = context.getResources().getBoolean(
- com.android.internal.R.bool.config_enableMotionPrediction);
- final int offsetNanos = context.getResources().getInteger(
- com.android.internal.R.integer.config_motionPredictionOffsetNanos);
- mPtr = nativeInitialize(offsetNanos);
+ this(
+ context.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableMotionPrediction),
+ context.getResources().getInteger(
+ com.android.internal.R.integer.config_motionPredictionOffsetNanos));
+ }
+
+ /**
+ * Internal constructor for testing.
+ * @hide
+ */
+ @VisibleForTesting
+ public MotionPredictor(boolean isPredictionEnabled, int motionPredictionOffsetNanos) {
+ mIsPredictionEnabled = isPredictionEnabled;
+ mPtr = nativeInitialize(motionPredictionOffsetNanos);
RegistryHolder.REGISTRY.registerNativeAllocation(this, mPtr);
}
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index ad326e4..a2f767d 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -102,6 +102,7 @@
per-file IWindow*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
per-file RemoteAnimation*.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file RemoteAnimation*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
+per-file ScreenRecordingCallbacks.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file *SurfaceControl*.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file SurfaceControl*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
per-file SurfaceSession.java = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index cd2d36c..72d4cda 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2191,7 +2191,8 @@
} else {
mDisplay = preferredDisplay;
}
- if (mHdrSdrRatioChangedListener != null && mDisplay != null) {
+ if (mHdrSdrRatioChangedListener != null && mDisplay != null
+ && mDisplay.isHdrSdrRatioAvailable()) {
mDisplay.registerHdrSdrRatioChangedListener(mExecutor, mHdrSdrRatioChangedListener);
}
mContext.updateDisplay(mDisplay.getDisplayId());
diff --git a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
index 7694754..c9ffdae 100644
--- a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
@@ -49,7 +49,6 @@
import android.view.View;
import android.view.ViewRootImpl;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
import com.android.internal.inputmethod.IRemoteInputConnection;
@@ -60,6 +59,7 @@
import java.lang.ref.WeakReference;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -164,18 +164,15 @@
boolean cancellable();
}
- @GuardedBy("mLock")
- @Nullable
- private InputConnection mInputConnection;
+ @NonNull
+ private final AtomicReference<InputConnection> mInputConnectionRef;
+ @NonNull
+ private final AtomicBoolean mDeactivateRequested = new AtomicBoolean(false);
@NonNull
private final Looper mLooper;
private final Handler mH;
- private final Object mLock = new Object();
- @GuardedBy("mLock")
- private boolean mFinished = false;
-
private final InputMethodManager mParentInputMethodManager;
private final WeakReference<View> mServedView;
@@ -193,7 +190,7 @@
RemoteInputConnectionImpl(@NonNull Looper looper,
@NonNull InputConnection inputConnection,
@NonNull InputMethodManager inputMethodManager, @Nullable View servedView) {
- mInputConnection = inputConnection;
+ mInputConnectionRef = new AtomicReference<>(inputConnection);
mLooper = looper;
mH = new Handler(mLooper);
mParentInputMethodManager = inputMethodManager;
@@ -211,9 +208,7 @@
*/
@Nullable
public InputConnection getInputConnection() {
- synchronized (mLock) {
- return mInputConnection;
- }
+ return mInputConnectionRef.get();
}
/**
@@ -229,13 +224,7 @@
* {@link InputConnection#closeConnection()} as a result of {@link #deactivate()}.
*/
private boolean isFinished() {
- synchronized (mLock) {
- return mFinished;
- }
- }
-
- private boolean isActive() {
- return mParentInputMethodManager.isActive() && !isFinished();
+ return mInputConnectionRef.get() == null;
}
private View getServedView() {
@@ -372,28 +361,18 @@
*/
@Dispatching(cancellable = false)
public void deactivate() {
- if (isFinished()) {
+ if (mDeactivateRequested.getAndSet(true)) {
// This is a small performance optimization. Still only the 1st call of
- // reportFinish() will take effect.
+ // deactivate() will take effect.
return;
}
dispatch(() -> {
// Deactivate the notifier when finishing typing.
notifyTypingHint(false /* isTyping */, true /* deactivate */);
- // Note that we do not need to worry about race condition here, because 1) mFinished is
- // updated only inside this block, and 2) the code here is running on a Handler hence we
- // assume multiple closeConnection() tasks will not be handled at the same time.
- if (isFinished()) {
- return;
- }
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#closeConnection");
try {
InputConnection ic = getInputConnection();
- // Note we do NOT check isActive() here, because this is safe
- // for an IME to call at any time, and we need to allow it
- // through to clean up our state after the IME has switched to
- // another client.
if (ic == null) {
return;
}
@@ -403,10 +382,7 @@
// TODO(b/199934664): See if we can remove this by providing a default impl.
}
} finally {
- synchronized (mLock) {
- mInputConnection = null;
- mFinished = true;
- }
+ mInputConnectionRef.set(null);
Trace.traceEnd(Trace.TRACE_TAG_INPUT);
}
@@ -460,8 +436,7 @@
public String toString() {
return "RemoteInputConnectionImpl{"
+ "connection=" + getInputConnection()
- + " finished=" + isFinished()
- + " mParentInputMethodManager.isActive()=" + mParentInputMethodManager.isActive()
+ + " mDeactivateRequested=" + mDeactivateRequested.get()
+ " mServedView=" + mServedView.get()
+ "}";
}
@@ -474,16 +449,14 @@
* {@link DumpableInputConnection#dumpDebug(ProtoOutputStream, long)}.
*/
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
- synchronized (mLock) {
- // Check that the call is initiated in the target thread of the current InputConnection
- // {@link InputConnection#getHandler} since the messages to IInputConnectionWrapper are
- // executed on this thread. Otherwise the messages are dispatched to the correct thread
- // in IInputConnectionWrapper, but this is not wanted while dumpng, for performance
- // reasons.
- if ((mInputConnection instanceof DumpableInputConnection)
- && mLooper.isCurrentThread()) {
- ((DumpableInputConnection) mInputConnection).dumpDebug(proto, fieldId);
- }
+ final InputConnection ic = mInputConnectionRef.get();
+ // Check that the call is initiated in the target thread of the current InputConnection
+ // {@link InputConnection#getHandler} since the messages to IInputConnectionWrapper are
+ // executed on this thread. Otherwise the messages are dispatched to the correct thread
+ // in IInputConnectionWrapper, but this is not wanted while dumping, for performance
+ // reasons.
+ if ((ic instanceof DumpableInputConnection) && mLooper.isCurrentThread()) {
+ ((DumpableInputConnection) ic).dumpDebug(proto, fieldId);
}
}
@@ -498,7 +471,7 @@
public void dispatchReportFullscreenMode(boolean enabled) {
dispatch(() -> {
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
return;
}
ic.reportFullscreenMode(enabled);
@@ -514,7 +487,7 @@
return null; // cancelled
}
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
return null;
}
@@ -536,7 +509,7 @@
return null; // cancelled
}
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
return null;
}
@@ -558,7 +531,7 @@
return null; // cancelled
}
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "getSelectedText on inactive InputConnection");
return null;
}
@@ -580,7 +553,7 @@
return null; // cancelled
}
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "getSurroundingText on inactive InputConnection");
return null;
}
@@ -608,7 +581,7 @@
return 0; // cancelled
}
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
return 0;
}
@@ -625,7 +598,7 @@
return null; // cancelled
}
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "getExtractedText on inactive InputConnection");
return null;
}
@@ -642,7 +615,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "commitText on inactive InputConnection");
return;
}
@@ -660,7 +633,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "commitText on inactive InputConnection");
return;
}
@@ -676,7 +649,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "commitCompletion on inactive InputConnection");
return;
}
@@ -692,7 +665,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "commitCorrection on inactive InputConnection");
return;
}
@@ -712,7 +685,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "setSelection on inactive InputConnection");
return;
}
@@ -728,7 +701,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "performEditorAction on inactive InputConnection");
return;
}
@@ -744,7 +717,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "performContextMenuAction on inactive InputConnection");
return;
}
@@ -760,7 +733,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "setComposingRegion on inactive InputConnection");
return;
}
@@ -781,7 +754,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "setComposingRegion on inactive InputConnection");
return;
}
@@ -798,7 +771,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "setComposingText on inactive InputConnection");
return;
}
@@ -816,7 +789,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "setComposingText on inactive InputConnection");
return;
}
@@ -845,11 +818,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- // Note we do NOT check isActive() here, because this is safe
- // for an IME to call at any time, and we need to allow it
- // through to clean up our state after the IME has switched to
- // another client.
- if (ic == null) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "finishComposingTextFromImm on inactive InputConnection");
return;
}
@@ -873,11 +842,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- // Note we do NOT check isActive() here, because this is safe
- // for an IME to call at any time, and we need to allow it
- // through to clean up our state after the IME has switched to
- // another client.
- if (ic == null) {
+ if (ic == null && mDeactivateRequested.get()) {
Log.w(TAG, "finishComposingText on inactive InputConnection");
return;
}
@@ -893,7 +858,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "sendKeyEvent on inactive InputConnection");
return;
}
@@ -909,7 +874,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
return;
}
@@ -926,7 +891,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
return;
}
@@ -944,7 +909,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection");
return;
}
@@ -964,7 +929,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "beginBatchEdit on inactive InputConnection");
return;
}
@@ -980,7 +945,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "endBatchEdit on inactive InputConnection");
return;
}
@@ -996,7 +961,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "performSpellCheck on inactive InputConnection");
return;
}
@@ -1013,7 +978,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "performPrivateCommand on inactive InputConnection");
return;
}
@@ -1051,7 +1016,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "performHandwritingGesture on inactive InputConnection");
if (resultReceiver != null) {
resultReceiver.send(
@@ -1091,7 +1056,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "previewHandwritingGesture on inactive InputConnection");
return; // cancelled
}
@@ -1139,7 +1104,7 @@
@InputConnection.CursorUpdateMode int cursorUpdateMode,
@InputConnection.CursorUpdateFilter int cursorUpdateFilter, int imeDisplayId) {
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "requestCursorUpdates on inactive InputConnection");
return false;
}
@@ -1177,7 +1142,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "requestTextBoundsInfo on inactive InputConnection");
resultReceiver.send(TextBoundsInfoResult.CODE_CANCELLED, null);
return;
@@ -1221,7 +1186,7 @@
return false; // cancelled
}
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "commitContent on inactive InputConnection");
return false;
}
@@ -1246,7 +1211,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "setImeConsumesInput on inactive InputConnection");
return;
}
@@ -1270,7 +1235,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "replaceText on inactive InputConnection");
return;
}
@@ -1289,7 +1254,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "commitText on inactive InputConnection");
return;
}
@@ -1309,7 +1274,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "setSelection on inactive InputConnection");
return;
}
@@ -1326,7 +1291,7 @@
return null; // cancelled
}
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "getSurroundingText on inactive InputConnection");
return null;
}
@@ -1354,7 +1319,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
return;
}
@@ -1370,7 +1335,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "sendKeyEvent on inactive InputConnection");
return;
}
@@ -1386,7 +1351,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "performEditorAction on inactive InputConnection");
return;
}
@@ -1402,7 +1367,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "performContextMenuAction on inactive InputConnection");
return;
}
@@ -1419,7 +1384,7 @@
return 0; // cancelled
}
final InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
return 0;
}
@@ -1435,7 +1400,7 @@
return; // cancelled
}
InputConnection ic = getInputConnection();
- if (ic == null || !isActive()) {
+ if (ic == null || mDeactivateRequested.get()) {
Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
return;
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 6ad1960..2bc584a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -423,12 +423,12 @@
int mMotionViewNewTop;
/**
- * The X value associated with the the down motion event
+ * The X value associated with the down motion event
*/
int mMotionX;
/**
- * The Y value associated with the the down motion event
+ * The Y value associated with the down motion event
*/
@UnsupportedAppUsage
int mMotionY;
@@ -7346,7 +7346,7 @@
scrap.dispatchStartTemporaryDetach();
- // The the accessibility state of the view may change while temporary
+ // the accessibility state of the view may change while temporary
// detached and we do not allow detached views to fire accessibility
// events. So we are announcing that the subtree changed giving a chance
// to clients holding on to a view in this subtree to refresh it.
@@ -7715,7 +7715,7 @@
}
/**
- * Abstract positon scroller used to handle smooth scrolling.
+ * Abstract position scroller used to handle smooth scrolling.
*/
static abstract class AbsPositionScroller {
public abstract void start(int position);
diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
index 76e97ad..3b7e1e9 100644
--- a/core/java/android/widget/AbsSpinner.java
+++ b/core/java/android/widget/AbsSpinner.java
@@ -170,7 +170,7 @@
* @see android.view.View#measure(int, int)
*
* Figure out the dimensions of this Spinner. The width comes from
- * the widthMeasureSpec as Spinnners can't have their width set to
+ * the widthMeasureSpec as Spinners can't have their width set to
* UNSPECIFIED. The height is based on the height of the selected item
* plus padding.
*/
diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS
index e20357fa..1dc90ed 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -15,3 +15,5 @@
per-file Remote* = file:../appwidget/OWNERS
per-file Toast.java = juliacr@google.com, jeffdq@google.com
+
+per-file flags/notification_widget_flags.aconfig = juliacr@google.com, jeffdq@google.com
diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java
index bdaad2b..473b814 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -47,6 +47,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
+import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -337,7 +338,14 @@
"SplashScreenView");
ImageView imageView = new ImageView(viewContext);
imageView.setBackground(mIconDrawable);
- viewHost.setView(imageView, mIconSize, mIconSize);
+ final int windowFlag = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ final WindowManager.LayoutParams lp =
+ new WindowManager.LayoutParams(mIconSize, mIconSize,
+ WindowManager.LayoutParams.TYPE_APPLICATION, windowFlag,
+ PixelFormat.TRANSPARENT);
+ viewHost.setView(imageView, lp);
SurfaceControlViewHost.SurfacePackage surfacePackage = viewHost.getSurfacePackage();
surfaceView.setChildSurfacePackage(surfacePackage);
view.mSurfacePackage = surfacePackage;
diff --git a/core/java/android/window/flags/OWNERS b/core/java/android/window/flags/OWNERS
index fa81ee3..fd73d35 100644
--- a/core/java/android/window/flags/OWNERS
+++ b/core/java/android/window/flags/OWNERS
@@ -1 +1,3 @@
-per-file responsible_apis.aconfig = file:/BAL_OWNERS
\ No newline at end of file
+per-file responsible_apis.aconfig = file:/BAL_OWNERS
+per-file large_screen_experiences_app_compat.aconfig = file:/LSE_APP_COMPAT_OWNERS
+per-file accessibility.aconfig = file:/core/java/android/view/accessibility/OWNERS
diff --git a/core/java/com/android/internal/colorextraction/OWNERS b/core/java/com/android/internal/colorextraction/OWNERS
index ffade1e..041559c 100644
--- a/core/java/com/android/internal/colorextraction/OWNERS
+++ b/core/java/com/android/internal/colorextraction/OWNERS
@@ -1,3 +1,2 @@
-dupin@google.com
cinek@google.com
-jamesoleary@google.com
+arteiro@google.com
diff --git a/core/java/com/android/internal/protolog/OWNERS b/core/java/com/android/internal/protolog/OWNERS
new file mode 100644
index 0000000..18cf2be
--- /dev/null
+++ b/core/java/com/android/internal/protolog/OWNERS
@@ -0,0 +1,3 @@
+# ProtoLog owners
+# Bug component: 1157642
+include platform/development:/tools/winscope/OWNERS
diff --git a/core/java/com/android/internal/util/RingBuffer.java b/core/java/com/android/internal/util/RingBuffer.java
index 8fc4c30..7f8c8a1 100644
--- a/core/java/com/android/internal/util/RingBuffer.java
+++ b/core/java/com/android/internal/util/RingBuffer.java
@@ -19,7 +19,10 @@
import static com.android.internal.util.Preconditions.checkArgumentPositive;
import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
+import java.util.function.IntFunction;
+import java.util.function.Supplier;
/**
* A simple ring buffer structure with bounded capacity backed by an array.
@@ -29,16 +32,35 @@
*/
public class RingBuffer<T> {
+ private final Supplier<T> mNewItem;
// Array for storing events.
private final T[] mBuffer;
// Cursor keeping track of the logical end of the array. This cursor never
// wraps and instead keeps track of the total number of append() operations.
private long mCursor = 0;
+ /**
+ * @deprecated This uses reflection to create new instances.
+ * Use {@link #RingBuffer(Supplier, IntFunction, int)}} instead.
+ */
+ @Deprecated
public RingBuffer(Class<T> c, int capacity) {
+ this(() -> (T) createNewItem(c), cap -> (T[]) Array.newInstance(c, cap), capacity);
+ }
+
+ private static Object createNewItem(Class c) {
+ try {
+ return c.getDeclaredConstructor().newInstance();
+ } catch (IllegalAccessException | InstantiationException | NoSuchMethodException
+ | InvocationTargetException e) {
+ return null;
+ }
+ }
+
+ public RingBuffer(Supplier<T> newItem, IntFunction<T[]> newBacking, int capacity) {
checkArgumentPositive(capacity, "A RingBuffer cannot have 0 capacity");
- // Java cannot create generic arrays without a runtime hint.
- mBuffer = (T[]) Array.newInstance(c, capacity);
+ mBuffer = newBacking.apply(capacity);
+ mNewItem = newItem;
}
public int size() {
@@ -68,22 +90,11 @@
public T getNextSlot() {
final int nextSlotIdx = indexOf(mCursor++);
if (mBuffer[nextSlotIdx] == null) {
- mBuffer[nextSlotIdx] = createNewItem();
+ mBuffer[nextSlotIdx] = mNewItem.get();
}
return mBuffer[nextSlotIdx];
}
- /**
- * @return a new object of type <T> or null if a new object could not be created.
- */
- protected T createNewItem() {
- try {
- return (T) mBuffer.getClass().getComponentType().newInstance();
- } catch (IllegalAccessException | InstantiationException e) {
- return null;
- }
- }
-
public T[] toArray() {
// Only generic way to create a T[] from another T[]
T[] out = Arrays.copyOf(mBuffer, size(), (Class<T[]>) mBuffer.getClass());
diff --git a/core/java/com/android/internal/widget/LockSettingsInternal.java b/core/java/com/android/internal/widget/LockSettingsInternal.java
index 8114e1f..e591327 100644
--- a/core/java/com/android/internal/widget/LockSettingsInternal.java
+++ b/core/java/com/android/internal/widget/LockSettingsInternal.java
@@ -166,4 +166,16 @@
* Refreshes pending strong auth timeout with the latest admin requirement set by device policy.
*/
public abstract void refreshStrongAuthTimeout(int userId);
+
+ /**
+ * Register a LockSettingsStateListener
+ * @param listener The listener to be registered
+ */
+ public abstract void registerLockSettingsStateListener(LockSettingsStateListener listener);
+
+ /**
+ * Unregister a LockSettingsStateListener
+ * @param listener The listener to be unregistered
+ */
+ public abstract void unregisterLockSettingsStateListener(LockSettingsStateListener listener);
}
diff --git a/core/java/com/android/internal/widget/LockSettingsStateListener.java b/core/java/com/android/internal/widget/LockSettingsStateListener.java
new file mode 100644
index 0000000..869e676
--- /dev/null
+++ b/core/java/com/android/internal/widget/LockSettingsStateListener.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+/**
+ * Callback interface between LockSettingService and other system services to be notified about the
+ * state of primary authentication (i.e. PIN/pattern/password).
+ * @hide
+ */
+public interface LockSettingsStateListener {
+ /**
+ * Defines behavior in response to a successful authentication
+ * @param userId The user Id for the requested authentication
+ */
+ void onAuthenticationSucceeded(int userId);
+
+ /**
+ * Defines behavior in response to a failed authentication
+ * @param userId The user Id for the requested authentication
+ */
+ void onAuthenticationFailed(int userId);
+}
diff --git a/core/java/com/android/server/OWNERS b/core/java/com/android/server/OWNERS
deleted file mode 100644
index 1c2d19d..0000000
--- a/core/java/com/android/server/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-per-file SystemConfig.java = file:/PACKAGE_MANAGER_OWNERS
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index f5b12db..c4ff402 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -182,8 +182,6 @@
"android_os_SharedMemory.cpp",
"android_os_storage_StorageManager.cpp",
"android_os_UEventObserver.cpp",
- "android_os_VintfObject.cpp",
- "android_os_VintfRuntimeInfo.cpp",
"android_os_incremental_IncrementalManager.cpp",
"android_net_LocalSocketImpl.cpp",
"android_service_DataLoaderService.cpp",
@@ -271,6 +269,7 @@
"libdmabufinfo",
"libgif",
"libgui_window_info_static",
+ "libkernelconfigs",
"libseccomp_policy",
"libgrallocusage",
"libscrypt_static",
@@ -340,7 +339,6 @@
"libnativeloader_lazy",
"libmemunreachable",
"libhidlbase",
- "libvintf",
"libnativedisplay",
"libnativewindow",
"libdl",
@@ -448,8 +446,25 @@
// (e.g. gDefaultServiceManager)
"libbinder",
"libhidlbase", // libhwbinder is in here
- "libvintf",
],
},
},
}
+
+cc_library_shared {
+ name: "libvintf_jni",
+
+ cpp_std: "gnu++20",
+
+ srcs: [
+ "android_os_VintfObject.cpp",
+ "android_os_VintfRuntimeInfo.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libnativehelper",
+ "libvintf",
+ ],
+}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 4e4c754..a3bc2bb 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -151,8 +151,6 @@
extern int register_android_os_Parcel(JNIEnv* env);
extern int register_android_os_PerformanceHintManager(JNIEnv* env);
extern int register_android_os_SELinux(JNIEnv* env);
-extern int register_android_os_VintfObject(JNIEnv *env);
-extern int register_android_os_VintfRuntimeInfo(JNIEnv *env);
extern int register_android_os_storage_StorageManager(JNIEnv* env);
extern int register_android_os_SystemProperties(JNIEnv *env);
extern int register_android_os_SystemClock(JNIEnv* env);
@@ -652,6 +650,8 @@
sizeof("-Xps-save-resolved-classes-delay-ms:")-1 + PROPERTY_VALUE_MAX];
char profileMinSavePeriodOptsBuf[sizeof("-Xps-min-save-period-ms:")-1 + PROPERTY_VALUE_MAX];
char profileMinFirstSaveOptsBuf[sizeof("-Xps-min-first-save-ms:") - 1 + PROPERTY_VALUE_MAX];
+ char profileInlineCacheThresholdOptsBuf[
+ sizeof("-Xps-inline-cache-threshold:") - 1 + PROPERTY_VALUE_MAX];
char madviseWillNeedFileSizeVdex[
sizeof("-XMadviseWillNeedVdexFileSize:")-1 + PROPERTY_VALUE_MAX];
char madviseWillNeedFileSizeOdex[
@@ -897,6 +897,9 @@
parseRuntimeOption("dalvik.vm.ps-min-first-save-ms", profileMinFirstSaveOptsBuf,
"-Xps-min-first-save-ms:");
+ parseRuntimeOption("dalvik.vm.ps-inline-cache-threshold", profileInlineCacheThresholdOptsBuf,
+ "-Xps-inline-cache-threshold:");
+
property_get("ro.config.low_ram", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
addOption("-XX:LowMemoryMode");
@@ -1536,8 +1539,6 @@
REG_JNI(register_android_os_NativeHandle),
REG_JNI(register_android_os_ServiceManager),
REG_JNI(register_android_os_storage_StorageManager),
- REG_JNI(register_android_os_VintfObject),
- REG_JNI(register_android_os_VintfRuntimeInfo),
REG_JNI(register_android_service_DataLoaderService),
REG_JNI(register_android_view_DisplayEventReceiver),
REG_JNI(register_android_view_Surface),
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 2f29cae..917d283 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
diff --git a/core/jni/android_opengl_EGL15.cpp b/core/jni/android_opengl_EGL15.cpp
index b9c36b9..447b8ec 100644
--- a/core/jni/android_opengl_EGL15.cpp
+++ b/core/jni/android_opengl_EGL15.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
diff --git a/core/jni/android_opengl_EGLExt.cpp b/core/jni/android_opengl_EGLExt.cpp
index cdc9852..ffd75ea 100644
--- a/core/jni/android_opengl_EGLExt.cpp
+++ b/core/jni/android_opengl_EGLExt.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
@@ -54,11 +55,11 @@
jclass eglsurfaceClassLocal = _env->FindClass("android/opengl/EGLSurface");
eglsurfaceClass = (jclass) _env->NewGlobalRef(eglsurfaceClassLocal);
jclass eglsyncClassLocal = _env->FindClass("android/opengl/EGLSync");
- eglsyncClass = (jclass)_env->NewGlobalRef(eglsyncClassLocal);
+ eglsyncClass = (jclass) _env->NewGlobalRef(eglsyncClassLocal);
egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
- eglsyncGetHandleID = _env->GetMethodID(eglsyncClassLocal, "getNativeHandle", "()J");
+ eglsyncGetHandleID = _env->GetMethodID(eglsyncClass, "getNativeHandle", "()J");
}
static void *
@@ -72,6 +73,14 @@
return reinterpret_cast<void*>(_env->CallLongMethod(obj, mid));
}
+// TODO: this should be generated from the .spec file, but needs to be renamed and made private
+static jint android_eglDupNativeFenceFDANDROID(JNIEnv *env, jobject, jobject dpy, jobject sync) {
+ EGLDisplay dpy_native = (EGLDisplay)fromEGLHandle(env, egldisplayGetHandleID, dpy);
+ EGLSync sync_native = (EGLSync)fromEGLHandle(env, eglsyncGetHandleID, sync);
+
+ return eglDupNativeFenceFDANDROID(dpy_native, sync_native);
+}
+
// --------------------------------------------------------------------------
/* EGLBoolean eglPresentationTimeANDROID ( EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time ) */
static jboolean
@@ -89,21 +98,12 @@
return (jboolean)_returnValue;
}
-static jint android_eglDupNativeFenceFDANDROID(JNIEnv *env, jobject, jobject dpy, jobject sync) {
- EGLDisplay dpy_native = (EGLDisplay)fromEGLHandle(env, egldisplayGetHandleID, dpy);
- EGLSync sync_native = (EGLSync)fromEGLHandle(env, eglsyncGetHandleID, sync);
-
- return eglDupNativeFenceFDANDROID(dpy_native, sync_native);
-}
-
static const char *classPathName = "android/opengl/EGLExt";
static const JNINativeMethod methods[] = {
- {"_nativeClassInit", "()V", (void *)nativeClassInit},
- {"eglPresentationTimeANDROID", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;J)Z",
- (void *)android_eglPresentationTimeANDROID},
- {"eglDupNativeFenceFDANDROIDImpl", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSync;)I",
- (void *)android_eglDupNativeFenceFDANDROID},
+{"_nativeClassInit", "()V", (void*)nativeClassInit },
+{"eglPresentationTimeANDROID", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;J)Z", (void *) android_eglPresentationTimeANDROID },
+{"eglDupNativeFenceFDANDROIDImpl", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSync;)I", (void *)android_eglDupNativeFenceFDANDROID },
};
int register_android_opengl_jni_EGLExt(JNIEnv *_env)
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index d65b498..2d921ad 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 3638b87..35a9a68 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 9724e6c..e04b56e 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 1ffa4ec..bccbda6 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index d832558..165262e 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES2/gl2.h>
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 719c6b3..d3fe439 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES3/gl3.h>
diff --git a/core/jni/android_opengl_GLES31.cpp b/core/jni/android_opengl_GLES31.cpp
index afe7c63..b123f9d 100644
--- a/core/jni/android_opengl_GLES31.cpp
+++ b/core/jni/android_opengl_GLES31.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <stdint.h>
diff --git a/core/jni/android_opengl_GLES31Ext.cpp b/core/jni/android_opengl_GLES31Ext.cpp
index 8127433..1e4049b 100644
--- a/core/jni/android_opengl_GLES31Ext.cpp
+++ b/core/jni/android_opengl_GLES31Ext.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES3/gl31.h>
diff --git a/core/jni/android_opengl_GLES32.cpp b/core/jni/android_opengl_GLES32.cpp
index 7ed7548..e0175f0 100644
--- a/core/jni/android_opengl_GLES32.cpp
+++ b/core/jni/android_opengl_GLES32.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <stdint.h>
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index fe95762..e4b0f1a 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -52,7 +52,7 @@
#include <memunreachable/memunreachable.h>
#include <android-base/strings.h>
#include "android_os_Debug.h"
-#include <vintf/VintfObject.h>
+#include <vintf/KernelConfigs.h>
namespace android
{
@@ -959,10 +959,9 @@
} cfg_state = CONFIG_UNKNOWN;
if (cfg_state == CONFIG_UNKNOWN) {
- auto runtime_info = vintf::VintfObject::GetInstance()->getRuntimeInfo(
- vintf::RuntimeInfo::FetchFlag::CONFIG_GZ);
- CHECK(runtime_info != nullptr) << "Kernel configs cannot be fetched. b/151092221";
- const std::map<std::string, std::string>& configs = runtime_info->kernelConfigs();
+ std::map<std::string, std::string> configs;
+ const status_t result = android::kernelconfigs::LoadKernelConfigs(&configs);
+ CHECK(result == OK) << "Kernel configs could not be fetched. b/151092221";
std::map<std::string, std::string>::const_iterator it = configs.find("CONFIG_VMAP_STACK");
cfg_state = (it != configs.end() && it->second == "y") ? CONFIG_SET : CONFIG_UNSET;
}
diff --git a/core/jni/android_os_HidlSupport.cpp b/core/jni/android_os_HidlSupport.cpp
index e3602d8..3e51e93 100644
--- a/core/jni/android_os_HidlSupport.cpp
+++ b/core/jni/android_os_HidlSupport.cpp
@@ -15,6 +15,7 @@
*/
#include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
#include <nativehelper/JNIHelp.h>
#include "core_jni_helpers.h"
@@ -24,8 +25,13 @@
return android::hardware::details::getPidIfSharable();
}
+static jboolean android_os_HidlSupport_isHidlSupported(JNIEnv*, jclass) {
+ return android::hardware::isHidlSupported();
+}
+
static const JNINativeMethod gHidlSupportMethods[] = {
- {"getPidIfSharable", "()I", (void*)android_os_HidlSupport_getPidIfSharable},
+ {"getPidIfSharable", "()I", (void*)android_os_HidlSupport_getPidIfSharable},
+ {"isHidlSupported", "()Z", (void*)android_os_HidlSupport_isHidlSupported},
};
const char* const kHidlSupportPathName = "android/os/HidlSupport";
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 781895e..734b5f4 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -39,7 +39,6 @@
#include <hwbinder/ProcessState.h>
#include <nativehelper/ScopedLocalRef.h>
#include <nativehelper/ScopedUtfChars.h>
-#include <vintf/parse_string.h>
#include <utils/misc.h>
#include "core_jni_helpers.h"
@@ -258,14 +257,59 @@
JHwBinder::SetNativeContext(env, thiz, context);
}
-static void JHwBinder_native_transact(
- JNIEnv * /* env */,
- jobject /* thiz */,
- jint /* code */,
- jobject /* requestObj */,
- jobject /* replyObj */,
- jint /* flags */) {
- CHECK(!"Should not be here");
+static void JHwBinder_native_transact(JNIEnv *env, jobject thiz, jint code, jobject requestObj,
+ jobject replyObj, jint flags) {
+ if (requestObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+ sp<hardware::IBinder> binder = JHwBinder::GetNativeBinder(env, thiz);
+ sp<android::hidl::base::V1_0::IBase> base = new android::hidl::base::V1_0::BpHwBase(binder);
+ hidl_string desc;
+ auto ret = base->interfaceDescriptor(
+ [&desc](const hidl_string &descriptor) { desc = descriptor; });
+ ret.assertOk();
+ // Only the fake hwservicemanager is allowed to be used locally like this.
+ if (desc != "android.hidl.manager@1.2::IServiceManager" &&
+ desc != "android.hidl.manager@1.1::IServiceManager" &&
+ desc != "android.hidl.manager@1.0::IServiceManager") {
+ LOG(FATAL) << "Local binders are not supported!";
+ }
+ if (replyObj == nullptr) {
+ LOG(FATAL) << "Unexpected null replyObj. code: " << code;
+ return;
+ }
+ const hardware::Parcel *request = JHwParcel::GetNativeContext(env, requestObj)->getParcel();
+ sp<JHwParcel> replyContext = JHwParcel::GetNativeContext(env, replyObj);
+ hardware::Parcel *reply = replyContext->getParcel();
+
+ request->setDataPosition(0);
+
+ bool isOneway = (flags & IBinder::FLAG_ONEWAY) != 0;
+ if (!isOneway) {
+ replyContext->setTransactCallback([](auto &replyParcel) {});
+ }
+
+ env->CallVoidMethod(thiz, gFields.onTransactID, code, requestObj, replyObj, flags);
+
+ if (env->ExceptionCheck()) {
+ jthrowable excep = env->ExceptionOccurred();
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+
+ binder_report_exception(env, excep, "Uncaught error or exception in hwbinder!");
+
+ env->DeleteLocalRef(excep);
+ }
+
+ if (!isOneway) {
+ if (!replyContext->wasSent()) {
+ // The implementation never finished the transaction.
+ LOG(ERROR) << "The reply failed to send!";
+ }
+ }
+
+ reply->setDataPosition(0);
}
static void JHwBinder_native_registerService(
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index 1baea2a..8dc9d0a 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -17,16 +17,14 @@
#define LOG_TAG "VintfObject"
//#define LOG_NDEBUG 0
#include <android-base/logging.h>
-
-#include <vector>
-#include <string>
-
-#include <nativehelper/JNIHelp.h>
#include <vintf/VintfObject.h>
#include <vintf/parse_string.h>
#include <vintf/parse_xml.h>
-#include "core_jni_helpers.h"
+#include <vector>
+#include <string>
+
+#include "jni_wrappers.h"
static jclass gString;
static jclass gHashMapClazz;
@@ -41,11 +39,13 @@
using vintf::HalManifest;
using vintf::Level;
using vintf::SchemaType;
+using vintf::SepolicyVersion;
using vintf::to_string;
using vintf::toXml;
using vintf::Version;
using vintf::VintfObject;
using vintf::Vndk;
+using vintf::CheckFlags::ENABLE_ALL_CHECKS;
template<typename V>
static inline jobjectArray toJavaStringArray(JNIEnv* env, const V& v) {
@@ -93,12 +93,16 @@
return toJavaStringArray(env, cStrings);
}
-static jint android_os_VintfObject_verifyWithoutAvb(JNIEnv* env, jclass) {
+static jint android_os_VintfObject_verifyBuildAtBoot(JNIEnv*, jclass) {
std::string error;
- int32_t status = VintfObject::GetInstance()->checkCompatibility(&error,
- ::android::vintf::CheckFlags::DISABLE_AVB_CHECK);
+ // Use temporary VintfObject, not the shared instance, to release memory
+ // after check.
+ int32_t status =
+ VintfObject::Builder()
+ .build()
+ ->checkCompatibility(&error, ENABLE_ALL_CHECKS.disableAvb().disableKernel());
if (status)
- LOG(WARNING) << "VintfObject.verifyWithoutAvb() returns " << status << ": " << error;
+ LOG(WARNING) << "VintfObject.verifyBuildAtBoot() returns " << status << ": " << error;
return status;
}
@@ -136,7 +140,7 @@
return nullptr;
}
- Version latest;
+ SepolicyVersion latest;
for (const auto& range : versions) {
latest = std::max(latest, range.maxVer());
}
@@ -170,7 +174,7 @@
static const JNINativeMethod gVintfObjectMethods[] = {
{"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report},
- {"verifyWithoutAvb", "()I", (void*)android_os_VintfObject_verifyWithoutAvb},
+ {"verifyBuildAtBoot", "()I", (void*)android_os_VintfObject_verifyBuildAtBoot},
{"getHalNamesAndVersions", "()[Ljava/lang/String;",
(void*)android_os_VintfObject_getHalNamesAndVersions},
{"getSepolicyVersion", "()Ljava/lang/String;",
@@ -199,4 +203,23 @@
NELEM(gVintfObjectMethods));
}
-};
+extern int register_android_os_VintfRuntimeInfo(JNIEnv* env);
+
+} // namespace android
+
+jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
+ JNIEnv* env = NULL;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)) {
+ return JNI_ERR;
+ }
+
+ if (android::register_android_os_VintfObject(env) < 0) {
+ return JNI_ERR;
+ }
+
+ if (android::register_android_os_VintfRuntimeInfo(env) < 0) {
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_1_6;
+}
diff --git a/core/jni/android_os_VintfRuntimeInfo.cpp b/core/jni/android_os_VintfRuntimeInfo.cpp
index b0271b9..7c2f588 100644
--- a/core/jni/android_os_VintfRuntimeInfo.cpp
+++ b/core/jni/android_os_VintfRuntimeInfo.cpp
@@ -17,23 +17,22 @@
#define LOG_TAG "VintfRuntimeInfo"
//#define LOG_NDEBUG 0
-#include <nativehelper/JNIHelp.h>
#include <vintf/VintfObject.h>
#include <vintf/parse_string.h>
#include <vintf/parse_xml.h>
-#include "core_jni_helpers.h"
+#include "jni_wrappers.h"
namespace android {
using vintf::RuntimeInfo;
using vintf::VintfObject;
-#define MAP_STRING_METHOD(javaMethod, cppString, flags) \
- static jstring android_os_VintfRuntimeInfo_##javaMethod(JNIEnv* env, jclass clazz) { \
- std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(flags); \
- if (info == nullptr) return nullptr; \
- return env->NewStringUTF((cppString).c_str()); \
+#define MAP_STRING_METHOD(javaMethod, cppString, flags) \
+ static jstring android_os_VintfRuntimeInfo_##javaMethod(JNIEnv* env, jclass) { \
+ std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(flags); \
+ if (info == nullptr) return nullptr; \
+ return env->NewStringUTF((cppString).c_str()); \
}
MAP_STRING_METHOD(getCpuInfo, info->cpuInfo(), RuntimeInfo::FetchFlag::CPU_INFO);
@@ -49,9 +48,7 @@
MAP_STRING_METHOD(getBootVbmetaAvbVersion, vintf::to_string(info->bootVbmetaAvbVersion()),
RuntimeInfo::FetchFlag::AVB);
-
-static jlong android_os_VintfRuntimeInfo_getKernelSepolicyVersion(JNIEnv *env, jclass clazz)
-{
+static jlong android_os_VintfRuntimeInfo_getKernelSepolicyVersion(JNIEnv*, jclass) {
std::shared_ptr<const RuntimeInfo> info =
VintfObject::GetRuntimeInfo(RuntimeInfo::FetchFlag::POLICYVERS);
if (info == nullptr) return 0;
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 91dfc60..d2e58bb 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -28,6 +28,7 @@
#include <meminfo/sysmeminfo.h>
#include <processgroup/processgroup.h>
#include <processgroup/sched_policy.h>
+#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <algorithm>
@@ -232,6 +233,31 @@
}
}
+// Look up the user ID of a process in /proc/${pid}/status. The Uid: line is present in
+// /proc/${pid}/status since at least kernel v2.5.
+static int uid_from_pid(int pid)
+{
+ int uid = -1;
+ std::array<char, 64> path;
+ int res = snprintf(path.data(), path.size(), "/proc/%d/status", pid);
+ if (res < 0 || res >= static_cast<int>(path.size())) {
+ DCHECK(false);
+ return uid;
+ }
+ FILE* f = fopen(path.data(), "r");
+ if (!f) {
+ return uid;
+ }
+ char line[256];
+ while (fgets(line, sizeof(line), f)) {
+ if (sscanf(line, "Uid: %d", &uid) == 1) {
+ break;
+ }
+ }
+ fclose(f);
+ return uid;
+}
+
void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
{
ALOGV("%s pid=%d grp=%" PRId32, __func__, pid, grp);
@@ -275,13 +301,23 @@
}
}
- if (!SetProcessProfilesCached(0, pid, {get_cpuset_policy_profile_name((SchedPolicy)grp)}))
+ const int uid = uid_from_pid(pid);
+ if (uid < 0) {
+ signalExceptionForGroupError(env, ESRCH, pid);
+ return;
+ }
+ if (!SetProcessProfilesCached(uid, pid, {get_cpuset_policy_profile_name((SchedPolicy)grp)}))
signalExceptionForGroupError(env, errno ? errno : EPERM, pid);
}
void android_os_Process_setProcessFrozen(
JNIEnv *env, jobject clazz, jint pid, jint uid, jboolean freeze)
{
+ if (uid < 0) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "uid is negative: %d", uid);
+ return;
+ }
+
bool success = true;
if (freeze) {
@@ -305,6 +341,11 @@
}
jint android_os_Process_createProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid) {
+ if (uid < 0) {
+ return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "uid is negative: %d", uid);
+ }
+
return createProcessGroup(uid, pid);
}
@@ -590,12 +631,21 @@
jint android_os_Process_setUid(JNIEnv* env, jobject clazz, jint uid)
{
+ if (uid < 0) {
+ return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "uid is negative: %d", uid);
+ }
+
return setuid(uid) == 0 ? 0 : errno;
}
-jint android_os_Process_setGid(JNIEnv* env, jobject clazz, jint uid)
-{
- return setgid(uid) == 0 ? 0 : errno;
+jint android_os_Process_setGid(JNIEnv* env, jobject clazz, jint gid) {
+ if (gid < 0) {
+ return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "gid is negative: %d", gid);
+ }
+
+ return setgid(gid) == 0 ? 0 : errno;
}
static int pid_compare(const void* v1, const void* v2)
@@ -1115,12 +1165,11 @@
static jlongArray android_os_Process_getRss(JNIEnv* env, jobject clazz, jint pid)
{
- // total, file, anon, swap
- jlong rss[4] = {0, 0, 0, 0};
+ // total, file, anon, swap, shmem
+ jlong rss[5] = {0, 0, 0, 0, 0};
std::string status_path =
android::base::StringPrintf("/proc/%d/status", pid);
UniqueFile file = MakeUniqueFile(status_path.c_str(), "re");
-
char line[256];
while (file != nullptr && fgets(line, sizeof(line), file.get())) {
jlong v;
@@ -1132,17 +1181,18 @@
rss[2] = v;
} else if ( sscanf(line, "VmSwap: %" SCNd64 " kB", &v) == 1) {
rss[3] = v;
+ } else if ( sscanf(line, "RssShmem: %" SCNd64 " kB", &v) == 1) {
+ rss[4] = v;
}
}
- jlongArray rssArray = env->NewLongArray(4);
+ jlongArray rssArray = env->NewLongArray(5);
if (rssArray == NULL) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
return NULL;
}
- env->SetLongArrayRegion(rssArray, 0, 4, rss);
-
+ env->SetLongArrayRegion(rssArray, 0, 5, rss);
return rssArray;
}
@@ -1235,11 +1285,21 @@
jint android_os_Process_killProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid)
{
+ if (uid < 0) {
+ return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "uid is negative: %d", uid);
+ }
+
return killProcessGroup(uid, pid, SIGKILL);
}
-jint android_os_Process_sendSignalToProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid,
+jboolean android_os_Process_sendSignalToProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid,
jint signal) {
+ if (uid < 0) {
+ return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "uid is negative: %d", uid);
+ }
+
return sendSignalToProcessGroup(uid, pid, signal);
}
@@ -1258,6 +1318,11 @@
}
void android_os_Process_freezeCgroupUID(JNIEnv* env, jobject clazz, jint uid, jboolean freeze) {
+ if (uid < 0) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "uid is negative: %d", uid);
+ return;
+ }
+
bool success = true;
if (freeze) {
@@ -1310,7 +1375,7 @@
//{"setApplicationObject", "(Landroid/os/IBinder;)V",
//(void*)android_os_Process_setApplicationObject},
{"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup},
- {"sendSignalToProcessGroup", "(III)I", (void*)android_os_Process_sendSignalToProcessGroup},
+ {"sendSignalToProcessGroup", "(III)Z", (void*)android_os_Process_sendSignalToProcessGroup},
{"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups},
{"nativePidFdOpen", "(II)I", (void*)android_os_Process_nativePidFdOpen},
{"freezeCgroupUid", "(IZ)V", (void*)android_os_Process_freezeCgroupUID},
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index f97d41b..baea3bc 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -83,7 +83,8 @@
deviceInfo.getId(), deviceInfo.getGeneration(),
deviceInfo.getControllerNumber(), nameObj.get(),
static_cast<int32_t>(ident.vendor),
- static_cast<int32_t>(ident.product), descriptorObj.get(),
+ static_cast<int32_t>(ident.product),
+ static_cast<int32_t>(ident.bus), descriptorObj.get(),
deviceInfo.isExternal(), deviceInfo.getSources(),
deviceInfo.getKeyboardType(), kcmObj.get(),
keyboardLanguageTagObj.get(), keyboardLayoutTypeObj.get(),
@@ -113,7 +114,7 @@
gInputDeviceClassInfo.clazz = MakeGlobalRefOrDie(env, gInputDeviceClassInfo.clazz);
gInputDeviceClassInfo.ctor = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
- "(IIILjava/lang/String;IILjava/lang/"
+ "(IIILjava/lang/String;IIILjava/lang/"
"String;ZIILandroid/view/KeyCharacterMap;Ljava/"
"lang/String;Ljava/lang/String;ZZZZZIII)V");
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 56066b2..cc16494 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -665,8 +665,9 @@
}
}
-static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn) {
+static void DropCapabilitiesBoundingSet(fail_fn_t fail_fn, jlong bounding_capabilities) {
for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {;
+ if ((1LL << i) & bounding_capabilities) continue;
if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0) == -1) {
if (errno == EINVAL) {
ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
@@ -678,6 +679,27 @@
}
}
+static bool MatchGid(JNIEnv* env, jintArray gids, jint gid, jint gid_to_find) {
+ if (gid == gid_to_find) return true;
+
+ if (gids == nullptr) return false;
+
+ jsize gids_num = env->GetArrayLength(gids);
+ ScopedIntArrayRO native_gid_proxy(env, gids);
+
+ if (native_gid_proxy.get() == nullptr) {
+ RuntimeAbort(env, __LINE__, "Bad gids array");
+ }
+
+ for (int gids_index = 0; gids_index < gids_num; ++gids_index) {
+ if (native_gid_proxy[gids_index] == gid_to_find) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void SetInheritable(uint64_t inheritable, fail_fn_t fail_fn) {
__user_cap_header_struct capheader;
memset(&capheader, 0, sizeof(capheader));
@@ -1742,9 +1764,9 @@
// Utility routine to specialize a zygote child process.
static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags,
jobjectArray rlimits, jlong permitted_capabilities,
- jlong effective_capabilities, jint mount_external,
- jstring managed_se_info, jstring managed_nice_name,
- bool is_system_server, bool is_child_zygote,
+ jlong effective_capabilities, jlong bounding_capabilities,
+ jint mount_external, jstring managed_se_info,
+ jstring managed_nice_name, bool is_system_server, bool is_child_zygote,
jstring managed_instruction_set, jstring managed_app_data_dir,
bool is_top_app, jobjectArray pkg_data_info_list,
jobjectArray allowlisted_data_info_list, bool mount_data_dirs,
@@ -1758,6 +1780,9 @@
auto instruction_set = extract_fn(managed_instruction_set);
auto app_data_dir = extract_fn(managed_app_data_dir);
+ // Permit bounding capabilities
+ permitted_capabilities |= bounding_capabilities;
+
// Keep capabilities across UID change, unless we're staying root.
if (uid != 0) {
EnableKeepCapabilities(fail_fn);
@@ -1765,7 +1790,7 @@
SetInheritable(permitted_capabilities, fail_fn);
- DropCapabilitiesBoundingSet(fail_fn);
+ DropCapabilitiesBoundingSet(fail_fn, bounding_capabilities);
bool need_pre_initialize_native_bridge = !is_system_server && instruction_set.has_value() &&
android::NativeBridgeAvailable() &&
@@ -1803,7 +1828,7 @@
// If this zygote isn't root, it won't be able to create a process group,
// since the directory is owned by root.
- if (!is_system_server && getuid() == 0) {
+ if (getuid() == 0) {
const int rc = createProcessGroup(uid, getpid());
if (rc != 0) {
fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing "
@@ -2028,6 +2053,23 @@
return capdata[0].effective | (static_cast<uint64_t>(capdata[1].effective) << 32);
}
+static jlong CalculateBoundingCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids) {
+ jlong capabilities = 0;
+
+ /*
+ * Grant CAP_SYS_NICE to CapInh/CapPrm/CapBnd for processes that can spawn
+ * VMs. This enables processes to execve on binaries with elevated
+ * capabilities if its file capability bits are set. This does not grant
+ * capability to the parent process(that spawns the VM) as the effective
+ * bits are not set.
+ */
+ if (MatchGid(env, gids, gid, AID_VIRTUALMACHINE)) {
+ capabilities |= (1LL << CAP_SYS_NICE);
+ }
+
+ return capabilities;
+}
+
static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids,
bool is_child_zygote) {
jlong capabilities = 0;
@@ -2050,6 +2092,7 @@
}
if (multiuser_get_app_id(uid) == AID_NETWORK_STACK) {
+ capabilities |= (1LL << CAP_WAKE_ALARM);
capabilities |= (1LL << CAP_NET_ADMIN);
capabilities |= (1LL << CAP_NET_BROADCAST);
capabilities |= (1LL << CAP_NET_BIND_SERVICE);
@@ -2060,26 +2103,7 @@
* Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
*/
- bool gid_wakelock_found = false;
- if (gid == AID_WAKELOCK) {
- gid_wakelock_found = true;
- } else if (gids != nullptr) {
- jsize gids_num = env->GetArrayLength(gids);
- ScopedIntArrayRO native_gid_proxy(env, gids);
-
- if (native_gid_proxy.get() == nullptr) {
- RuntimeAbort(env, __LINE__, "Bad gids array");
- }
-
- for (int gids_index = 0; gids_index < gids_num; ++gids_index) {
- if (native_gid_proxy[gids_index] == AID_WAKELOCK) {
- gid_wakelock_found = true;
- break;
- }
- }
- }
-
- if (gid_wakelock_found) {
+ if (MatchGid(env, gids, gid, AID_WAKELOCK)) {
capabilities |= (1LL << CAP_BLOCK_SUSPEND);
}
@@ -2255,6 +2279,11 @@
const std::vector<int>& fds_to_ignore,
bool is_priority_fork,
bool purge) {
+ ATRACE_CALL();
+ if (is_priority_fork) {
+ setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
+ }
+
SetSignalHandlers();
// Curry a failure function.
@@ -2340,6 +2369,10 @@
// We blocked SIGCHLD prior to a fork, we unblock it here.
UnblockSignal(SIGCHLD, fail_fn);
+ if (is_priority_fork && pid != 0) {
+ setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT);
+ }
+
return pid;
}
@@ -2356,6 +2389,7 @@
jobjectArray pkg_data_info_list, jobjectArray allowlisted_data_info_list,
jboolean mount_data_dirs, jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
+ jlong bounding_capabilities = CalculateBoundingCapabilities(env, uid, gid, gids);
if (UNLIKELY(managed_fds_to_close == nullptr)) {
zygote::ZygoteFailure(env, "zygote", nice_name,
@@ -2394,10 +2428,10 @@
if (pid == 0) {
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities,
- mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE,
- instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list,
- allowlisted_data_info_list, mount_data_dirs == JNI_TRUE,
- mount_storage_dirs == JNI_TRUE);
+ bounding_capabilities, mount_external, se_info, nice_name, false,
+ is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
+ is_top_app == JNI_TRUE, pkg_data_info_list, allowlisted_data_info_list,
+ mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE);
}
return pid;
}
@@ -2407,6 +2441,7 @@
JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
jlong effective_capabilities) {
+ ATRACE_CALL();
std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
fds_to_ignore(fds_to_close);
@@ -2430,7 +2465,7 @@
// System server prcoess does not need data isolation so no need to
// know pkg_data_info_list.
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities,
- effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
+ effective_capabilities, 0, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
false, nullptr, nullptr, /* is_top_app= */ false,
/* pkg_data_info_list */ nullptr,
/* allowlisted_data_info_list */ nullptr, false, false);
@@ -2482,6 +2517,7 @@
jintArray managed_session_socket_fds,
jboolean args_known,
jboolean is_priority_fork) {
+ ATRACE_CALL();
std::vector<int> session_socket_fds =
ExtractJIntArray(env, "USAP", nullptr, managed_session_socket_fds)
.value_or(std::vector<int>());
@@ -2497,6 +2533,7 @@
bool args_known,
bool is_priority_fork,
bool purge) {
+ ATRACE_CALL();
std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
fds_to_ignore(fds_to_close);
@@ -2587,12 +2624,13 @@
jobjectArray allowlisted_data_info_list, jboolean mount_data_dirs,
jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
+ jlong bounding_capabilities = CalculateBoundingCapabilities(env, uid, gid, gids);
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities,
- mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE,
- instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list,
- allowlisted_data_info_list, mount_data_dirs == JNI_TRUE,
- mount_storage_dirs == JNI_TRUE);
+ bounding_capabilities, mount_external, se_info, nice_name, false,
+ is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
+ is_top_app == JNI_TRUE, pkg_data_info_list, allowlisted_data_info_list,
+ mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE);
}
/**
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index 21de723..ef29c88 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
diff --git a/core/jni/core_jni_helpers.h b/core/jni/core_jni_helpers.h
index 210dc89..769fa72 100644
--- a/core/jni/core_jni_helpers.h
+++ b/core/jni/core_jni_helpers.h
@@ -22,6 +22,8 @@
#include <nativehelper/scoped_utf_chars.h>
#include <android_runtime/AndroidRuntime.h>
+#include "jni_wrappers.h"
+
// Host targets (layoutlib) do not differentiate between regular and critical native methods,
// and they need all the JNI methods to have JNIEnv* and jclass/jobject as their first two arguments.
// The following macro allows to have those arguments when compiling for host while omitting them when
@@ -36,60 +38,6 @@
namespace android {
-// Defines some helpful functions.
-
-static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
- jclass clazz = env->FindClass(class_name);
- LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name);
- return clazz;
-}
-
-static inline jfieldID GetFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
- const char* field_signature) {
- jfieldID res = env->GetFieldID(clazz, field_name, field_signature);
- LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find field %s with signature %s", field_name,
- field_signature);
- return res;
-}
-
-static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
- const char* method_signature) {
- jmethodID res = env->GetMethodID(clazz, method_name, method_signature);
- LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s with signature %s", method_name,
- method_signature);
- return res;
-}
-
-static inline jfieldID GetStaticFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
- const char* field_signature) {
- jfieldID res = env->GetStaticFieldID(clazz, field_name, field_signature);
- LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s with signature %s", field_name,
- field_signature);
- return res;
-}
-
-static inline jmethodID GetStaticMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
- const char* method_signature) {
- jmethodID res = env->GetStaticMethodID(clazz, method_name, method_signature);
- LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static method %s with signature %s",
- method_name, method_signature);
- return res;
-}
-
-template <typename T>
-static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) {
- jobject res = env->NewGlobalRef(in);
- LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference.");
- return static_cast<T>(res);
-}
-
-static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className,
- const JNINativeMethod* gMethods, int numMethods) {
- int res = AndroidRuntime::registerNativeMethods(env, className, gMethods, numMethods);
- LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
- return res;
-}
-
/**
* Returns the result of invoking java.lang.ref.Reference.get() on a Reference object.
*/
diff --git a/core/jni/hwbinder/EphemeralStorage.cpp b/core/jni/hwbinder/EphemeralStorage.cpp
index 95bb42e..ef0750c 100644
--- a/core/jni/hwbinder/EphemeralStorage.cpp
+++ b/core/jni/hwbinder/EphemeralStorage.cpp
@@ -164,7 +164,7 @@
}
default:
- CHECK(!"Should not be here");
+ CHECK(!"Should not be here") << "Item type: " << item.mType;
}
}
diff --git a/core/jni/jni_wrappers.h b/core/jni/jni_wrappers.h
new file mode 100644
index 0000000..3b29e30
--- /dev/null
+++ b/core/jni/jni_wrappers.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+// JNI wrappers for better logging
+
+#include <jni.h>
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+
+static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
+ jclass clazz = env->FindClass(class_name);
+ LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name);
+ return clazz;
+}
+
+static inline jfieldID GetFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
+ const char* field_signature) {
+ jfieldID res = env->GetFieldID(clazz, field_name, field_signature);
+ LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find field %s with signature %s", field_name,
+ field_signature);
+ return res;
+}
+
+static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
+ const char* method_signature) {
+ jmethodID res = env->GetMethodID(clazz, method_name, method_signature);
+ LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s with signature %s", method_name,
+ method_signature);
+ return res;
+}
+
+static inline jfieldID GetStaticFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
+ const char* field_signature) {
+ jfieldID res = env->GetStaticFieldID(clazz, field_name, field_signature);
+ LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s with signature %s", field_name,
+ field_signature);
+ return res;
+}
+
+static inline jmethodID GetStaticMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
+ const char* method_signature) {
+ jmethodID res = env->GetStaticMethodID(clazz, method_name, method_signature);
+ LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static method %s with signature %s",
+ method_name, method_signature);
+ return res;
+}
+
+template <typename T>
+static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) {
+ jobject res = env->NewGlobalRef(in);
+ LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference.");
+ return static_cast<T>(res);
+}
+
+static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className,
+ const JNINativeMethod* gMethods, int numMethods) {
+ int res = jniRegisterNativeMethods(env, className, gMethods, numMethods);
+ LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+ return res;
+}
+
+} // namespace android
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index db391f7..00d90cc 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -13,14 +13,14 @@
jjaggi@google.com
kwekua@google.com
roosa@google.com
-per-file package_item_info.proto = toddke@google.com,patb@google.com
+per-file package_item_info.proto = file:/PACKAGE_MANAGER_OWNERS
per-file usagestatsservice.proto, usagestatsservice_v2.proto = file:/core/java/android/app/usage/OWNERS
per-file apphibernationservice.proto = file:/core/java/android/apphibernation/OWNERS
per-file android/hardware/sensorprivacy.proto = ntmyren@google.com,evanseverson@google.com
per-file background_install_control.proto = wenhaowang@google.com,georgechan@google.com,billylau@google.com
+per-file android/content/intent.proto = file:/PACKAGE_MANAGER_OWNERS
# Biometrics
-jaggies@google.com
jbolinger@google.com
# Launcher
@@ -31,5 +31,3 @@
# Accessibility
pweaver@google.com
-hongmingjin@google.com
-cbrower@google.com
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index bc74f39..5713e9e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2237,7 +2237,7 @@
<!-- @SystemApi @hide Allows changing Thread network state and access to Thread network
credentials such as Network Key and PSKc.
<p>Not for use by third-party applications.
- @FlaggedApi("com.android.net.thread.flags.thread_enabled") -->
+ @FlaggedApi("com.android.net.thread.platform.flags.thread_enabled_platform") -->
<permission android:name="android.permission.THREAD_NETWORK_PRIVILEGED"
android:protectionLevel="signature|privileged" />
@@ -2287,7 +2287,7 @@
<!-- Allows system apps to call methods to register itself as a mDNS offload engine.
<p>Not for use by third-party or privileged applications.
@SystemApi
- @FlaggedApi("com.android.net.flags.register_nsd_offload_engine")
+ @FlaggedApi("android.net.platform.flags.register_nsd_offload_engine")
@hide This should only be used by system apps.
-->
<permission android:name="android.permission.REGISTER_NSD_OFFLOAD_ENGINE"
@@ -3522,6 +3522,13 @@
<permission android:name="android.permission.MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION"
android:protectionLevel="internal|role" />
+ <!-- Allows an application to set policy related to <a
+ href="https://www.threadgroup.org">Thread</a> network.
+ @FlaggedApi("com.android.net.thread.platform.flags.thread_user_restriction_enabled")
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_THREAD_NETWORK"
+ android:protectionLevel="internal|role" />
+
<!-- Allows an application to set policy related to windows.
<p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
required to call APIs protected by this permission on users different to the calling user.
@@ -5751,7 +5758,7 @@
<permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS"
android:protectionLevel="signature|privileged" />
- <!-- Allows an application to collect usage infomation about brightness slider changes.
+ <!-- Allows an application to collect usage information about brightness slider changes.
<p>Not for use by third-party applications.</p>
@hide
@SystemApi
diff --git a/core/res/OWNERS b/core/res/OWNERS
index f24c3f5..36daa7d 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -8,7 +8,6 @@
hackbod@android.com
hackbod@google.com
ilyamaty@google.com
-jaggies@google.com
jbolinger@google.com
jsharkey@android.com
jsharkey@google.com
diff --git a/core/res/res/layout/app_perms_summary.xml b/core/res/res/layout/app_perms_summary.xml
index b8d93ac..509b988 100644
--- a/core/res/res/layout/app_perms_summary.xml
+++ b/core/res/res/layout/app_perms_summary.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<!-- Describes permission item consisting of a group name and the list of permisisons under the group -->
+<!-- Describes permission item consisting of a group name and the list of permissions under the group -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 3a2e50a..61e6a36 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -34,7 +34,7 @@
http://smscoin.net/software/engine/WordPress/Paid+SMS-registration/ -->
<!-- Arab Emirates -->
- <shortcode country="ae" pattern="\\d{1,5}" free="1017|1355|3214" />
+ <shortcode country="ae" pattern="\\d{1,5}" free="1017|1355|3214|6253" />
<!-- Albania: 5 digits, known short codes listed -->
<shortcode country="al" pattern="\\d{5}" premium="15191|55[56]00" />
@@ -86,7 +86,7 @@
<shortcode country="cn" premium="1066.*" free="1065.*" />
<!-- Colombia: 1-6 digits (not confirmed) -->
- <shortcode country="co" pattern="\\d{1,6}" free="890350|908160|892255|898002|898880|899960|899948|87739|85517" />
+ <shortcode country="co" pattern="\\d{1,6}" free="890350|908160|892255|898002|898880|899960|899948|87739|85517|491289" />
<!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
<shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
@@ -104,6 +104,12 @@
<!-- Denmark: see http://iprs.webspacecommerce.com/Denmark-Premium-Rate-Numbers -->
<shortcode country="dk" pattern="\\d{4,5}" premium="1\\d{3}" free="116\\d{3}|4665" />
+ <!-- Dominican Republic: 1-6 digits (standard system default, not country specific) -->
+ <shortcode country="do" pattern="\\d{1,6}" free="912892" />
+
+ <!-- Ecuador: 1-6 digits (standard system default, not country specific) -->
+ <shortcode country="ec" pattern="\\d{1,6}" free="466453" />
+
<!-- Estonia: short codes 3-5 digits starting with 1, plus premium 7 digit numbers starting with 90, plus EU.
http://www.tja.ee/public/documents/Elektrooniline_side/Oigusaktid/ENG/Estonian_Numbering_Plan_annex_06_09_2010.mht -->
<shortcode country="ee" pattern="1\\d{2,4}" premium="90\\d{5}|15330|1701[0-3]" free="116\\d{3}|95034" />
@@ -121,7 +127,7 @@
<!-- France: 5 digits, free: 3xxxx, premium [4-8]xxxx, plus EU:
http://clients.txtnation.com/entries/161972-france-premium-sms-short-code-requirements,
visual voicemail code for Orange: 21101 -->
- <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}|21101|20366|555|2051" />
+ <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}|21101|20366|555|2051|33033" />
<!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU:
http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf,
@@ -144,6 +150,9 @@
http://clients.txtnation.com/entries/209633-hungary-premium-sms-short-code-regulations -->
<shortcode country="hu" pattern="[01](?:\\d{3}|\\d{9})" premium="0691227910|1784" free="116\\d{3}" />
+ <!-- Honduras -->
+ <shortcode country="hn" pattern="\\d{4,6}" free="466453" />
+
<!-- India: 1-5 digits (standard system default, not country specific) -->
<shortcode country="in" pattern="\\d{1,5}" free="59336|53969" />
@@ -154,8 +163,8 @@
http://www.comreg.ie/_fileupload/publications/ComReg1117.pdf -->
<shortcode country="ie" pattern="\\d{5}" premium="5[3-9]\\d{3}" free="50\\d{3}|116\\d{3}" standard="5[12]\\d{3}" />
- <!-- Israel: 4 digits, known premium codes listed -->
- <shortcode country="il" pattern="\\d{4}" premium="4422|4545" />
+ <!-- Israel: 1-5 digits, known premium codes listed -->
+ <shortcode country="il" pattern="\\d{1,5}" premium="4422|4545" free="37477|6681" />
<!-- Italy: 5 digits (premium=41xxx,42xxx), plus EU:
https://www.itu.int/dms_pub/itu-t/oth/02/02/T020200006B0001PDFE.pdf -->
@@ -165,7 +174,7 @@
<shortcode country="jp" pattern="\\d{1,5}" free="8083" />
<!-- Kenya: 5 digits, known premium codes listed -->
- <shortcode country="ke" pattern="\\d{5}" free="21725|21562|40520|23342|40023" />
+ <shortcode country="ke" pattern="\\d{5}" free="21725|21562|40520|23342|40023|24088|23054" />
<!-- Kyrgyzstan: 4 digits, known premium codes listed -->
<shortcode country="kg" pattern="\\d{4}" premium="415[2367]|444[69]" />
@@ -177,7 +186,7 @@
<shortcode country="kz" pattern="\\d{4}" premium="335[02]|4161|444[469]|77[2359]0|8444|919[3-5]|968[2-5]" />
<!-- Kuwait: 1-5 digits (standard system default, not country specific) -->
- <shortcode country="kw" pattern="\\d{1,5}" free="1378|50420|94006|55991" />
+ <shortcode country="kw" pattern="\\d{1,5}" free="1378|50420|94006|55991|50976" />
<!-- Lithuania: 3-5 digits, known premium codes listed, plus EU -->
<shortcode country="lt" pattern="\\d{3,5}" premium="13[89]1|1394|16[34]5" free="116\\d{3}|1399|1324" />
@@ -189,15 +198,30 @@
<!-- Latvia: 4 digits, known premium codes listed, plus EU -->
<shortcode country="lv" pattern="\\d{4}" premium="18(?:19|63|7[1-4])" free="116\\d{3}|1399" />
+ <!-- Morocco: 1-5 digits (standard system default, not country specific) -->
+ <shortcode country="ma" pattern="\\d{1,5}" free="53819" />
+
<!-- Macedonia: 1-6 digits (not confirmed), known premium codes listed -->
<shortcode country="mk" pattern="\\d{1,6}" free="129005|122" />
+ <!-- Malawi: 1-5 digits (standard system default, not country specific) -->
+ <shortcode country="mw" pattern="\\d{1,5}" free="4276" />
+
+ <!-- Mozambique: 1-5 digits (standard system default, not country specific) -->
+ <shortcode country="mz" pattern="\\d{1,5}" free="1714" />
+
<!-- Mexico: 4-5 digits (not confirmed), known premium codes listed -->
- <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101|45453" />
+ <shortcode country="mx" pattern="\\d{4,6}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101|45453|550346" />
<!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf -->
<shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288|66668" />
+ <!-- Namibia: 1-5 digits (standard system default, not country specific) -->
+ <shortcode country="na" pattern="\\d{1,5}" free="40005" />
+
+ <!-- Nicaragua -->
+ <shortcode country="ni" pattern="\\d{4,6}" free="466453" />
+
<!-- The Netherlands, 4 digits, known premium codes listed, plus EU -->
<shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}|2223|6225|2223|1662" />
@@ -210,8 +234,8 @@
<!-- New Zealand: 3-4 digits, known premium codes listed -->
<shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995|4679" free="1737|176|2141|3067|3068|3110|3876|4006|4053|4061|4062|4202|4300|4334|4412|4575|5626|8006|8681" />
- <!-- Peru: 4-5 digits (not confirmed), known premium codes listed -->
- <shortcode country="pe" pattern="\\d{4,5}" free="9963|40778" />
+ <!-- Peru: 4-6 digits (not confirmed), known premium codes listed -->
+ <shortcode country="pe" pattern="\\d{4,6}" free="9963|40778|301303" />
<!-- Philippines -->
<shortcode country="ph" pattern="\\d{1,5}" free="2147|5495|5496" />
@@ -260,6 +284,12 @@
<!-- Slovakia: 4 digits (premium), plus EU: http://www.cmtelecom.com/premium-sms/slovakia -->
<shortcode country="sk" premium="\\d{4}" free="116\\d{3}|8000" />
+ <!-- Senegal(SN): 1-5 digits (standard system default, not country specific) -->
+ <shortcode country="sn" pattern="\\d{1,5}" free="21215" />
+
+ <!-- El Salvador(SV): 1-5 digits (standard system default, not country specific) -->
+ <shortcode country="sv" pattern="\\d{4,6}" free="466453" />
+
<!-- Taiwan -->
<shortcode country="tw" pattern="\\d{4}" free="1922" />
@@ -269,15 +299,21 @@
<!-- Tajikistan: 4 digits, known premium codes listed -->
<shortcode country="tj" pattern="\\d{4}" premium="11[3-7]1|4161|4333|444[689]" />
+ <!-- Tanzania: 1-5 digits (standard system default, not country specific) -->
+ <shortcode country="tz" pattern="\\d{1,5}" free="15046|15234" />
+
<!-- Turkey -->
<shortcode country="tr" pattern="\\d{1,5}" free="7529|5528|6493|3193" />
<!-- Ukraine: 4 digits, known premium codes listed -->
<shortcode country="ua" pattern="\\d{4}" premium="444[3-9]|70[579]4|7540" />
+ <!-- Uganda(UG): 4 digits (standard system default, not country specific) -->
+ <shortcode country="ug" pattern="\\d{4}" free="8000" />
+
<!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm),
visual voicemail code for T-Mobile: 122 -->
- <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567|244444" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245|611611" />
+ <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567|244444" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245|611611|96831" />
<!-- Vietnam: 1-5 digits (standard system default, not country specific) -->
<shortcode country="vn" pattern="\\d{1,5}" free="5001|9055" />
diff --git a/core/tests/BroadcastRadioTests/Android.bp b/core/tests/BroadcastRadioTests/Android.bp
index 054d10c..39ea6e6 100644
--- a/core/tests/BroadcastRadioTests/Android.bp
+++ b/core/tests/BroadcastRadioTests/Android.bp
@@ -18,6 +18,7 @@
// all of the 'license_kinds' from "frameworks_base_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
+ default_team: "trendy_team_aaos_framework",
default_applicable_licenses: ["frameworks_base_license"],
}
diff --git a/core/tests/BroadcastRadioTests/OWNERS b/core/tests/BroadcastRadioTests/OWNERS
index d2bdd64..51a85e4 100644
--- a/core/tests/BroadcastRadioTests/OWNERS
+++ b/core/tests/BroadcastRadioTests/OWNERS
@@ -1,3 +1,3 @@
xuweilin@google.com
oscarazu@google.com
-keunyoung@google.com
+ericjeong@google.com
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java
index 6a6a951..00afba8d 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java
@@ -264,7 +264,7 @@
int scanStatus = mRadioTuner.scan(RadioTuner.DIRECTION_DOWN, /* skipSubChannel= */ false);
verify(mTunerMock).seek(/* directionDown= */ true, /* skipSubChannel= */ false);
- assertWithMessage("Status for scaning")
+ assertWithMessage("Status for scanning")
.that(scanStatus).isEqualTo(RadioManager.STATUS_OK);
verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onProgramInfoChanged(FM_PROGRAM_INFO);
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
index 0806fa0..db95d7a 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
@@ -99,7 +99,7 @@
}
}
- public int getSoftApInterations() {
+ public int getSoftApIterations() {
return mSoftApIterations;
}
diff --git a/core/tests/coretests/src/android/animation/AnimatorSetCallsTest.java b/core/tests/coretests/src/android/animation/AnimatorSetCallsTest.java
index 43266a5..cb3f99c 100644
--- a/core/tests/coretests/src/android/animation/AnimatorSetCallsTest.java
+++ b/core/tests/coretests/src/android/animation/AnimatorSetCallsTest.java
@@ -17,6 +17,7 @@
package android.animation;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.util.PollingCheck;
@@ -343,6 +344,20 @@
}
@Test
+ public void childAnimatorCancelsDuringUpdate_animatorSetIsEnded() throws Throwable {
+ mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ animation.cancel();
+ }
+ });
+ mActivity.runOnUiThread(() -> {
+ mSet1.start();
+ assertFalse(mSet1.isRunning());
+ });
+ }
+
+ @Test
public void reentrantStart() throws Throwable {
CountDownLatch latch = new CountDownLatch(3);
AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index a0d8183..d2d7452 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -29,6 +29,7 @@
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
+import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.F_OK;
import static android.system.OsConstants.O_APPEND;
import static android.system.OsConstants.O_CREAT;
@@ -37,6 +38,7 @@
import static android.system.OsConstants.O_TRUNC;
import static android.system.OsConstants.O_WRONLY;
import static android.system.OsConstants.R_OK;
+import static android.system.OsConstants.SOCK_STREAM;
import static android.system.OsConstants.W_OK;
import static android.system.OsConstants.X_OK;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
@@ -54,6 +56,7 @@
import android.content.Context;
import android.os.FileUtils.MemoryPipe;
import android.provider.DocumentsContract.Document;
+import android.system.Os;
import android.util.DataUnit;
import androidx.test.InstrumentationRegistry;
@@ -70,6 +73,8 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -77,6 +82,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
+import java.net.InetSocketAddress;
@RunWith(AndroidJUnit4.class)
public class FileUtilsTest {
@@ -249,6 +255,84 @@
assertArrayEquals(expected, actual);
}
+ //TODO(ravenwood) Remove the _$noRavenwood suffix and add @RavenwoodIgnore instead
+ @Test
+ public void testCopy_SocketToFile_FileToSocket$noRavenwood() throws Exception {
+ for (int size : DATA_SIZES ) {
+ final File src = new File(mTarget, "src");
+ final File dest = new File(mTarget, "dest");
+ byte[] expected = new byte[size];
+ byte[] actual = new byte[size];
+ new Random().nextBytes(expected);
+
+ // write test data in to src file
+ writeFile(src, expected);
+
+ // start server, get data from client and save to dest file (socket --> file)
+ FileDescriptor srvSocketFd = Os.socket(AF_INET, SOCK_STREAM, 0);
+ Os.bind(srvSocketFd, new InetSocketAddress("localhost", 0));
+ Os.listen(srvSocketFd, 5);
+ InetSocketAddress localSocketAddress = (InetSocketAddress) Os.getsockname(srvSocketFd);
+
+ final Thread srv = new Thread(new Runnable() {
+ public void run() {
+ try {
+ InetSocketAddress peerAddress = new InetSocketAddress();
+ FileDescriptor srvConnFd = Os.accept(srvSocketFd, peerAddress);
+
+ // read file size
+ byte[] rcvFileSizeByteArray = new byte[8];
+ Os.read(srvConnFd, rcvFileSizeByteArray, 0, rcvFileSizeByteArray.length);
+ long rcvFileSize = 0;
+ for (int i = 0; i < 8; i++) {
+ rcvFileSize <<= 8;
+ rcvFileSize |= (rcvFileSizeByteArray[i] & 0xFF);
+ }
+
+ FileOutputStream fileOutputStream = new FileOutputStream(dest);
+ // copy data from socket to file
+ FileUtils.copy(srvConnFd, fileOutputStream.getFD(), rcvFileSize, null, null, null);
+
+ fileOutputStream.close();
+ Os.close(srvConnFd);
+ Os.close(srvSocketFd);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ srv.start();
+
+
+ // start client, get data from dest file and send to server (file --> socket)
+ FileDescriptor clientFd = Os.socket(AF_INET, SOCK_STREAM, 0);
+ Os.connect(clientFd, localSocketAddress.getAddress(), localSocketAddress.getPort());
+
+ FileInputStream fileInputStream = new FileInputStream(src);
+ long sndFileSize = src.length();
+ // send the file size to server
+ byte[] sndFileSizeByteArray = new byte[8];
+ for (int i = 7; i >= 0; i--) {
+ sndFileSizeByteArray[i] = (byte)(sndFileSize & 0xFF);
+ sndFileSize >>= 8;
+ }
+ Os.write(clientFd, sndFileSizeByteArray, 0, sndFileSizeByteArray.length);
+
+ // copy data from file to socket
+ FileUtils.copy(fileInputStream.getFD(), clientFd, src.length(), null, null, null);
+
+ fileInputStream.close();
+ Os.close(clientFd);
+
+ srv.join();
+
+ // read test data from dest file
+ actual = readFile(dest);
+ assertArrayEquals(expected, actual);
+ }
+ }
+
@Test
public void testIsFilenameSafe() throws Exception {
assertTrue(FileUtils.isFilenameSafe(new File("foobar")));
diff --git a/core/tests/nfctests/OWNERS b/core/tests/nfctests/OWNERS
deleted file mode 100644
index 34b095c..0000000
--- a/core/tests/nfctests/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /core/java/android/nfc/OWNERS
diff --git a/core/tests/overlaytests/Android.mk b/core/tests/overlaytests/Android.mk
deleted file mode 100644
index b798d87..0000000
--- a/core/tests/overlaytests/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-include $(call all-subdir-makefiles)
diff --git a/core/tests/overlaytests/host/Android.mk b/core/tests/overlaytests/host/Android.mk
deleted file mode 100644
index d58d939..0000000
--- a/core/tests/overlaytests/host/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-# Include to build test-apps.
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
diff --git a/core/tests/overlaytests/host/test-apps/Android.mk b/core/tests/overlaytests/host/test-apps/Android.mk
deleted file mode 100644
index 5c7187e..0000000
--- a/core/tests/overlaytests/host/test-apps/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-include $(call all-subdir-makefiles)
-
diff --git a/core/tests/overlaytests/host/test-apps/SignatureOverlay/Android.bp b/core/tests/overlaytests/host/test-apps/SignatureOverlay/Android.bp
new file mode 100644
index 0000000..bb7d63e
--- /dev/null
+++ b/core/tests/overlaytests/host/test-apps/SignatureOverlay/Android.bp
@@ -0,0 +1,57 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Error: Cannot get the name of the license module in the
+// ./Android.bp file.
+// If no such license module exists, please add one there first.
+// Then reset the default_applicable_licenses property below with the license module name.
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "OverlayHostTests_NonPlatformSignatureOverlay",
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+ aaptflags: [
+ "--custom-package com.android.server.om.hosttest.signature_overlay_bad",
+ ],
+}
+
+android_test_helper_app {
+ name: "OverlayHostTests_PlatformSignatureStaticOverlay",
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+ certificate: "platform",
+ manifest: "static/AndroidManifest.xml",
+ aaptflags: [
+ "--custom-package com.android.server.om.hosttest.signature_overlay_static",
+ ],
+}
+
+android_test_helper_app {
+ name: "OverlayHostTests_PlatformSignatureOverlay",
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+ certificate: "platform",
+ aaptflags: [
+ "--custom-package",
+ "com.android.server.om.hosttest.signature_overlay_v1",
+ "--version-code",
+ "1",
+ "--version-name",
+ "v1",
+ ],
+}
diff --git a/core/tests/overlaytests/host/test-apps/SignatureOverlay/Android.mk b/core/tests/overlaytests/host/test-apps/SignatureOverlay/Android.mk
deleted file mode 100644
index b453cde9..0000000
--- a/core/tests/overlaytests/host/test-apps/SignatureOverlay/Android.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-my_package_prefix := com.android.server.om.hosttest.signature_overlay
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := OverlayHostTests_NonPlatformSignatureOverlay
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_bad
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := OverlayHostTests_PlatformSignatureStaticOverlay
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_CERTIFICATE := platform
-LOCAL_MANIFEST_FILE := static/AndroidManifest.xml
-LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_static
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := OverlayHostTests_PlatformSignatureOverlay
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_CERTIFICATE := platform
-LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_v1
-LOCAL_AAPT_FLAGS += --version-code 1 --version-name v1
-include $(BUILD_PACKAGE)
-
-my_package_prefix :=
diff --git a/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.bp b/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.bp
new file mode 100644
index 0000000..ee0c0e5
--- /dev/null
+++ b/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.bp
@@ -0,0 +1,97 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Error: Cannot get the name of the license module in the
+// ./Android.bp file.
+// If no such license module exists, please add one there first.
+// Then reset the default_applicable_licenses property below with the license module name.
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "OverlayHostTests_UpdateOverlay",
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+ static_libs: ["androidx.test.rules"],
+ aaptflags: ["--no-resource-removal"],
+}
+
+android_test_helper_app {
+ name: "OverlayHostTests_FrameworkOverlayV1",
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+ certificate: "platform",
+ aaptflags: [
+ "--custom-package",
+ "com.android.server.om.hosttest.framework_overlay_v1",
+ "--version-code",
+ "1",
+ "--version-name",
+ "v1",
+ ],
+ resource_dirs: ["framework/v1/res"],
+ manifest: "framework/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+ name: "OverlayHostTests_FrameworkOverlayV2",
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+ certificate: "platform",
+ aaptflags: [
+ "--custom-package",
+ "com.android.server.om.hosttest.framework_overlay_v2",
+ "--version-code",
+ "2",
+ "--version-name",
+ "v2",
+ ],
+ resource_dirs: ["framework/v2/res"],
+ manifest: "framework/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+ name: "OverlayHostTests_AppOverlayV1",
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+ aaptflags: [
+ "--custom-package",
+ "com.android.server.om.hosttest.app_overlay_v1",
+ "--version-code",
+ "1",
+ "--version-name",
+ "v1",
+ ],
+ resource_dirs: ["app/v1/res"],
+ manifest: "app/v1/AndroidManifest.xml",
+}
+
+android_test_helper_app {
+ name: "OverlayHostTests_AppOverlayV2",
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+ aaptflags: [
+ "--custom-package",
+ "com.android.server.om.hosttest.app_overlay_v2",
+ "--version-code",
+ "2",
+ "--version-name",
+ "v2",
+ ],
+ resource_dirs: ["app/v2/res"],
+ manifest: "app/v2/AndroidManifest.xml",
+}
diff --git a/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk b/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk
deleted file mode 100644
index 77fc887..0000000
--- a/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk
+++ /dev/null
@@ -1,93 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_PACKAGE_NAME := OverlayHostTests_UpdateOverlay
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
-LOCAL_USE_AAPT2 := true
-LOCAL_AAPT_FLAGS := --no-resource-removal
-include $(BUILD_PACKAGE)
-
-my_package_prefix := com.android.server.om.hosttest.framework_overlay
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := OverlayHostTests_FrameworkOverlayV1
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_CERTIFICATE := platform
-LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_v1
-LOCAL_AAPT_FLAGS += --version-code 1 --version-name v1
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/framework/v1/res
-LOCAL_MANIFEST_FILE := framework/AndroidManifest.xml
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := OverlayHostTests_FrameworkOverlayV2
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_CERTIFICATE := platform
-LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_v2
-LOCAL_AAPT_FLAGS += --version-code 2 --version-name v2
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/framework/v2/res
-LOCAL_MANIFEST_FILE := framework/AndroidManifest.xml
-include $(BUILD_PACKAGE)
-
-my_package_prefix := com.android.server.om.hosttest.app_overlay
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := OverlayHostTests_AppOverlayV1
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_v1
-LOCAL_AAPT_FLAGS += --version-code 1 --version-name v1
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/app/v1/res
-LOCAL_MANIFEST_FILE := app/v1/AndroidManifest.xml
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := OverlayHostTests_AppOverlayV2
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_AAPT_FLAGS := --custom-package $(my_package_prefix)_v2
-LOCAL_AAPT_FLAGS += --version-code 2 --version-name v2
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/app/v2/res
-LOCAL_MANIFEST_FILE := app/v2/AndroidManifest.xml
-include $(BUILD_PACKAGE)
-
-my_package_prefix :=
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index ea23aba..245f216 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -1,3 +1,5 @@
+include /PACKAGE_MANAGER_OWNERS
+
alanstokes@google.com
cbrubaker@google.com
hackbod@android.com
@@ -6,11 +8,6 @@
jsharkey@android.com
jsharkey@google.com
lorenzo@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
-toddke@android.com
-toddke@google.com
-patb@google.com
yamasani@google.com
per-file preinstalled-packages* = file:/MULTIUSER_OWNERS
diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml
index dcc9686..fbe1b8e 100644
--- a/data/etc/com.android.settings.xml
+++ b/data/etc/com.android.settings.xml
@@ -48,6 +48,7 @@
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.READ_SEARCH_INDEXABLES"/>
<permission name="android.permission.REBOOT"/>
+ <permission name="android.permission.RECOVERY"/>
<permission name="android.permission.STATUS_BAR"/>
<permission name="android.permission.SUGGEST_MANUAL_TIME_AND_ZONE"/>
<permission name="android.permission.TETHER_PRIVILEGED"/>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index c4530f6..cb803f7 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -124,6 +124,10 @@
<group gid="security_log_writer" />
</permission>
+ <permission name="android.permission.MANAGE_VIRTUAL_MACHINE">
+ <group gid="virtualmachine" />
+ </permission>
+
<!-- These are permissions that were mapped to gids but we need
to keep them here until an upgrade from L to the current
version is to be supported. These permissions are built-in
diff --git a/data/fonts/Android.bp b/data/fonts/Android.bp
index 3dd9ba9..f403b4f 100644
--- a/data/fonts/Android.bp
+++ b/data/fonts/Android.bp
@@ -57,3 +57,9 @@
name: "font_fallback.xml",
src: "font_fallback.xml",
}
+
+/////////////////////////////////
+// Move `fontchain_lint` to `core/tasks/fontchain_lint.mk`.
+// Because `system.img` is a dependency of `fontchain_lint`, it cannot be
+// converted to Android.bp for now.
+// After system.img can be generated by Soong, then it can be converted to Android.bp.
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
deleted file mode 100644
index a322b82..0000000
--- a/data/fonts/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-# Run sanity tests on fonts on checkbuild
-checkbuild: fontchain_lint
-
-FONTCHAIN_LINTER := $(HOST_OUT_EXECUTABLES)/fontchain_linter
-ifeq ($(MINIMAL_FONT_FOOTPRINT),true)
-CHECK_EMOJI := false
-else
-CHECK_EMOJI := true
-endif
-
-fontchain_lint_timestamp := $(call intermediates-dir-for,PACKAGING,fontchain_lint)/stamp
-
-.PHONY: fontchain_lint
-fontchain_lint: $(fontchain_lint_timestamp)
-
-fontchain_lint_deps := \
- external/unicode/DerivedAge.txt \
- external/unicode/emoji-data.txt \
- external/unicode/emoji-sequences.txt \
- external/unicode/emoji-variation-sequences.txt \
- external/unicode/emoji-zwj-sequences.txt \
- external/unicode/additions/emoji-data.txt \
- external/unicode/additions/emoji-sequences.txt \
- external/unicode/additions/emoji-zwj-sequences.txt \
-
-$(fontchain_lint_timestamp): $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml $(PRODUCT_OUT)/system.img $(fontchain_lint_deps)
- @echo Running fontchain lint
- $(FONTCHAIN_LINTER) $(TARGET_OUT) $(CHECK_EMOJI) external/unicode
- touch $@
diff --git a/data/keyboards/Android.bp b/data/keyboards/Android.bp
new file mode 100644
index 0000000..f15c153
--- /dev/null
+++ b/data/keyboards/Android.bp
@@ -0,0 +1,29 @@
+// Copyright 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+genrule {
+ name: "validate_framework_keymaps",
+ srcs: [
+ "*.kl",
+ "*.kcm",
+ "*.idc",
+ ],
+ tools: ["validatekeymaps"],
+ out: ["stamp"],
+ cmd: "$(location validatekeymaps) -q $(in) " +
+ "&& touch $(out)",
+ dist: {
+ targets: ["droidcore"],
+ },
+}
diff --git a/data/keyboards/Android.mk b/data/keyboards/Android.mk
deleted file mode 100644
index 6ae8800..0000000
--- a/data/keyboards/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This makefile performs build time validation of framework keymap files.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(LOCAL_PATH)/common.mk
-
-# Validate all key maps.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := validate_framework_keymaps
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-intermediates := $(call intermediates-dir-for,ETC,$(LOCAL_MODULE),,COMMON)
-LOCAL_BUILT_MODULE := $(intermediates)/stamp
-
-validatekeymaps := $(HOST_OUT_EXECUTABLES)/validatekeymaps$(HOST_EXECUTABLE_SUFFIX)
-$(LOCAL_BUILT_MODULE): PRIVATE_VALIDATEKEYMAPS := $(validatekeymaps)
-$(LOCAL_BUILT_MODULE) : $(framework_keylayouts) $(framework_keycharmaps) $(framework_keyconfigs) | $(validatekeymaps)
- $(hide) $(PRIVATE_VALIDATEKEYMAPS) -q $^
- $(hide) mkdir -p $(dir $@) && touch $@
-
-# Run validatekeymaps uncondionally for platform build.
-droidcore : $(LOCAL_BUILT_MODULE)
-
-# Reset temp vars.
-validatekeymaps :=
-framework_keylayouts :=
-framework_keycharmaps :=
-framework_keyconfigs :=
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 31092536..51b720d 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -430,19 +430,17 @@
key 659 MACRO_4
# Keys defined by HID usages
-key usage 0x0c0067 WINDOW
-key usage 0x0c006F BRIGHTNESS_UP
-key usage 0x0c0070 BRIGHTNESS_DOWN
-key usage 0x0c0079 KEYBOARD_BACKLIGHT_UP
-key usage 0x0c007A KEYBOARD_BACKLIGHT_DOWN
-key usage 0x0c007C KEYBOARD_BACKLIGHT_TOGGLE
-key usage 0x0c0173 MEDIA_AUDIO_TRACK
-key usage 0x0c019C PROFILE_SWITCH
-key usage 0x0c01A2 ALL_APPS
-# 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
+key usage 0x0c0067 WINDOW FALLBACK_USAGE_MAPPING
+key usage 0x0c006F BRIGHTNESS_UP FALLBACK_USAGE_MAPPING
+key usage 0x0c0070 BRIGHTNESS_DOWN FALLBACK_USAGE_MAPPING
+key usage 0x0c0079 KEYBOARD_BACKLIGHT_UP FALLBACK_USAGE_MAPPING
+key usage 0x0c007A KEYBOARD_BACKLIGHT_DOWN FALLBACK_USAGE_MAPPING
+key usage 0x0c007C KEYBOARD_BACKLIGHT_TOGGLE FALLBACK_USAGE_MAPPING
+key usage 0x0c0173 MEDIA_AUDIO_TRACK FALLBACK_USAGE_MAPPING
+key usage 0x0c019C PROFILE_SWITCH FALLBACK_USAGE_MAPPING
+key usage 0x0c01A2 ALL_APPS FALLBACK_USAGE_MAPPING
+key usage 0x0d0044 STYLUS_BUTTON_PRIMARY FALLBACK_USAGE_MAPPING
+key usage 0x0d005a STYLUS_BUTTON_SECONDARY FALLBACK_USAGE_MAPPING
# Joystick and game controller axes.
# Axes that are not mapped will be assigned generic axis numbers by the input subsystem.
diff --git a/data/keyboards/Vendor_0428_Product_4001.kl b/data/keyboards/Vendor_0428_Product_4001.kl
new file mode 100644
index 0000000..7d1dd12
--- /dev/null
+++ b/data/keyboards/Vendor_0428_Product_4001.kl
@@ -0,0 +1,27 @@
+# Gravis GamePad Pro USB
+
+# Yellow
+key 0x131 BUTTON_A
+# Green
+key 0x132 BUTTON_B
+# Red
+key 0x130 BUTTON_X
+# Blue
+key 0x133 BUTTON_Y
+
+# Left Upper Shoulder "1"
+key 0x134 BUTTON_L1
+# Right Upper Shoulder "1"
+key 0x135 BUTTON_R1
+# Left Lower Shoulder "2"
+key 0x136 BUTTON_L2
+# Right Lower Shoulder "2"
+key 0x137 BUTTON_R2
+
+# Select & Start
+key 0x138 BUTTON_SELECT
+key 0x139 BUTTON_START
+
+# D-Pad
+axis 0x00 HAT_X
+axis 0x01 HAT_Y
diff --git a/data/keyboards/common.mk b/data/keyboards/common.mk
deleted file mode 100644
index d75b691..0000000
--- a/data/keyboards/common.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This is the list of framework provided keylayouts and key character maps to include.
-# Used by Android.mk and keyboards.mk.
-
-framework_keylayouts := $(wildcard $(LOCAL_PATH)/*.kl)
-
-framework_keycharmaps := $(wildcard $(LOCAL_PATH)/*.kcm)
-
-framework_keyconfigs := $(wildcard $(LOCAL_PATH)/*.idc)
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 1da8e18..d915b74 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -25,10 +25,13 @@
import android.content.res.Resources;
import android.os.Build;
import android.os.Trace;
+import android.system.OsConstants;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
+import libcore.io.IoBridge;
+
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
@@ -523,19 +526,19 @@
public static Bitmap decodeFile(String pathName, Options opts) {
validate(opts);
Bitmap bm = null;
- InputStream stream = null;
+ FileDescriptor fd = null;
try {
- stream = new FileInputStream(pathName);
- bm = decodeStream(stream, null, opts);
+ fd = IoBridge.open(pathName, OsConstants.O_RDONLY);
+ bm = decodeFileDescriptor(fd, null, opts);
} catch (Exception e) {
/* do nothing.
If the exception happened on open, bm will be null.
*/
- Log.e("BitmapFactory", "Unable to decode stream: " + e);
+ Log.e("BitmapFactory", "Unable to decode file: " + e);
} finally {
- if (stream != null) {
+ if (fd != null) {
try {
- stream.close();
+ IoBridge.closeAndSignalBlockedThreads(fd);
} catch (IOException e) {
// do nothing here
}
diff --git a/graphics/java/android/view/PixelCopy.java b/graphics/java/android/view/PixelCopy.java
index 0e198d5..1200ff9 100644
--- a/graphics/java/android/view/PixelCopy.java
+++ b/graphics/java/android/view/PixelCopy.java
@@ -96,7 +96,7 @@
*
* The contents of the source will be scaled to fit exactly inside the bitmap.
* The pixel format of the source buffer will be converted, as part of the copy,
- * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer
+ * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer
* in the SurfaceView's Surface will be used as the source of the copy.
*
* @param source The source from which to copy
@@ -117,7 +117,7 @@
*
* The contents of the source will be scaled to fit exactly inside the bitmap.
* The pixel format of the source buffer will be converted, as part of the copy,
- * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer
+ * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer
* in the SurfaceView's Surface will be used as the source of the copy.
*
* @param source The source from which to copy
@@ -143,7 +143,7 @@
*
* The contents of the source will be scaled to fit exactly inside the bitmap.
* The pixel format of the source buffer will be converted, as part of the copy,
- * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer
+ * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer
* in the Surface will be used as the source of the copy.
*
* @param source The source from which to copy
@@ -164,7 +164,7 @@
*
* The contents of the source rect will be scaled to fit exactly inside the bitmap.
* The pixel format of the source buffer will be converted, as part of the copy,
- * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer
+ * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer
* in the Surface will be used as the source of the copy.
*
* @param source The source from which to copy
@@ -201,7 +201,7 @@
*
* The contents of the source will be scaled to fit exactly inside the bitmap.
* The pixel format of the source buffer will be converted, as part of the copy,
- * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer
+ * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer
* in the Window's Surface will be used as the source of the copy.
*
* Note: This is limited to being able to copy from Window's with a non-null
@@ -231,7 +231,7 @@
*
* The contents of the source rect will be scaled to fit exactly inside the bitmap.
* The pixel format of the source buffer will be converted, as part of the copy,
- * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer
+ * to fit the bitmap's {@link Bitmap.Config}. The most recently queued buffer
* in the Window's Surface will be used as the source of the copy.
*
* Note: This is limited to being able to copy from Window's with a non-null
diff --git a/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl b/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl
index c360cb8..cfc5980 100644
--- a/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl
+++ b/keystore/aaid/aidl/android/security/keystore/IKeyAttestationApplicationIdProvider.aidl
@@ -20,8 +20,14 @@
/** @hide */
interface IKeyAttestationApplicationIdProvider {
+ const int ERROR_GET_ATTESTATION_APPLICATION_ID_FAILED = 1;
+
/**
* Provides information describing the possible applications identified by a UID.
+ *
+ * In case of not getting package ids from uid return
+ * {@link #ERROR_GET_ATTESTATION_APPLICATION_ID_FAILED} to the caller.
+ *
* @hide
*/
KeyAttestationApplicationId getKeyAttestationApplicationId(int uid);
diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
index 2beb434..2430e8d 100644
--- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.os.StrictMode;
@@ -218,4 +219,28 @@
return SYSTEM_ERROR;
}
}
+
+ /**
+ * Returns the list of Application UIDs that have auth-bound keys that are bound to
+ * the given SID. This enables warning the user when they are about to invalidate
+ * a SID (for example, removing the LSKF).
+ *
+ * @param userId - The ID of the user the SID is associated with.
+ * @param userSecureId - The SID in question.
+ *
+ * @return A list of app UIDs.
+ */
+ public static long[] getAllAppUidsAffectedBySid(int userId, long userSecureId)
+ throws KeyStoreException {
+ StrictMode.noteDiskWrite();
+ try {
+ return getService().getAppUidsAffectedBySid(userId, userSecureId);
+ } catch (RemoteException | NullPointerException e) {
+ throw new KeyStoreException(SYSTEM_ERROR,
+ "Failure to connect to Keystore while trying to get apps affected by SID.");
+ } catch (ServiceSpecificException e) {
+ throw new KeyStoreException(e.errorCode,
+ "Keystore error while trying to get apps affected by SID.");
+ }
+ }
}
diff --git a/keystore/java/android/security/AndroidProtectedConfirmation.java b/keystore/java/android/security/AndroidProtectedConfirmation.java
index dfe485a..268e0a5 100644
--- a/keystore/java/android/security/AndroidProtectedConfirmation.java
+++ b/keystore/java/android/security/AndroidProtectedConfirmation.java
@@ -59,6 +59,10 @@
/**
* Requests keystore call into the confirmationui HAL to display a prompt.
+ * @deprecated Android Protected Confirmation had a low adoption rate among Android device
+ * makers and developers alike. Given the lack of devices supporting the
+ * feature, it is deprecated. Developers can use auth-bound Keystore keys
+ * as a partial replacement.
*
* @param listener the binder to use for callbacks.
* @param promptText the prompt to display.
@@ -68,6 +72,7 @@
* @return one of the {@code CONFIRMATIONUI_*} constants, for
* example {@code KeyStore.CONFIRMATIONUI_OK}.
*/
+ @Deprecated
public int presentConfirmationPrompt(IConfirmationCallback listener, String promptText,
byte[] extraData, String locale, int uiOptionsAsFlags) {
try {
@@ -84,11 +89,16 @@
/**
* Requests keystore call into the confirmationui HAL to cancel displaying a prompt.
+ * @deprecated Android Protected Confirmation had a low adoption rate among Android device
+ * makers and developers alike. Given the lack of devices supporting the
+ * feature, it is deprecated. Developers can use auth-bound Keystore keys
+ * as a partial replacement.
*
* @param listener the binder passed to the {@link #presentConfirmationPrompt} method.
* @return one of the {@code CONFIRMATIONUI_*} constants, for
* example {@code KeyStore.CONFIRMATIONUI_OK}.
*/
+ @Deprecated
public int cancelConfirmationPrompt(IConfirmationCallback listener) {
try {
getService().cancelPrompt(listener);
@@ -103,9 +113,14 @@
/**
* Requests keystore to check if the confirmationui HAL is available.
+ * @deprecated Android Protected Confirmation had a low adoption rate among Android device
+ * makers and developers alike. Given the lack of devices supporting the
+ * feature, it is deprecated. Developers can use auth-bound Keystore keys
+ * as a partial replacement.
*
* @return whether the confirmationUI HAL is available.
*/
+ @Deprecated
public boolean isConfirmationPromptSupported() {
try {
return getService().isSupported();
diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java
index 4ec5e1b..6404c4b 100644
--- a/keystore/java/android/security/Authorization.java
+++ b/keystore/java/android/security/Authorization.java
@@ -100,12 +100,14 @@
*
* @param userId - the user's Android user ID
* @param unlockingSids - list of biometric SIDs with which the device may be unlocked again
+ * @param weakUnlockEnabled - true if non-strong biometric or trust agent unlock is enabled
* @return 0 if successful or a {@code ResponseCode}.
*/
- public static int onDeviceLocked(int userId, @NonNull long[] unlockingSids) {
+ public static int onDeviceLocked(int userId, @NonNull long[] unlockingSids,
+ boolean weakUnlockEnabled) {
StrictMode.noteDiskWrite();
try {
- getService().onDeviceLocked(userId, unlockingSids);
+ getService().onDeviceLocked(userId, unlockingSids, weakUnlockEnabled);
return 0;
} catch (RemoteException | NullPointerException e) {
Log.w(TAG, "Can not connect to keystore", e);
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 11b8271..bd9abec 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -21,12 +21,14 @@
import android.os.StrictMode;
/**
- * @hide This should not be made public in its present form because it
- * assumes that private and secret key bytes are available and would
- * preclude the use of hardware crypto.
+ * This class provides some constants and helper methods related to Android's Keystore service.
+ * This class was originally much larger, but its functionality was superseded by other classes.
+ * It now just contains a few remaining pieces for which the users haven't been updated yet.
+ * You may be looking for {@link java.security.KeyStore} instead.
+ *
+ * @hide
*/
public class KeyStore {
- private static final String TAG = "KeyStore";
// ResponseCodes - see system/security/keystore/include/keystore/keystore.h
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -42,50 +44,6 @@
return KEY_STORE;
}
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public byte[] get(String key) {
- return null;
- }
-
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public boolean delete(String key) {
- return false;
- }
-
- /**
- * List uids of all keys that are auth bound to the current user.
- * Only system is allowed to call this method.
- * @hide
- * @deprecated This function always returns null.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int[] listUidsOfAuthBoundKeys() {
- return null;
- }
-
-
- /**
- * @hide
- * @deprecated This function has no effect.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public boolean unlock(String password) {
- return false;
- }
-
- /**
- *
- * @return
- * @deprecated This function always returns true.
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
- public boolean isEmpty() {
- return true;
- }
-
/**
* Add an authentication record to the keystore authorization table.
*
@@ -105,13 +63,4 @@
public void onDeviceOffBody() {
AndroidKeyStoreMaintenance.onDeviceOffBody();
}
-
- /**
- * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
- * code.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static KeyStoreException getKeyStoreException(int errorCode) {
- return new KeyStoreException(-10000, "Should not be called.");
- }
}
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 4982f37..244fe30 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -618,7 +618,7 @@
* @see #isMgf1DigestsSpecified()
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2)
public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {
if (mMgf1Digests.isEmpty()) {
throw new IllegalStateException("Mask generation function (MGF) not specified");
@@ -633,7 +633,7 @@
* @see #getMgf1Digests()
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2)
public boolean isMgf1DigestsSpecified() {
return !mMgf1Digests.isEmpty();
}
@@ -1292,7 +1292,7 @@
* <p>See {@link KeyProperties}.{@code DIGEST} constants.
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2)
public Builder setMgf1Digests(@NonNull @KeyProperties.DigestEnum String... mgf1Digests) {
mMgf1Digests = Set.of(mgf1Digests);
return this;
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index f50efd2..5cffe46 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -16,6 +16,7 @@
package android.security.keystore;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -81,6 +82,7 @@
private final @KeyProperties.AuthEnum int mUserAuthenticationType;
private final boolean mUserAuthenticationRequirementEnforcedBySecureHardware;
private final boolean mUserAuthenticationValidWhileOnBody;
+ private final boolean mUnlockedDeviceRequired;
private final boolean mTrustedUserPresenceRequired;
private final boolean mInvalidatedByBiometricEnrollment;
private final boolean mUserConfirmationRequired;
@@ -107,6 +109,7 @@
@KeyProperties.AuthEnum int userAuthenticationType,
boolean userAuthenticationRequirementEnforcedBySecureHardware,
boolean userAuthenticationValidWhileOnBody,
+ boolean unlockedDeviceRequired,
boolean trustedUserPresenceRequired,
boolean invalidatedByBiometricEnrollment,
boolean userConfirmationRequired,
@@ -132,6 +135,7 @@
mUserAuthenticationRequirementEnforcedBySecureHardware =
userAuthenticationRequirementEnforcedBySecureHardware;
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
+ mUnlockedDeviceRequired = unlockedDeviceRequired;
mTrustedUserPresenceRequired = trustedUserPresenceRequired;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
mUserConfirmationRequired = userConfirmationRequired;
@@ -275,6 +279,20 @@
}
/**
+ * Returns {@code true} if the key is authorized to be used only when the device is unlocked.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
+ *
+ * @see KeyGenParameterSpec.Builder#setUnlockedDeviceRequired(boolean)
+ * @see KeyProtection.Builder#setUnlockedDeviceRequired(boolean)
+ */
+ @FlaggedApi(android.security.Flags.FLAG_KEYINFO_UNLOCKED_DEVICE_REQUIRED)
+ public boolean isUnlockedDeviceRequired() {
+ return mUnlockedDeviceRequired;
+ }
+
+ /**
* Returns {@code true} if the key is authorized to be used only for messages confirmed by the
* user.
*
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 7b6b2d1..2495d1a 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -401,7 +401,7 @@
* @see #isMgf1DigestsSpecified()
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2)
public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {
if (mMgf1Digests.isEmpty()) {
throw new IllegalStateException("Mask generation function (MGF) not specified");
@@ -416,7 +416,7 @@
* @see #getMgf1Digests()
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2)
public boolean isMgf1DigestsSpecified() {
return !mMgf1Digests.isEmpty();
}
@@ -799,7 +799,7 @@
* <p>See {@link KeyProperties}.{@code DIGEST} constants.
*/
@NonNull
- @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
+ @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER_V2)
public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) {
mMgf1Digests = Set.of(mgf1Digests);
return this;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index 9c05a3a..e6c652c 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -109,13 +109,29 @@
}
}
+ // For curve 25519, KeyMint uses the KM_ALGORITHM_EC constant, but in the Java layer we need
+ // to distinguish between Curve 25519 and other EC algorithms, so we use a different constant
+ // with a value that is outside the range of the enum used for KeyMint algorithms.
+ private static final int ALGORITHM_XDH = KeymasterDefs.KM_ALGORITHM_EC + 1200;
+ private static final int ALGORITHM_ED25519 = ALGORITHM_XDH + 1;
+
/**
- * XDH represents Curve 25519 providers.
+ * XDH represents Curve 25519 agreement key provider.
*/
public static class XDH extends AndroidKeyStoreKeyPairGeneratorSpi {
// XDH is treated as EC.
public XDH() {
- super(KeymasterDefs.KM_ALGORITHM_EC);
+ super(ALGORITHM_XDH);
+ }
+ }
+
+ /**
+ * ED25519 represents Curve 25519 signing key provider.
+ */
+ public static class ED25519 extends AndroidKeyStoreKeyPairGeneratorSpi {
+ // ED25519 is treated as EC.
+ public ED25519() {
+ super(ALGORITHM_ED25519);
}
}
@@ -241,7 +257,9 @@
KeyGenParameterSpec spec;
boolean encryptionAtRestRequired = false;
- int keymasterAlgorithm = mOriginalKeymasterAlgorithm;
+ int keymasterAlgorithm = (mOriginalKeymasterAlgorithm == ALGORITHM_XDH
+ || mOriginalKeymasterAlgorithm == ALGORITHM_ED25519)
+ ? KeymasterDefs.KM_ALGORITHM_EC : mOriginalKeymasterAlgorithm;
if (params instanceof KeyGenParameterSpec) {
spec = (KeyGenParameterSpec) params;
} else if (params instanceof KeyPairGeneratorSpec) {
@@ -610,6 +628,15 @@
if (algSpecificSpec instanceof ECGenParameterSpec) {
ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec;
mEcCurveName = ecSpec.getName();
+ if (mOriginalKeymasterAlgorithm == ALGORITHM_XDH
+ && !mEcCurveName.equalsIgnoreCase("x25519")) {
+ throw new InvalidAlgorithmParameterException("XDH algorithm only supports"
+ + " x25519 curve.");
+ } else if (mOriginalKeymasterAlgorithm == ALGORITHM_ED25519
+ && !mEcCurveName.equalsIgnoreCase("ed25519")) {
+ throw new InvalidAlgorithmParameterException("Ed25519 algorithm only"
+ + " supports ed25519 curve.");
+ }
final Integer ecSpecKeySizeBits = SUPPORTED_EC_CURVE_NAME_TO_SIZE.get(
mEcCurveName.toLowerCase(Locale.US));
if (ecSpecKeySizeBits == null) {
@@ -947,7 +974,7 @@
private static boolean getMgf1DigestSetterFlag() {
try {
- return Flags.mgf1DigestSetter();
+ return Flags.mgf1DigestSetterV2();
} catch (SecurityException e) {
Log.w(TAG, "Cannot read MGF1 Digest setter flag value", e);
return false;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index 11278e8..d204f13 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -86,11 +86,14 @@
put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$EC");
put("KeyPairGenerator.RSA", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA");
put("KeyPairGenerator.XDH", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$XDH");
+ put("KeyPairGenerator.ED25519", PACKAGE_NAME
+ + ".AndroidKeyStoreKeyPairGeneratorSpi$ED25519");
// java.security.KeyFactory
putKeyFactoryImpl("EC");
putKeyFactoryImpl("RSA");
putKeyFactoryImpl("XDH");
+ putKeyFactoryImpl("ED25519");
// javax.crypto.KeyGenerator
put("KeyGenerator.AES", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$AES");
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
index 97592b4..2682eb6 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -93,6 +93,7 @@
long userAuthenticationValidityDurationSeconds = 0;
boolean userAuthenticationRequired = true;
boolean userAuthenticationValidWhileOnBody = false;
+ boolean unlockedDeviceRequired = false;
boolean trustedUserPresenceRequired = false;
boolean trustedUserConfirmationRequired = false;
int remainingUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT;
@@ -184,6 +185,9 @@
+ userAuthenticationValidityDurationSeconds + " seconds");
}
break;
+ case KeymasterDefs.KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+ unlockedDeviceRequired = true;
+ break;
case KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY:
userAuthenticationValidWhileOnBody =
KeyStore2ParameterUtils.isSecureHardware(a.securityLevel);
@@ -257,6 +261,7 @@
: keymasterSwEnforcedUserAuthenticators,
userAuthenticationRequirementEnforcedBySecureHardware,
userAuthenticationValidWhileOnBody,
+ unlockedDeviceRequired,
trustedUserPresenceRequired,
invalidatedByBiometricEnrollment,
trustedUserConfirmationRequired,
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 2d8c5a3..e6a63b9 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -259,7 +259,7 @@
private static boolean getMgf1DigestSetterFlag() {
try {
- return Flags.mgf1DigestSetter();
+ return Flags.mgf1DigestSetterV2();
} catch (SecurityException e) {
Log.w(NAME, "Cannot read MGF1 Digest setter flag value", e);
return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index f35eda6..63ca6a52 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -336,7 +336,7 @@
continue;
}
- final int pairedTaskId = mSplitTasks.get(taskInfo.taskId);
+ final int pairedTaskId = mSplitTasks.get(taskInfo.taskId, INVALID_TASK_ID);
if (pairedTaskId != INVALID_TASK_ID && rawMapping.contains(
pairedTaskId)) {
final ActivityManager.RecentTaskInfo pairedTaskInfo = rawMapping.get(pairedTaskId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 7dec12a..2c0ba92 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -479,18 +479,20 @@
private void startFadeAnimation(@NonNull SurfaceControl leash, boolean show) {
final float end = show ? 1.f : 0.f;
final float start = 1.f - end;
- final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
final ValueAnimator va = ValueAnimator.ofFloat(start, end);
va.setDuration(FADE_DURATION);
va.setInterpolator(show ? ALPHA_IN : ALPHA_OUT);
va.addUpdateListener(animation -> {
float fraction = animation.getAnimatedFraction();
+ final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
transaction.setAlpha(leash, start * (1.f - fraction) + end * fraction);
transaction.apply();
+ mTransactionPool.release(transaction);
});
va.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
transaction.setAlpha(leash, end);
transaction.apply();
mTransactionPool.release(transaction);
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index bb62846..e0ccf17 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -210,15 +210,6 @@
path: "apex/java",
}
-java_api_contribution {
- name: "framework-graphics-public-stubs",
- api_surface: "public",
- api_file: "api/current.txt",
- visibility: [
- "//build/orchestrator/apis",
- ],
-}
-
// ------------------------
// APEX
// ------------------------
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index a8d170d..f4d6b8c 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -218,7 +218,7 @@
}
// Perform clipping
- if (props.getClipDamageToBounds() && !frame->pendingDirty.isEmpty()) {
+ if (props.getClipDamageToBounds()) {
if (!frame->pendingDirty.intersect(SkRect::MakeIWH(props.getWidth(), props.getHeight()))) {
frame->pendingDirty.setEmpty();
}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 1dd22cf..a733d17 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -218,7 +218,7 @@
* stencil buffer may be needed. Views that use a functor to draw will be forced onto a layer.
*/
void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer) {
- if (mDamageGenerationId == info.damageGenerationId) {
+ if (mDamageGenerationId == info.damageGenerationId && mDamageGenerationId != 0) {
// We hit the same node a second time in the same tree. We don't know the minimal
// damage rect anymore, so just push the biggest we can onto our parent's transform
// We push directly onto parent in case we are clipped to bounds but have moved position.
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 572635a..4d03bf1 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -263,7 +263,7 @@
DisplayList mDisplayList;
DisplayList mStagingDisplayList;
- int64_t mDamageGenerationId;
+ int64_t mDamageGenerationId = 0;
friend class AnimatorManager;
AnimatorManager mAnimatorManager;
diff --git a/libs/hwui/jni/PathMeasure.cpp b/libs/hwui/jni/PathMeasure.cpp
index acf893e..79acb6c 100644
--- a/libs/hwui/jni/PathMeasure.cpp
+++ b/libs/hwui/jni/PathMeasure.cpp
@@ -17,7 +17,11 @@
#include "GraphicsJNI.h"
+#include "SkMatrix.h"
+#include "SkPath.h"
#include "SkPathMeasure.h"
+#include "SkPoint.h"
+#include "SkScalar.h"
/* We declare an explicit pair, so that we don't have to rely on the java
client to be sure not to edit the path while we have an active measure
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index cf31173..56f1e64 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -115,7 +115,7 @@
const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler,
- const HardwareBufferRenderParams& bufferParams) {
+ const HardwareBufferRenderParams& bufferParams, std::mutex& profilerLock) {
if (!isCapturingSkp() && !mHardwareBuffer) {
mEglManager.damageFrame(frame, dirty);
}
@@ -167,6 +167,7 @@
// Draw visual debugging features
if (CC_UNLIKELY(Properties::showDirtyRegions ||
ProfileType::None != Properties::getProfileType())) {
+ std::scoped_lock lock(profilerLock);
SkCanvas* profileCanvas = surface->getCanvas();
SkiaProfileRenderer profileRenderer(profileCanvas, frame.width(), frame.height());
profiler->draw(profileRenderer);
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index f0461be..0325593 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -42,7 +42,8 @@
const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
const std::vector<sp<RenderNode> >& renderNodes, FrameInfoVisualizer* profiler,
- const renderthread::HardwareBufferRenderParams& bufferParams) override;
+ const renderthread::HardwareBufferRenderParams& bufferParams,
+ std::mutex& profilerLock) override;
GrSurfaceOrigin getSurfaceOrigin() override { return kBottomLeft_GrSurfaceOrigin; }
bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
FrameInfo* currentFrameInfo, bool* requireSwap) override;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 86096d5..7d19232 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -75,7 +75,7 @@
const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler,
- const HardwareBufferRenderParams& bufferParams) {
+ const HardwareBufferRenderParams& bufferParams, std::mutex& profilerLock) {
sk_sp<SkSurface> backBuffer;
SkMatrix preTransform;
if (mHardwareBuffer) {
@@ -103,6 +103,7 @@
// Draw visual debugging features
if (CC_UNLIKELY(Properties::showDirtyRegions ||
ProfileType::None != Properties::getProfileType())) {
+ std::scoped_lock lock(profilerLock);
SkCanvas* profileCanvas = backBuffer->getCanvas();
SkAutoCanvasRestore saver(profileCanvas, true);
profileCanvas->concat(mVkSurface->getCurrentPreTransform());
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 284cde5..37b86f1 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -42,7 +42,8 @@
const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
const std::vector<sp<RenderNode> >& renderNodes, FrameInfoVisualizer* profiler,
- const renderthread::HardwareBufferRenderParams& bufferParams) override;
+ const renderthread::HardwareBufferRenderParams& bufferParams,
+ std::mutex& profilerLock) override;
GrSurfaceOrigin getSurfaceOrigin() override { return kTopLeft_GrSurfaceOrigin; }
bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
FrameInfo* currentFrameInfo, bool* requireSwap) override;
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index babce88..f695556 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -277,7 +277,7 @@
const nsecs_t now = systemTime(CLOCK_MONOTONIC);
// Rate limiting
- if ((now - mLastDeferredCleanup) < 25_ms) {
+ if ((now - mLastDeferredCleanup) > 25_ms) {
mLastDeferredCleanup = now;
const nsecs_t frameCompleteNanos = mFrameCompletions[0];
const nsecs_t frameDiffNanos = now - frameCompleteNanos;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 618c896..bbbb0ca 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -592,14 +592,10 @@
{
// FrameInfoVisualizer accesses the frame events, which cannot be mutated mid-draw
// or it can lead to memory corruption.
- // This lock is overly broad, but it's the quickest fix since this mutex is otherwise
- // not visible to IRenderPipeline much less FrameInfoVisualizer. And since this is
- // the thread we're primarily concerned about being responsive, this being too broad
- // shouldn't pose a performance issue.
- std::scoped_lock lock(mFrameMetricsReporterMutex);
drawResult = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry,
&mLayerUpdateQueue, mContentDrawBounds, mOpaque,
- mLightInfo, mRenderNodes, &(profiler()), mBufferParams);
+ mLightInfo, mRenderNodes, &(profiler()), mBufferParams,
+ profilerLock());
}
uint64_t frameCompleteNr = getFrameNumber();
@@ -729,7 +725,7 @@
mCurrentFrameInfo->markFrameCompleted();
mCurrentFrameInfo->set(FrameInfoIndex::GpuCompleted)
= mCurrentFrameInfo->get(FrameInfoIndex::FrameCompleted);
- std::scoped_lock lock(mFrameMetricsReporterMutex);
+ std::scoped_lock lock(mFrameInfoMutex);
mJankTracker.finishFrame(*mCurrentFrameInfo, mFrameMetricsReporter, frameCompleteNr,
mSurfaceControlGenerationId);
}
@@ -758,7 +754,7 @@
void CanvasContext::reportMetricsWithPresentTime() {
{ // acquire lock
- std::scoped_lock lock(mFrameMetricsReporterMutex);
+ std::scoped_lock lock(mFrameInfoMutex);
if (mFrameMetricsReporter == nullptr) {
return;
}
@@ -793,7 +789,7 @@
forthBehind->set(FrameInfoIndex::DisplayPresentTime) = presentTime;
{ // acquire lock
- std::scoped_lock lock(mFrameMetricsReporterMutex);
+ std::scoped_lock lock(mFrameInfoMutex);
if (mFrameMetricsReporter != nullptr) {
mFrameMetricsReporter->reportFrameMetrics(forthBehind->data(), true /*hasPresentTime*/,
frameNumber, surfaceControlId);
@@ -802,7 +798,7 @@
}
void CanvasContext::addFrameMetricsObserver(FrameMetricsObserver* observer) {
- std::scoped_lock lock(mFrameMetricsReporterMutex);
+ std::scoped_lock lock(mFrameInfoMutex);
if (mFrameMetricsReporter.get() == nullptr) {
mFrameMetricsReporter.reset(new FrameMetricsReporter());
}
@@ -816,7 +812,7 @@
}
void CanvasContext::removeFrameMetricsObserver(FrameMetricsObserver* observer) {
- std::scoped_lock lock(mFrameMetricsReporterMutex);
+ std::scoped_lock lock(mFrameInfoMutex);
if (mFrameMetricsReporter.get() != nullptr) {
mFrameMetricsReporter->removeObserver(observer);
if (!mFrameMetricsReporter->hasObservers()) {
@@ -853,7 +849,7 @@
FrameInfo* frameInfo = instance->getFrameInfoFromLast4(frameNumber, surfaceControlId);
if (frameInfo != nullptr) {
- std::scoped_lock lock(instance->mFrameMetricsReporterMutex);
+ std::scoped_lock lock(instance->mFrameInfoMutex);
frameInfo->set(FrameInfoIndex::FrameCompleted) = std::max(gpuCompleteTime,
frameInfo->get(FrameInfoIndex::SwapBuffersCompleted));
frameInfo->set(FrameInfoIndex::GpuCompleted) = std::max(
@@ -1035,6 +1031,7 @@
if (dirty->isEmpty()) {
dirty->setIWH(frame.width(), frame.height());
+ return *dirty;
}
// At this point dirty is the area of the window to update. However,
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 32ac5af..3978fbc 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -161,6 +161,7 @@
void notifyFramePending();
FrameInfoVisualizer& profiler() { return mProfiler; }
+ std::mutex& profilerLock() { return mFrameInfoMutex; }
void dumpFrames(int fd);
void resetFrameStats();
@@ -340,8 +341,8 @@
JankTracker mJankTracker;
FrameInfoVisualizer mProfiler;
std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter
- GUARDED_BY(mFrameMetricsReporterMutex);
- std::mutex mFrameMetricsReporterMutex;
+ GUARDED_BY(mFrameInfoMutex);
+ std::mutex mFrameInfoMutex;
std::set<RenderNode*> mPrefetchedLayers;
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 6c2cb9d..023c29a 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -67,7 +67,8 @@
const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
const std::vector<sp<RenderNode>>& renderNodes,
FrameInfoVisualizer* profiler,
- const HardwareBufferRenderParams& bufferParams) = 0;
+ const HardwareBufferRenderParams& bufferParams,
+ std::mutex& profilerLock) = 0;
virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
virtual DeferredLayerUpdater* createTextureLayer() = 0;
diff --git a/libs/incident/libincident.map.txt b/libs/incident/libincident.map.txt
index f75ccea..d8650e1 100644
--- a/libs/incident/libincident.map.txt
+++ b/libs/incident/libincident.map.txt
@@ -1,15 +1,15 @@
LIBINCIDENT {
global:
- AIncidentReportArgs_init; # systemapi # introduced=30
- AIncidentReportArgs_clone; # systemapi # introduced=30
- AIncidentReportArgs_delete; # systemapi # introduced=30
- AIncidentReportArgs_setAll; # systemapi # introduced=30
- AIncidentReportArgs_setPrivacyPolicy; # systemapi # introduced=30
- AIncidentReportArgs_addSection; # systemapi # introduced=30
- AIncidentReportArgs_setReceiverPackage; # systemapi # introduced=30
- AIncidentReportArgs_setReceiverClass; # systemapi # introduced=30
- AIncidentReportArgs_addHeader; # systemapi # introduced=30
- AIncidentReportArgs_takeReport; # systemapi # introduced=30
+ AIncidentReportArgs_init; # systemapi introduced=30
+ AIncidentReportArgs_clone; # systemapi introduced=30
+ AIncidentReportArgs_delete; # systemapi introduced=30
+ AIncidentReportArgs_setAll; # systemapi introduced=30
+ AIncidentReportArgs_setPrivacyPolicy; # systemapi introduced=30
+ AIncidentReportArgs_addSection; # systemapi introduced=30
+ AIncidentReportArgs_setReceiverPackage; # systemapi introduced=30
+ AIncidentReportArgs_setReceiverClass; # systemapi introduced=30
+ AIncidentReportArgs_addHeader; # systemapi introduced=30
+ AIncidentReportArgs_takeReport; # systemapi introduced=30
local:
*;
};
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index 9211c53..65cc1c4 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -31,7 +31,7 @@
* device at the boundary of the audio system.
* In addition to base audio port attributes, the device descriptor contains:
* - the device type (e.g AudioManager.DEVICE_OUT_SPEAKER)
- * - the device address (e.g MAC adddress for AD2P sink).
+ * - the device address (e.g MAC address for AD2P sink).
* @see AudioPort
* @hide
*/
diff --git a/media/java/android/media/AudioHalVersionInfo.java b/media/java/android/media/AudioHalVersionInfo.java
index 985a758..472cb3f 100644
--- a/media/java/android/media/AudioHalVersionInfo.java
+++ b/media/java/android/media/AudioHalVersionInfo.java
@@ -75,11 +75,13 @@
/**
* List of all valid Audio HAL versions. This list need to be in sync with sAudioHALVersions
- * defined in frameworks/av/media/libaudiohal/FactoryHalHidl.cpp.
+ * defined in frameworks/av/media/libaudiohal/FactoryHal.cpp.
+ *
+ * Note: update {@link android.media.audio.cts.AudioHalVersionInfoTest} CTS accordingly if
+ * there is a change to supported versions.
*/
- // TODO: add AIDL_1_0 with sAudioHALVersions.
public static final @NonNull List<AudioHalVersionInfo> VERSIONS =
- List.of(HIDL_7_1, HIDL_7_0, HIDL_6_0, HIDL_5_0, HIDL_4_0);
+ List.of(AIDL_1_0, HIDL_7_1, HIDL_7_0, HIDL_6_0, HIDL_5_0);
private static final String TAG = "AudioHalVersionInfo";
private AudioHalVersion mHalVersion = new AudioHalVersion();
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index b7c97208..5b479b5 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -16,7 +16,13 @@
package android.media;
+import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE;
+import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST;
+
+import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME;
+
import android.Manifest;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -43,6 +49,7 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
@@ -52,6 +59,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
@@ -1824,6 +1832,7 @@
private static final String EOS_AND_DECODE_ONLY_ERROR_MESSAGE = "An input buffer cannot have "
+ "both BUFFER_FLAG_END_OF_STREAM and BUFFER_FLAG_DECODE_ONLY flags";
private static final int CB_CRYPTO_ERROR = 6;
+ private static final int CB_LARGE_FRAME_OUTPUT_AVAILABLE = 7;
private class EventHandler extends Handler {
private MediaCodec mCodec;
@@ -1945,6 +1954,39 @@
break;
}
+ case CB_LARGE_FRAME_OUTPUT_AVAILABLE:
+ {
+ int index = msg.arg2;
+ ArrayDeque<BufferInfo> infos = (ArrayDeque<BufferInfo>)msg.obj;
+ synchronized(mBufferLock) {
+ switch (mBufferMode) {
+ case BUFFER_MODE_LEGACY:
+ validateOutputByteBuffersLocked(mCachedOutputBuffers,
+ index, infos);
+ break;
+ case BUFFER_MODE_BLOCK:
+ while (mOutputFrames.size() <= index) {
+ mOutputFrames.add(null);
+ }
+ OutputFrame frame = mOutputFrames.get(index);
+ if (frame == null) {
+ frame = new OutputFrame(index);
+ mOutputFrames.set(index, frame);
+ }
+ frame.setBufferInfos(infos);
+ frame.setAccessible(true);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Unrecognized buffer mode: for large frame output");
+ }
+ }
+ mCallback.onOutputBuffersAvailable(
+ mCodec, index, infos);
+
+ break;
+ }
+
case CB_ERROR:
{
mCallback.onError(mCodec, (MediaCodec.CodecException) msg.obj);
@@ -2172,6 +2214,18 @@
*/
public static final int CONFIGURE_FLAG_USE_CRYPTO_ASYNC = 4;
+ /**
+ * Configure the codec with a detached output surface.
+ * <p>
+ * This flag is only defined for a video decoder. MediaCodec
+ * configured with this flag will be in Surface mode even though
+ * the surface parameter is null.
+ *
+ * @see detachOutputSurface
+ */
+ @FlaggedApi(FLAG_NULL_OUTPUT_SURFACE)
+ public static final int CONFIGURE_FLAG_DETACHED_SURFACE = 8;
+
/** @hide */
@IntDef(
flag = true,
@@ -2354,6 +2408,31 @@
private native void native_setSurface(@NonNull Surface surface);
/**
+ * Detach the current output surface of a codec.
+ * <p>
+ * Detaches the currently associated output Surface from the
+ * MediaCodec decoder. This allows the SurfaceView or other
+ * component holding the Surface to be safely destroyed or
+ * modified without affecting the decoder's operation. After
+ * calling this method (and after it returns), the decoder will
+ * enter detached-Surface mode and will no longer render
+ * output.
+ *
+ * @throws IllegalStateException if the codec was not
+ * configured in surface mode.
+ * @see CONFIGURE_FLAG_DETACHED_SURFACE
+ */
+ @FlaggedApi(FLAG_NULL_OUTPUT_SURFACE)
+ public void detachOutputSurface() {
+ if (!mHasSurface) {
+ throw new IllegalStateException("codec was not configured for an output surface");
+ }
+ // note: we still have a surface in detached mode, so keep mHasSurface
+ // we also technically allow calling detachOutputSurface multiple times in a row
+ // native_detachSurface();
+ }
+
+ /**
* Create a persistent input surface that can be used with codecs that normally have an input
* surface, such as video encoders. A persistent input can be reused by subsequent
* {@link MediaCodec} or {@link MediaRecorder} instances, but can only be used by at
@@ -2836,11 +2915,72 @@
}
}
+ /**
+ * Submit multiple access units to the codec along with multiple
+ * {@link MediaCodec.BufferInfo} describing the contents of the buffer. This method
+ * is supported only in asynchronous mode. While this method can be used for all codecs,
+ * it is meant for buffer batching, which is only supported by codecs that advertise
+ * FEATURE_MultipleFrames. Other codecs will not output large output buffers via
+ * onOutputBuffersAvailable, and instead will output single-access-unit output via
+ * onOutputBufferAvailable.
+ * <p>
+ * Output buffer size can be configured using the following MediaFormat keys.
+ * {@link MediaFormat#KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE} and
+ * {@link MediaFormat#KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE}.
+ * Details for each access unit present in the buffer should be described using
+ * {@link MediaCodec.BufferInfo}. Access units must be laid out contiguously (without any gaps)
+ * and in order. Multiple access units in the output if present, will be available in
+ * {@link Callback#onOutputBuffersAvailable} or {@link Callback#onOutputBufferAvailable}
+ * in case of single-access-unit output or when output does not contain any buffers,
+ * such as flags.
+ * <p>
+ * All other details for populating {@link MediaCodec.BufferInfo} is the same as described in
+ * {@link #queueInputBuffer}.
+ *
+ * @param index The index of a client-owned input buffer previously returned
+ * in a call to {@link #dequeueInputBuffer}.
+ * @param bufferInfos ArrayDeque of {@link MediaCodec.BufferInfo} that describes the
+ * contents in the buffer. The ArrayDeque and the BufferInfo objects provided
+ * can be recycled by the caller for re-use.
+ * @throws IllegalStateException if not in the Executing state or not in asynchronous mode.
+ * @throws MediaCodec.CodecException upon codec error.
+ * @throws IllegalArgumentException upon if bufferInfos is empty, contains null, or if the
+ * access units are not contiguous.
+ * @throws CryptoException if a crypto object has been specified in
+ * {@link #configure}
+ */
+ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
+ public final void queueInputBuffers(
+ int index,
+ @NonNull ArrayDeque<BufferInfo> bufferInfos) {
+ synchronized(mBufferLock) {
+ if (mBufferMode == BUFFER_MODE_BLOCK) {
+ throw new IncompatibleWithBlockModelException("queueInputBuffers() "
+ + "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. "
+ + "Please use getQueueRequest() to queue buffers");
+ }
+ invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
+ mDequeuedInputBuffers.remove(index);
+ }
+ try {
+ native_queueInputBuffers(
+ index, bufferInfos.toArray());
+ } catch (CryptoException | IllegalStateException | IllegalArgumentException e) {
+ revalidateByteBuffer(mCachedInputBuffers, index, true /* input */);
+ throw e;
+ }
+ }
+
private native final void native_queueInputBuffer(
int index,
int offset, int size, long presentationTimeUs, int flags)
throws CryptoException;
+ private native final void native_queueInputBuffers(
+ int index,
+ @NonNull Object[] infos)
+ throws CryptoException, CodecException;
+
public static final int CRYPTO_MODE_UNENCRYPTED = 0;
public static final int CRYPTO_MODE_AES_CTR = 1;
public static final int CRYPTO_MODE_AES_CBC = 2;
@@ -3110,6 +3250,51 @@
}
}
+ /**
+ * Similar to {@link #queueInputBuffers queueInputBuffers} but submits multiple access units
+ * in a buffer that is potentially encrypted.
+ * <strong>Check out further notes at {@link #queueInputBuffers queueInputBuffers}.</strong>
+ *
+ * @param index The index of a client-owned input buffer previously returned
+ * in a call to {@link #dequeueInputBuffer}.
+ * @param bufferInfos ArrayDeque of {@link MediaCodec.BufferInfo} that describes the
+ * contents in the buffer. The ArrayDeque and the BufferInfo objects provided
+ * can be recycled by the caller for re-use.
+ * @param cryptoInfos ArrayDeque of {@link MediaCodec.CryptoInfo} objects to facilitate the
+ * decryption of the contents. The ArrayDeque and the CryptoInfo objects
+ * provided can be reused immediately after the call returns. These objects
+ * should correspond to bufferInfo objects to ensure correct decryption.
+ * @throws IllegalStateException if not in the Executing state or not in asynchronous mode.
+ * @throws MediaCodec.CodecException upon codec error.
+ * @throws IllegalArgumentException upon if bufferInfos is empty, contains null, or if the
+ * access units are not contiguous.
+ * @throws CryptoException if an error occurs while attempting to decrypt the buffer.
+ * An error code associated with the exception helps identify the
+ * reason for the failure.
+ */
+ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
+ public final void queueSecureInputBuffers(
+ int index,
+ @NonNull ArrayDeque<BufferInfo> bufferInfos,
+ @NonNull ArrayDeque<CryptoInfo> cryptoInfos) {
+ synchronized(mBufferLock) {
+ if (mBufferMode == BUFFER_MODE_BLOCK) {
+ throw new IncompatibleWithBlockModelException("queueSecureInputBuffers() "
+ + "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. "
+ + "Please use getQueueRequest() to queue buffers");
+ }
+ invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
+ mDequeuedInputBuffers.remove(index);
+ }
+ try {
+ native_queueSecureInputBuffers(
+ index, bufferInfos.toArray(), cryptoInfos.toArray());
+ } catch (CryptoException | IllegalStateException | IllegalArgumentException e) {
+ revalidateByteBuffer(mCachedInputBuffers, index, true /* input */);
+ throw e;
+ }
+ }
+
private native final void native_queueSecureInputBuffer(
int index,
int offset,
@@ -3117,6 +3302,11 @@
long presentationTimeUs,
int flags) throws CryptoException;
+ private native final void native_queueSecureInputBuffers(
+ int index,
+ @NonNull Object[] bufferInfos,
+ @NonNull Object[] cryptoInfos) throws CryptoException, CodecException;
+
/**
* Returns the index of an input buffer to be filled with valid data
* or -1 if no such buffer is currently available.
@@ -3362,7 +3552,37 @@
mLinearBlock = block;
mOffset = offset;
mSize = size;
- mCryptoInfo = null;
+ mCryptoInfos.clear();
+ return this;
+ }
+
+ /**
+ * Set a linear block that contain multiple non-encrypted access unit to this
+ * queue request. Exactly one buffer must be set for a queue request before
+ * calling {@link #queue}. Multiple access units if present must be laid out contiguously
+ * and without gaps and in order. An IllegalArgumentException will be thrown
+ * during {@link #queue} if access units are not laid out contiguously.
+ *
+ * @param block The linear block object
+ * @param infos Represents {@link MediaCodec.BufferInfo} objects to mark
+ * individual access-unit boundaries and the timestamps associated with it.
+ * @return this object
+ * @throws IllegalStateException if a buffer is already set
+ */
+ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
+ public @NonNull QueueRequest setMultiFrameLinearBlock(
+ @NonNull LinearBlock block,
+ @NonNull ArrayDeque<BufferInfo> infos) {
+ if (!isAccessible()) {
+ throw new IllegalStateException("The request is stale");
+ }
+ if (mLinearBlock != null || mHardwareBuffer != null) {
+ throw new IllegalStateException("Cannot set block twice");
+ }
+ mLinearBlock = block;
+ mBufferInfos.clear();
+ mBufferInfos.addAll(infos);
+ mCryptoInfos.clear();
return this;
}
@@ -3396,7 +3616,44 @@
mLinearBlock = block;
mOffset = offset;
mSize = size;
- mCryptoInfo = cryptoInfo;
+ mCryptoInfos.clear();
+ mCryptoInfos.add(cryptoInfo);
+ return this;
+ }
+
+ /**
+ * Set an encrypted linear block to this queue request. Exactly one buffer must be
+ * set for a queue request before calling {@link #queue}. The block can contain multiple
+ * access units and if present should be laid out contiguously and without gaps.
+ *
+ * @param block The linear block object
+ * @param bufferInfos ArrayDeque of {@link MediaCodec.BufferInfo} that describes the
+ * contents in the buffer. The ArrayDeque and the BufferInfo objects
+ * provided can be recycled by the caller for re-use.
+ * @param cryptoInfos ArrayDeque of {@link MediaCodec.CryptoInfo} that describes the
+ * structure of the encrypted input samples. The ArrayDeque and the
+ * BufferInfo objects provided can be recycled by the caller for re-use.
+ * @return this object
+ * @throws IllegalStateException if a buffer is already set
+ * @throws IllegalArgumentException upon if bufferInfos is empty, contains null, or if the
+ * access units are not contiguous.
+ */
+ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
+ public @NonNull QueueRequest setMultiFrameEncryptedLinearBlock(
+ @NonNull LinearBlock block,
+ @NonNull ArrayDeque<MediaCodec.BufferInfo> bufferInfos,
+ @NonNull ArrayDeque<MediaCodec.CryptoInfo> cryptoInfos) {
+ if (!isAccessible()) {
+ throw new IllegalStateException("The request is stale");
+ }
+ if (mLinearBlock != null || mHardwareBuffer != null) {
+ throw new IllegalStateException("Cannot set block twice");
+ }
+ mLinearBlock = block;
+ mBufferInfos.clear();
+ mBufferInfos.addAll(bufferInfos);
+ mCryptoInfos.clear();
+ mCryptoInfos.addAll(cryptoInfos);
return this;
}
@@ -3577,10 +3834,20 @@
throw new IllegalStateException("No block is set");
}
setAccessible(false);
+ if (mBufferInfos.isEmpty()) {
+ BufferInfo info = new BufferInfo();
+ info.size = mSize;
+ info.offset = mOffset;
+ info.presentationTimeUs = mPresentationTimeUs;
+ info.flags = mFlags;
+ mBufferInfos.add(info);
+ }
if (mLinearBlock != null) {
+
mCodec.native_queueLinearBlock(
- mIndex, mLinearBlock, mOffset, mSize, mCryptoInfo,
- mPresentationTimeUs, mFlags,
+ mIndex, mLinearBlock,
+ mCryptoInfos.isEmpty() ? null : mCryptoInfos.toArray(),
+ mBufferInfos.toArray(),
mTuningKeys, mTuningValues);
} else if (mHardwareBuffer != null) {
mCodec.native_queueHardwareBuffer(
@@ -3594,10 +3861,11 @@
mLinearBlock = null;
mOffset = 0;
mSize = 0;
- mCryptoInfo = null;
mHardwareBuffer = null;
mPresentationTimeUs = 0;
mFlags = 0;
+ mBufferInfos.clear();
+ mCryptoInfos.clear();
mTuningKeys.clear();
mTuningValues.clear();
return this;
@@ -3617,10 +3885,11 @@
private LinearBlock mLinearBlock = null;
private int mOffset = 0;
private int mSize = 0;
- private MediaCodec.CryptoInfo mCryptoInfo = null;
private HardwareBuffer mHardwareBuffer = null;
private long mPresentationTimeUs = 0;
private @BufferFlag int mFlags = 0;
+ private final ArrayDeque<BufferInfo> mBufferInfos = new ArrayDeque<>();
+ private final ArrayDeque<CryptoInfo> mCryptoInfos = new ArrayDeque<>();
private final ArrayList<String> mTuningKeys = new ArrayList<>();
private final ArrayList<Object> mTuningValues = new ArrayList<>();
@@ -3630,11 +3899,8 @@
private native void native_queueLinearBlock(
int index,
@NonNull LinearBlock block,
- int offset,
- int size,
- @Nullable CryptoInfo cryptoInfo,
- long presentationTimeUs,
- int flags,
+ @Nullable Object[] cryptoInfos,
+ @NonNull Object[] bufferInfos,
@NonNull ArrayList<String> keys,
@NonNull ArrayList<Object> values);
@@ -4048,6 +4314,27 @@
}
}
+ private void validateOutputByteBuffersLocked(
+ @Nullable ByteBuffer[] buffers, int index, @NonNull ArrayDeque<BufferInfo> infoDeque) {
+ Optional<BufferInfo> minInfo = infoDeque.stream().min(
+ (info1, info2) -> Integer.compare(info1.offset, info2.offset));
+ Optional<BufferInfo> maxInfo = infoDeque.stream().max(
+ (info1, info2) -> Integer.compare(info1.offset, info2.offset));
+ if (buffers == null) {
+ if (index >= 0) {
+ mValidOutputIndices.set(index);
+ }
+ } else if (index >= 0 && index < buffers.length) {
+ ByteBuffer buffer = buffers[index];
+ if (buffer != null && minInfo.isPresent() && maxInfo.isPresent()) {
+ buffer.setAccessible(true);
+ buffer.limit(maxInfo.get().offset + maxInfo.get().size);
+ buffer.position(minInfo.get().offset);
+ }
+ }
+
+ }
+
private void validateOutputByteBufferLocked(
@Nullable ByteBuffer[] buffers, int index, @NonNull BufferInfo info) {
if (buffers == null) {
@@ -4405,6 +4692,22 @@
return mFlags;
}
+ /*
+ * Returns the BufferInfos associated with this OutputFrame. These BufferInfos
+ * describes the access units present in the OutputFrame. Access units are laid
+ * out contiguously without gaps and in order.
+ */
+ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
+ public @NonNull ArrayDeque<BufferInfo> getBufferInfos() {
+ if (mBufferInfos.isEmpty()) {
+ // single BufferInfo could be present.
+ BufferInfo bufferInfo = new BufferInfo();
+ bufferInfo.set(0, 0, mPresentationTimeUs, mFlags);
+ mBufferInfos.add(bufferInfo);
+ }
+ return mBufferInfos;
+ }
+
/**
* Returns a read-only {@link MediaFormat} for this frame. The returned
* object is valid only until the client calls {@link MediaCodec#releaseOutputBuffer}.
@@ -4430,6 +4733,7 @@
mLinearBlock = null;
mHardwareBuffer = null;
mFormat = null;
+ mBufferInfos.clear();
mChangedKeys.clear();
mKeySet.clear();
mLoaded = false;
@@ -4448,6 +4752,11 @@
mFlags = info.flags;
}
+ void setBufferInfos(ArrayDeque<BufferInfo> infos) {
+ mBufferInfos.clear();
+ mBufferInfos.addAll(infos);
+ }
+
boolean isLoaded() {
return mLoaded;
}
@@ -4462,6 +4771,7 @@
private long mPresentationTimeUs = 0;
private @BufferFlag int mFlags = 0;
private MediaFormat mFormat = null;
+ private final ArrayDeque<BufferInfo> mBufferInfos = new ArrayDeque<>();
private final ArrayList<String> mChangedKeys = new ArrayList<>();
private final Set<String> mKeySet = new HashSet<>();
private boolean mAccessible = false;
@@ -4765,6 +5075,68 @@
public static final String PARAMETER_KEY_TUNNEL_PEEK = "tunnel-peek";
/**
+ * Set the region of interest as QpOffset-Map on the next queued input frame.
+ * <p>
+ * The associated value is a byte array containing quantization parameter (QP) offsets in
+ * raster scan order for the entire frame at 16x16 granularity. The size of the byte array
+ * shall be ((frame_width + 15) / 16) * ((frame_height + 15) / 16), where frame_width and
+ * frame_height correspond to width and height configured using {@link MediaFormat#KEY_WIDTH}
+ * and {@link MediaFormat#KEY_HEIGHT} keys respectively. During encoding, if the coding unit
+ * size is larger than 16x16, then the qpOffset information of all 16x16 blocks that
+ * encompass the coding unit is combined and used. The QP of target block will be calculated
+ * as 'frameQP + offsetQP'. If the result exceeds minQP or maxQP configured then the value
+ * may be clamped. Negative offset results in blocks encoded at lower QP than frame QP and
+ * positive offsets will result in encoding blocks at higher QP than frame QP. If the areas
+ * of negative QP and positive QP are chosen wisely, the overall viewing experience can be
+ * improved.
+ * <p>
+ * If byte array size is too small than the expected size, components may ignore the
+ * configuration silently. If the byte array exceeds the expected size, components shall use
+ * the initial portion and ignore the rest.
+ * <p>
+ * The scope of this key is throughout the encoding session until it is reconfigured during
+ * running state.
+ * <p>
+ * @see #setParameters(Bundle)
+ */
+ @FlaggedApi(FLAG_REGION_OF_INTEREST)
+ public static final String PARAMETER_KEY_QP_OFFSET_MAP = "qp-offset-map";
+
+ /**
+ * Set the region of interest as QpOffset-Rects on the next queued input frame.
+ * <p>
+ * The associated value is a String in the format "Top1,Left1-Bottom1,Right1=Offset1;Top2,
+ * Left2-Bottom2,Right2=Offset2;...". Co-ordinates (Top, Left), (Top, Right), (Bottom, Left)
+ * and (Bottom, Right) form the vertices of bounding box of region of interest in pixels.
+ * Pixel (0, 0) points to the top-left corner of the frame. Offset is the suggested
+ * quantization parameter (QP) offset of the blocks in the bounding box. The bounding box
+ * will get stretched outwards to align to LCU boundaries during encoding. The Qp Offset is
+ * integral and shall be in the range [-128, 127]. The QP of target block will be calculated
+ * as frameQP + offsetQP. If the result exceeds minQP or maxQP configured then the value may
+ * be clamped. Negative offset results in blocks encoded at lower QP than frame QP and
+ * positive offsets will result in blocks encoded at higher QP than frame QP. If the areas of
+ * negative QP and positive QP are chosen wisely, the overall viewing experience can be
+ * improved.
+ * <p>
+ * If Roi rect is not valid that is bounding box width is < 0 or bounding box height is < 0,
+ * components may ignore the configuration silently. If Roi rect extends outside frame
+ * boundaries, then rect shall be clamped to the frame boundaries.
+ * <p>
+ * The scope of this key is throughout the encoding session until it is reconfigured during
+ * running state.
+ * <p>
+ * The maximum number of contours (rectangles) that can be specified for a given input frame
+ * is device specific. Implementations will drop/ignore the rectangles that are beyond their
+ * supported limit. Hence it is preferable to place the rects in descending order of
+ * importance. Transitively, if the bounding boxes overlap, then the most preferred
+ * rectangle's qp offset (earlier rectangle qp offset) will be used to quantize the block.
+ * <p>
+ * @see #setParameters(Bundle)
+ */
+ @FlaggedApi(FLAG_REGION_OF_INTEREST)
+ public static final String PARAMETER_KEY_QP_OFFSET_RECTS = "qp-offset-rects";
+
+ /**
* Communicate additional parameter changes to the component instance.
* <b>Note:</b> Some of these parameter changes may silently fail to apply.
*
@@ -5170,6 +5542,32 @@
@NonNull MediaCodec codec, int index, @NonNull BufferInfo info);
/**
+ * Called when multiple access-units are available in the output.
+ *
+ * @param codec The MediaCodec object.
+ * @param index The index of the available output buffer.
+ * @param infos Infos describing the available output buffer {@link MediaCodec.BufferInfo}.
+ * Access units present in the output buffer are laid out contiguously
+ * without gaps and in order.
+ */
+ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
+ public void onOutputBuffersAvailable(
+ @NonNull MediaCodec codec, int index, @NonNull ArrayDeque<BufferInfo> infos) {
+ /*
+ * This callback returns multiple BufferInfos when codecs are configured to operate on
+ * large audio frame. Since at this point, we have a single large buffer, returning
+ * each BufferInfo using
+ * {@link Callback#onOutputBufferAvailable onOutputBufferAvailable} may cause the
+ * index to be released to the codec using {@link MediaCodec#releaseOutputBuffer}
+ * before all BuffersInfos can be returned to the client.
+ * Hence this callback is required to be implemented or else an exception is thrown.
+ */
+ throw new IllegalStateException(
+ "Client must override onOutputBuffersAvailable when codec is " +
+ "configured to operate with multiple access units");
+ }
+
+ /**
* Called when the MediaCodec encountered an error
*
* @param codec The MediaCodec object.
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 88b9643..1e7bc47 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -18,7 +18,14 @@
import static android.media.Utils.intersectSortedDistinctRanges;
import static android.media.Utils.sortDistinctRanges;
+import static android.media.codec.Flags.FLAG_DYNAMIC_COLOR_ASPECTS;
+import static android.media.codec.Flags.FLAG_HLG_EDITING;
+import static android.media.codec.Flags.FLAG_IN_PROCESS_SW_AUDIO_CODEC;
+import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE;
+import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST;
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -35,6 +42,8 @@
import android.util.Rational;
import android.util.Size;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -692,6 +701,99 @@
public static final String FEATURE_HdrEditing = "hdr-editing";
/**
+ * <b>video encoder only</b>: codec supports HLG editing.
+ * <p>
+ * HLG editing support means that the codec accepts 10-bit HDR
+ * input surface in both YUV and RGB pixel format. This feature
+ * is only meaningful when using a 10-bit (HLG) profile and
+ * 10-bit input.
+ * <p>
+ * This feature implies that the codec is capable of encoding
+ * 10-bit format, and that it supports RGBA_1010102 as
+ * well as P010, and optionally RGBA_FP16 input formats.
+ * <p>
+ * The difference between this feature and {@link
+ * FEATURE_HdrEditing} is that HLG does not require the
+ * generation of HDR metadata and does not use an explicit HDR
+ * profile.
+ */
+ @SuppressLint("AllUpper")
+ @FlaggedApi(FLAG_HLG_EDITING)
+ public static final String FEATURE_HlgEditing = "hlg-editing";
+
+ /**
+ * <b>video decoder only</b>: codec supports dynamically
+ * changing color aspects.
+ * <p>
+ * If true, the codec can propagate color aspect changes during
+ * decoding. This is only meaningful at session boundaries, e.g.
+ * upon processing Picture Parameter Sets prior to a new IDR.
+ * The color aspects may come from the bitstream, or may be
+ * provided using {@link MediaCodec#setParameters} calls.
+ * <p>
+ * If the codec supports both 8-bit and 10-bit profiles, this
+ * feature means that the codec can dynamically switch between 8
+ * and 10-bit profiles, but this is restricted to Surface mode
+ * only.
+ * <p>
+ * If the device supports HDR transfer functions, switching
+ * between SDR and HDR transfer is also supported. Together with
+ * the previous clause this means that switching between SDR and
+ * HDR sessions are supported in Surface mode, as SDR is
+ * typically encoded at 8-bit and HDR at 10-bit.
+ */
+ @SuppressLint("AllUpper")
+ @FlaggedApi(FLAG_DYNAMIC_COLOR_ASPECTS)
+ public static final String FEATURE_DynamicColorAspects = "dynamic-color-aspects";
+
+ /**
+ * <b>video encoder only</b>: codec supports region of interest encoding.
+ * <p>
+ * RoI encoding support means the codec accepts information that specifies the relative
+ * importance of different portions of each video frame. This allows the encoder to
+ * separate a video frame into critical and non-critical regions, and use more bits
+ * (better quality) to represent the critical regions and de-prioritize non-critical
+ * regions. In other words, the encoder chooses a negative qp bias for the critical
+ * portions and a zero or positive qp bias for the non-critical portions.
+ * <p>
+ * At a basic level, if the encoder decides to encode each frame with a uniform
+ * quantization value 'qpFrame' and a 'qpBias' is chosen/suggested for an LCU of the
+ * frame, then the actual qp of the LCU will be 'qpFrame + qpBias', although this value
+ * can be clamped basing on the min-max configured qp bounds for the current encoding
+ * session.
+ * <p>
+ * In a shot, if a group of LCUs pan out quickly they can be marked as non-critical
+ * thereby enabling the encoder to reserve fewer bits during their encoding. Contrarily,
+ * LCUs that remain in shot for a prolonged duration can be encoded at better quality in
+ * one frame thereby setting-up an excellent long-term reference for all future frames.
+ * <p>
+ * Note that by offsetting the quantization of each LCU, the overall bit allocation will
+ * differ from the originally estimated bit allocation, and the encoder will adjust the
+ * frame quantization for subsequent frames to meet the bitrate target. An effective
+ * selection of critical regions can set-up a golden reference and this can compensate
+ * for the bit burden that was introduced due to encoding RoI's at better quality.
+ * On the other hand, an ineffective choice of critical regions might increase the
+ * quality of certain parts of the image but this can hamper quality in subsequent frames.
+ * <p>
+ * @see MediaCodec#PARAMETER_KEY_QP_OFFSET_MAP
+ * @see MediaCodec#PARAMETER_KEY_QP_OFFSET_RECTS
+ */
+ @SuppressLint("AllUpper")
+ @FlaggedApi(FLAG_REGION_OF_INTEREST)
+ public static final String FEATURE_Roi = "region-of-interest";
+
+ /**
+ * <b>video decoder only</b>: codec supports detaching the
+ * output surface when in Surface mode.
+ * <p> If true, the codec can be configured in Surface mode
+ * without an actual surface (in detached surface mode).
+ * @see MediaCodec#CONFIGURE_FLAG_DETACHED_SURFACE
+ */
+ @SuppressLint("AllUpper")
+ @FlaggedApi(FLAG_NULL_OUTPUT_SURFACE)
+ public static final String FEATURE_DetachedSurface = "detached-surface";
+
+ /**
* Query codec feature capabilities.
* <p>
* These features are supported to be used by the codec. These
@@ -712,29 +814,66 @@
return checkFeature(name, mFlagsRequired);
}
- private static final Feature[] decoderFeatures = {
- new Feature(FEATURE_AdaptivePlayback, (1 << 0), true),
- new Feature(FEATURE_SecurePlayback, (1 << 1), false),
- new Feature(FEATURE_TunneledPlayback, (1 << 2), false),
- new Feature(FEATURE_PartialFrame, (1 << 3), false),
- new Feature(FEATURE_FrameParsing, (1 << 4), false),
- new Feature(FEATURE_MultipleFrames, (1 << 5), false),
- new Feature(FEATURE_DynamicTimestamp, (1 << 6), false),
- new Feature(FEATURE_LowLatency, (1 << 7), true),
- // feature to exclude codec from REGULAR codec list
- new Feature(FEATURE_SpecialCodec, (1 << 30), false, true),
- };
+ // Flags are used for feature list creation so separate this into a private
+ // static class to delay reading the flags only when constructing the list.
+ private static class FeatureList {
+ private static Feature[] getDecoderFeatures() {
+ ArrayList<Feature> features = new ArrayList();
+ features.add(new Feature(FEATURE_AdaptivePlayback, (1 << 0), true));
+ features.add(new Feature(FEATURE_SecurePlayback, (1 << 1), false));
+ features.add(new Feature(FEATURE_TunneledPlayback, (1 << 2), false));
+ features.add(new Feature(FEATURE_PartialFrame, (1 << 3), false));
+ features.add(new Feature(FEATURE_FrameParsing, (1 << 4), false));
+ features.add(new Feature(FEATURE_MultipleFrames, (1 << 5), false));
+ features.add(new Feature(FEATURE_DynamicTimestamp, (1 << 6), false));
+ features.add(new Feature(FEATURE_LowLatency, (1 << 7), true));
+ if (android.media.codec.Flags.dynamicColorAspects()) {
+ features.add(new Feature(FEATURE_DynamicColorAspects, (1 << 8), true));
+ }
+ if (android.media.codec.Flags.nullOutputSurface()) {
+ features.add(new Feature(FEATURE_DetachedSurface, (1 << 9), true));
+ }
- private static final Feature[] encoderFeatures = {
- new Feature(FEATURE_IntraRefresh, (1 << 0), false),
- new Feature(FEATURE_MultipleFrames, (1 << 1), false),
- new Feature(FEATURE_DynamicTimestamp, (1 << 2), false),
- new Feature(FEATURE_QpBounds, (1 << 3), false),
- new Feature(FEATURE_EncodingStatistics, (1 << 4), false),
- new Feature(FEATURE_HdrEditing, (1 << 5), false),
- // feature to exclude codec from REGULAR codec list
- new Feature(FEATURE_SpecialCodec, (1 << 30), false, true),
- };
+ // feature to exclude codec from REGULAR codec list
+ features.add(new Feature(FEATURE_SpecialCodec, (1 << 30), false, true));
+
+ return features.toArray(new Feature[0]);
+ };
+
+ private static Feature[] decoderFeatures = getDecoderFeatures();
+
+ private static Feature[] getEncoderFeatures() {
+ ArrayList<Feature> features = new ArrayList();
+
+ features.add(new Feature(FEATURE_IntraRefresh, (1 << 0), false));
+ features.add(new Feature(FEATURE_MultipleFrames, (1 << 1), false));
+ features.add(new Feature(FEATURE_DynamicTimestamp, (1 << 2), false));
+ features.add(new Feature(FEATURE_QpBounds, (1 << 3), false));
+ features.add(new Feature(FEATURE_EncodingStatistics, (1 << 4), false));
+ features.add(new Feature(FEATURE_HdrEditing, (1 << 5), false));
+ if (android.media.codec.Flags.hlgEditing()) {
+ features.add(new Feature(FEATURE_HlgEditing, (1 << 6), true));
+ }
+ if (android.media.codec.Flags.regionOfInterest()) {
+ features.add(new Feature(FEATURE_Roi, (1 << 7), true));
+ }
+
+ // feature to exclude codec from REGULAR codec list
+ features.add(new Feature(FEATURE_SpecialCodec, (1 << 30), false, true));
+
+ return features.toArray(new Feature[0]);
+ };
+
+ private static Feature[] encoderFeatures = getEncoderFeatures();
+
+ public static Feature[] getFeatures(boolean isEncoder) {
+ if (isEncoder) {
+ return encoderFeatures;
+ } else {
+ return decoderFeatures;
+ }
+ }
+ }
/** @hide */
public String[] validFeatures() {
@@ -749,10 +888,7 @@
}
private Feature[] getValidFeatures() {
- if (!isEncoder()) {
- return decoderFeatures;
- }
- return encoderFeatures;
+ return FeatureList.getFeatures(isEncoder());
}
private boolean checkFeature(String name, int flags) {
@@ -1676,6 +1812,55 @@
}
}
+ /** @hide */
+ @IntDef(prefix = {"SECURITY_MODEL_"}, value = {
+ SECURITY_MODEL_SANDBOXED,
+ SECURITY_MODEL_MEMORY_SAFE,
+ SECURITY_MODEL_TRUSTED_CONTENT_ONLY,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SecurityModel {}
+
+ /**
+ * In this model the codec is running in a sandboxed process. Even if a
+ * malicious content was fed to the codecs in this model, the impact will
+ * be contained in the sandboxed process.
+ */
+ @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+ public static final int SECURITY_MODEL_SANDBOXED = 0;
+ /**
+ * In this model the codec is not running in a sandboxed process, but
+ * written in a memory-safe way. It typically means that the software
+ * implementation of the codec is written in a memory-safe language such
+ * as Rust.
+ */
+ @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+ public static final int SECURITY_MODEL_MEMORY_SAFE = 1;
+ /**
+ * In this model the codec is suitable only for trusted content where
+ * the input can be verified to be well-formed and no malicious actor
+ * can alter it. For example, codecs in this model are not suitable
+ * for arbitrary media downloaded from the internet or present in a user
+ * directory. On the other hand, they could be suitable for media encoded
+ * in the backend that the app developer wholly controls.
+ * <p>
+ * Codecs with this security model is not included in
+ * {@link MediaCodecList#REGULAR_CODECS}, but included in
+ * {@link MediaCodecList#ALL_CODECS}.
+ */
+ @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+ public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2;
+
+ /**
+ * Query the security model of the codec.
+ */
+ @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+ @SecurityModel
+ public int getSecurityModel() {
+ // TODO b/297922713 --- detect security model of out-of-sandbox codecs
+ return SECURITY_MODEL_SANDBOXED;
+ }
+
/**
* A class that supports querying the video capabilities of a codec.
*/
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 46db777..7b83842 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -16,6 +16,12 @@
package android.media;
+import static android.media.codec.Flags.FLAG_IN_PROCESS_SW_AUDIO_CODEC;
+
+import static com.android.media.codec.flags.Flags.FLAG_CODEC_IMPORTANCE;
+import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME;
+
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -118,6 +124,10 @@
* <tr><td>{@link #KEY_MPEGH_REFERENCE_CHANNEL_LAYOUT}</td>
* <td>Integer</td><td><b>decoder-only</b>, optional, if content is MPEG-H audio,
* specifies the preferred reference channel layout of the stream.</td></tr>
+ * <tr><td>{@link #KEY_MAX_BUFFER_BATCH_OUTPUT_SIZE}</td><td>Integer</td><td>optional, used with
+ * large audio frame support, specifies max size of output buffer in bytes.</td></tr>
+ * <tr><td>{@link #KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE}</td><td>Integer</td><td>optional,
+ * used with large audio frame support, specifies threshold output size in bytes.</td></tr>
* </table>
*
* Subtitle formats have the following keys:
@@ -456,6 +466,50 @@
public static final String KEY_MAX_INPUT_SIZE = "max-input-size";
/**
+ * A key describing the maximum output buffer size in bytes when using
+ * large buffer mode containing multiple access units.
+ *
+ * When not-set - codec functions with one access-unit per frame.
+ * When set less than the size of two access-units - will make codec
+ * operate in single access-unit per output frame.
+ * When set to a value too big - The component or the framework will
+ * override this value to a reasonable max size not exceeding typical
+ * 10 seconds of data (device dependent) when set to a value larger than
+ * that. The value final value used will be returned in the output format.
+ *
+ * The associated value is an integer
+ *
+ * @see FEATURE_MultipleFrames
+ */
+ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
+ public static final String KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE = "buffer-batch-max-output-size";
+
+ /**
+ * A key describing the threshold output size in bytes when using large buffer
+ * mode containing multiple access units.
+ *
+ * This is an optional parameter.
+ *
+ * If not set - the component can set this to a reasonable value.
+ * If set larger than max size, the components will
+ * clip this setting to maximum buffer batching output size.
+ *
+ * The component will return a partial output buffer if the output buffer reaches or
+ * surpass this limit.
+ *
+ * Threshold size should be always less or equal to KEY_MAX_BUFFER_BATCH_OUTPUT_SIZE.
+ * The final setting of this value as determined by the component will be returned
+ * in the output format
+ *
+ * The associated value is an integer
+ *
+ * @see FEATURE_MultipleFrames
+ */
+ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
+ public static final String KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE =
+ "buffer-batch-threshold-output-size";
+
+ /**
* A key describing the pixel aspect ratio width.
* The associated value is an integer
*/
@@ -1635,6 +1689,86 @@
*/
public static final String KEY_ALLOW_FRAME_DROP = "allow-frame-drop";
+ /**
+ * A key describing the desired codec importance for the application.
+ * <p>
+ * The associated value is a positive integer including zero.
+ * Higher value means lesser importance.
+ * <p>
+ * The resource manager may use the codec importance, along with other factors
+ * when reclaiming codecs from an application.
+ * The specifics of reclaim policy is device dependent, but specifying the codec importance,
+ * will allow the resource manager to prioritize reclaiming less important codecs
+ * (assigned higher values) from the (reclaim) requesting application first.
+ * So, the codec importance is only relevant within the context of that application.
+ * <p>
+ * The codec importance can be set:
+ * <ul>
+ * <li>through {@link MediaCodec#configure}. </li>
+ * <li>through {@link MediaCodec#setParameters} if the codec has been configured already,
+ * which allows the users to change the codec importance multiple times.
+ * </ul>
+ * Any change/update in codec importance is guaranteed upon the completion of the function call
+ * that sets the codec importance. So, in case of concurrent codec operations,
+ * make sure to wait for the change in codec importance, before using another codec.
+ * Note that unless specified, by default the codecs will have highest importance (of value 0).
+ *
+ */
+ @FlaggedApi(FLAG_CODEC_IMPORTANCE)
+ public static final String KEY_IMPORTANCE = "importance";
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_SECURITY_MODEL_"}, value = {
+ FLAG_SECURITY_MODEL_SANDBOXED,
+ FLAG_SECURITY_MODEL_MEMORY_SAFE,
+ FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SecurityModelFlag {}
+
+ /**
+ * Flag for {@link MediaCodecInfo#SECURITY_MODEL_SANDBOXED}.
+ */
+ @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+ public static final int FLAG_SECURITY_MODEL_SANDBOXED =
+ (1 << MediaCodecInfo.SECURITY_MODEL_SANDBOXED);
+ /**
+ * Flag for {@link MediaCodecInfo#SECURITY_MODEL_MEMORY_SAFE}.
+ */
+ @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+ public static final int FLAG_SECURITY_MODEL_MEMORY_SAFE =
+ (1 << MediaCodecInfo.SECURITY_MODEL_MEMORY_SAFE);
+ /**
+ * Flag for {@link MediaCodecInfo#SECURITY_MODEL_TRUSTED_CONTENT_ONLY}.
+ */
+ @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+ public static final int FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY =
+ (1 << MediaCodecInfo.SECURITY_MODEL_TRUSTED_CONTENT_ONLY);
+
+ /**
+ * A key describing the requested security model as flags.
+ * <p>
+ * The associated value is a flag of the following values:
+ * {@link FLAG_SECURITY_MODEL_SANDBOXED},
+ * {@link FLAG_SECURITY_MODEL_MEMORY_SAFE},
+ * {@link FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY}. The default value is
+ * {@link FLAG_SECURITY_MODEL_SANDBOXED}.
+ * <p>
+ * When passed to {@link MediaCodecList#findDecoderForFormat} or
+ * {@link MediaCodecList#findEncoderForFormat}, MediaCodecList filters
+ * the security model of the codecs according to this flag value.
+ * <p>
+ * When passed to {@link MediaCodec#configure}, MediaCodec verifies
+ * the security model matches the flag value passed, and throws
+ * {@link java.lang.IllegalArgumentException} if the model does not match.
+ * <p>
+ * @see MediaCodecInfo#getSecurityModel
+ * @see MediaCodecList#findDecoderForFormat
+ * @see MediaCodecList#findEncoderForFormat
+ */
+ @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
+ public static final String KEY_SECURITY_MODEL = "security-model";
+
/* package private */ MediaFormat(@NonNull Map<String, Object> map) {
mMap = map;
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 1ee5aa3..0d9acf2 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1156,6 +1156,7 @@
setDataSource(afd);
return true;
} catch (NullPointerException | SecurityException | IOException ex) {
+ Log.w(TAG, "Error setting data source via ContentResolver", ex);
return false;
}
}
diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS
index 058c5be..5d470ae 100644
--- a/media/java/android/media/OWNERS
+++ b/media/java/android/media/OWNERS
@@ -14,3 +14,5 @@
# Haptics team also works on Ringtone
per-file *Ringtone* = file:/services/core/java/com/android/server/vibrator/OWNERS
+
+per-file flags/projection.aconfig = file:projection/OWNERS
\ No newline at end of file
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index ef90bf9..8396005 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -163,6 +163,13 @@
static struct {
jclass clazz;
jmethodID ctorId;
+ jmethodID sizeId;
+ jmethodID addId;
+} gArrayDequeInfo;
+
+static struct {
+ jclass clazz;
+ jmethodID ctorId;
jmethodID setInternalStateId;
jfieldID contextId;
jfieldID validId;
@@ -200,8 +207,14 @@
jfieldID queueRequestIndexID;
jfieldID outputFrameLinearBlockID;
jfieldID outputFrameHardwareBufferID;
+ jfieldID outputFramebufferInfosID;
jfieldID outputFrameChangedKeysID;
jfieldID outputFrameFormatID;
+ jfieldID bufferInfoFlags;
+ jfieldID bufferInfoOffset;
+ jfieldID bufferInfoSize;
+ jfieldID bufferInfoPresentationTimeUs;
+
};
static fields_t gFields;
@@ -412,6 +425,22 @@
index, offset, size, timeUs, flags, errorDetailMsg);
}
+status_t JMediaCodec::queueInputBuffers(
+ size_t index,
+ size_t offset,
+ size_t size,
+ const sp<RefBase> &infos,
+ AString *errorDetailMsg) {
+
+ sp<BufferInfosWrapper> auInfo((BufferInfosWrapper *)infos.get());
+ return mCodec->queueInputBuffers(
+ index,
+ offset,
+ size,
+ auInfo,
+ errorDetailMsg);
+}
+
status_t JMediaCodec::queueSecureInputBuffer(
size_t index,
size_t offset,
@@ -429,30 +458,46 @@
presentationTimeUs, flags, errorDetailMsg);
}
+status_t JMediaCodec::queueSecureInputBuffers(
+ size_t index,
+ size_t offset,
+ size_t size,
+ const sp<RefBase> &auInfos_,
+ const sp<RefBase> &cryptoInfos_,
+ AString *errorDetailMsg) {
+ sp<BufferInfosWrapper> auInfos((BufferInfosWrapper *)auInfos_.get());
+ sp<CryptoInfosWrapper> cryptoInfos((CryptoInfosWrapper *)cryptoInfos_.get());
+ return mCodec->queueSecureInputBuffers(
+ index,
+ offset,
+ size,
+ auInfos,
+ cryptoInfos,
+ errorDetailMsg);
+}
+
status_t JMediaCodec::queueBuffer(
- size_t index, const std::shared_ptr<C2Buffer> &buffer, int64_t timeUs,
- uint32_t flags, const sp<AMessage> &tunings, AString *errorDetailMsg) {
+ size_t index, const std::shared_ptr<C2Buffer> &buffer,
+ const sp<RefBase> &infos, const sp<AMessage> &tunings, AString *errorDetailMsg) {
+ sp<BufferInfosWrapper> auInfo((BufferInfosWrapper *)infos.get());
return mCodec->queueBuffer(
- index, buffer, timeUs, flags, tunings, errorDetailMsg);
+ index, buffer, auInfo, tunings, errorDetailMsg);
}
status_t JMediaCodec::queueEncryptedLinearBlock(
size_t index,
const sp<hardware::HidlMemory> &buffer,
size_t offset,
- const CryptoPlugin::SubSample *subSamples,
- size_t numSubSamples,
- const uint8_t key[16],
- const uint8_t iv[16],
- CryptoPlugin::Mode mode,
- const CryptoPlugin::Pattern &pattern,
- int64_t presentationTimeUs,
- uint32_t flags,
+ size_t size,
+ const sp<RefBase> &infos,
+ const sp<RefBase> &cryptoInfos_,
const sp<AMessage> &tunings,
AString *errorDetailMsg) {
+ sp<BufferInfosWrapper> auInfo((BufferInfosWrapper *)infos.get());
+ sp<CryptoInfosWrapper> cryptoInfos((CryptoInfosWrapper *)cryptoInfos_.get());
return mCodec->queueEncryptedBuffer(
- index, buffer, offset, subSamples, numSubSamples, key, iv, mode, pattern,
- presentationTimeUs, flags, tunings, errorDetailMsg);
+ index, buffer, offset, size, auInfo, cryptoInfos,
+ tunings, errorDetailMsg);
}
status_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
@@ -722,6 +767,42 @@
return OK;
}
+void maybeSetBufferInfos(JNIEnv *env, jobject &frame, const sp<BufferInfosWrapper> &bufInfos) {
+ if (!bufInfos) {
+ return;
+ }
+ std::vector<AccessUnitInfo> &infos = bufInfos.get()->value;
+ if (infos.empty()) {
+ return;
+ }
+ ScopedLocalRef<jobject> dequeObj{env, env->NewObject(
+ gArrayDequeInfo.clazz, gArrayDequeInfo.ctorId)};
+ jint offset = 0;
+ std::vector<jobject> jObjectInfos;
+ for (int i = 0 ; i < infos.size(); i++) {
+ jobject bufferInfo = env->NewObject(
+ gBufferInfo.clazz, gBufferInfo.ctorId);
+ if (bufferInfo != NULL) {
+ env->CallVoidMethod(bufferInfo, gBufferInfo.setId,
+ offset,
+ (jint)(infos)[i].mSize,
+ (infos)[i].mTimestamp,
+ (infos)[i].mFlags);
+ (void)env->CallBooleanMethod(
+ dequeObj.get(), gArrayDequeInfo.addId, bufferInfo);
+ offset += (infos)[i].mSize;
+ jObjectInfos.push_back(bufferInfo);
+ }
+ }
+ env->SetObjectField(
+ frame,
+ gFields.outputFramebufferInfosID,
+ dequeObj.get());
+ for (int i = 0; i < jObjectInfos.size(); i++) {
+ env->DeleteLocalRef(jObjectInfos[i]);
+ }
+}
+
status_t JMediaCodec::getOutputFrame(
JNIEnv *env, jobject frame, size_t index) const {
sp<MediaCodecBuffer> buffer;
@@ -732,6 +813,11 @@
}
if (buffer->size() > 0) {
+ sp<RefBase> obj;
+ sp<BufferInfosWrapper> bufInfos;
+ if (buffer->meta()->findObject("accessUnitInfo", &obj)) {
+ bufInfos = std::move(((decltype(bufInfos.get()))obj.get()));
+ }
std::shared_ptr<C2Buffer> c2Buffer = buffer->asC2Buffer();
if (c2Buffer) {
switch (c2Buffer->data().type()) {
@@ -747,6 +833,7 @@
(jlong)context.release(),
true);
env->SetObjectField(frame, gFields.outputFrameLinearBlockID, linearBlock.get());
+ maybeSetBufferInfos(env, frame, bufInfos);
break;
}
case C2BufferData::GRAPHIC: {
@@ -787,6 +874,7 @@
(jlong)context.release(),
true);
env->SetObjectField(frame, gFields.outputFrameLinearBlockID, linearBlock.get());
+ maybeSetBufferInfos(env, frame, bufInfos);
} else {
// No-op.
}
@@ -1250,6 +1338,7 @@
void JMediaCodec::handleCallback(const sp<AMessage> &msg) {
int32_t arg1, arg2 = 0;
jobject obj = NULL;
+ std::vector<jobject> jObjectInfos;
CHECK(msg->findInt32("callbackID", &arg1));
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1287,6 +1376,35 @@
break;
}
+ case MediaCodec::CB_LARGE_FRAME_OUTPUT_AVAILABLE:
+ {
+ sp<RefBase> spobj = nullptr;
+ CHECK(msg->findInt32("index", &arg2));
+ CHECK(msg->findObject("accessUnitInfo", &spobj));
+ if (spobj != nullptr) {
+ sp<BufferInfosWrapper> bufferInfoParamsWrapper {
+ (BufferInfosWrapper *)spobj.get()};
+ std::vector<AccessUnitInfo> &bufferInfoParams =
+ bufferInfoParamsWrapper.get()->value;
+ obj = env->NewObject(gArrayDequeInfo.clazz, gArrayDequeInfo.ctorId);
+ jint offset = 0;
+ for (int i = 0 ; i < bufferInfoParams.size(); i++) {
+ jobject bufferInfo = env->NewObject(gBufferInfo.clazz, gBufferInfo.ctorId);
+ if (bufferInfo != NULL) {
+ env->CallVoidMethod(bufferInfo, gBufferInfo.setId,
+ offset,
+ (jint)(bufferInfoParams)[i].mSize,
+ (bufferInfoParams)[i].mTimestamp,
+ (bufferInfoParams)[i].mFlags);
+ (void)env->CallBooleanMethod(obj, gArrayDequeInfo.addId, bufferInfo);
+ offset += (bufferInfoParams)[i].mSize;
+ jObjectInfos.push_back(bufferInfo);
+ }
+ }
+ }
+ break;
+ }
+
case MediaCodec::CB_CRYPTO_ERROR:
{
int32_t err, actionCode;
@@ -1346,6 +1464,9 @@
arg2,
obj);
+ for (int i = 0; i < jObjectInfos.size(); i++) {
+ env->DeleteLocalRef(jObjectInfos[i]);
+ }
env->DeleteLocalRef(obj);
}
@@ -1913,6 +2034,103 @@
codec->getExceptionMessage(errorDetailMsg.c_str()).c_str());
}
+static status_t extractInfosFromObject(
+ JNIEnv * const env,
+ jint * const initialOffset,
+ jint * const totalSize,
+ std::vector<AccessUnitInfo> * const infos,
+ const jobjectArray &objArray,
+ AString * const errorDetailMsg) {
+ if (totalSize == nullptr
+ || initialOffset == nullptr
+ || infos == nullptr) {
+ if (errorDetailMsg) {
+ *errorDetailMsg = "Error: Null arguments provided for extracting Access unit info";
+ }
+ return BAD_VALUE;
+ }
+ const jsize numEntries = env->GetArrayLength(objArray);
+ if (numEntries <= 0) {
+ if (errorDetailMsg) {
+ *errorDetailMsg = "Error: No BufferInfo found while queuing for large frame input";
+ }
+ return BAD_VALUE;
+ }
+ *initialOffset = 0;
+ *totalSize = 0;
+ for (jsize i = 0; i < numEntries; i++) {
+ jobject param = env->GetObjectArrayElement(objArray, i);
+ if (param == NULL) {
+ if (errorDetailMsg) {
+ *errorDetailMsg = "Error: Queuing a null BufferInfo";
+ }
+ return BAD_VALUE;
+ }
+ size_t offset = static_cast<size_t>(env->GetIntField(param, gFields.bufferInfoOffset));
+ size_t size = static_cast<size_t>(env->GetIntField(param, gFields.bufferInfoSize));
+ uint32_t flags = static_cast<uint32_t>(env->GetIntField(param, gFields.bufferInfoFlags));
+ if (flags == 0 && size == 0) {
+ if (errorDetailMsg) {
+ *errorDetailMsg = "Error: Queuing an empty BufferInfo";
+ }
+ return BAD_VALUE;
+ }
+ if (i == 0) {
+ *initialOffset = offset;
+ }
+ if (CC_UNLIKELY((offset > UINT32_MAX)
+ || ((long)(offset + size) > UINT32_MAX)
+ || ((offset - *initialOffset) != *totalSize))) {
+ if (errorDetailMsg) {
+ *errorDetailMsg = "Error: offset/size in BufferInfo";
+ }
+ return BAD_VALUE;
+ }
+ infos->emplace_back(
+ flags,
+ size,
+ env->GetLongField(param, gFields.bufferInfoPresentationTimeUs));
+ *totalSize += size;
+ }
+ return OK;
+}
+
+static void android_media_MediaCodec_queueInputBuffers(
+ JNIEnv *env,
+ jobject thiz,
+ jint index,
+ jobjectArray objArray) {
+ ALOGV("android_media_MediaCodec_queueInputBuffers");
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+ if (codec == NULL || codec->initCheck() != OK || objArray == NULL) {
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
+ return;
+ }
+ sp<BufferInfosWrapper> infoObj =
+ new BufferInfosWrapper{decltype(infoObj->value)()};
+ AString errorDetailMsg;
+ jint initialOffset = 0;
+ jint totalSize = 0;
+ status_t err = extractInfosFromObject(
+ env,
+ &initialOffset,
+ &totalSize,
+ &infoObj->value,
+ objArray,
+ &errorDetailMsg);
+ if (err == OK) {
+ err = codec->queueInputBuffers(
+ index,
+ initialOffset,
+ totalSize,
+ infoObj,
+ &errorDetailMsg);
+ }
+ throwExceptionAsNecessary(
+ env, err, ACTION_CODE_FATAL,
+ codec->getExceptionMessage(errorDetailMsg.c_str()).c_str());
+}
+
struct NativeCryptoInfo {
NativeCryptoInfo(JNIEnv *env, jobject cryptoInfoObj)
: mEnv{env},
@@ -2059,6 +2277,61 @@
CryptoPlugin::Pattern mPattern;
};
+// This class takes away all dependencies on java(env and jni) and
+// could be used for taking cryptoInfo objects to MediaCodec.
+struct MediaCodecCryptoInfo: public CodecCryptoInfo {
+ explicit MediaCodecCryptoInfo(const NativeCryptoInfo &cryptoInfo) {
+ if (cryptoInfo.mErr == OK) {
+ mNumSubSamples = cryptoInfo.mNumSubSamples;
+ mMode = cryptoInfo.mMode;
+ mPattern = cryptoInfo.mPattern;
+ if (cryptoInfo.mKey != nullptr) {
+ mKeyBuffer = ABuffer::CreateAsCopy(cryptoInfo.mKey, 16);
+ mKey = (uint8_t*)(mKeyBuffer.get() != nullptr ? mKeyBuffer.get()->data() : nullptr);
+ }
+ if (cryptoInfo.mIv != nullptr) {
+ mIvBuffer = ABuffer::CreateAsCopy(cryptoInfo.mIv, 16);
+ mIv = (uint8_t*)(mIvBuffer.get() != nullptr ? mIvBuffer.get()->data() : nullptr);
+ }
+ if (cryptoInfo.mSubSamples != nullptr) {
+ mSubSamplesBuffer = new ABuffer(sizeof(CryptoPlugin::SubSample) * mNumSubSamples);
+ if (mSubSamplesBuffer.get()) {
+ CryptoPlugin::SubSample * samples =
+ (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data());
+ for (int s = 0 ; s < mNumSubSamples ; s++) {
+ samples[s].mNumBytesOfClearData =
+ cryptoInfo.mSubSamples[s].mNumBytesOfClearData;
+ samples[s].mNumBytesOfEncryptedData =
+ cryptoInfo.mSubSamples[s].mNumBytesOfEncryptedData;
+ }
+ mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data();
+ }
+ }
+
+ }
+ }
+
+ explicit MediaCodecCryptoInfo(jint size) {
+ mSubSamplesBuffer = new ABuffer(sizeof(CryptoPlugin::SubSample) * 1);
+ mNumSubSamples = 1;
+ if (mSubSamplesBuffer.get()) {
+ CryptoPlugin::SubSample * samples =
+ (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data());
+ samples[0].mNumBytesOfClearData = size;
+ samples[0].mNumBytesOfEncryptedData = 0;
+ mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data();
+ }
+ }
+ ~MediaCodecCryptoInfo() {}
+
+protected:
+ // all backup buffers for the base object.
+ sp<ABuffer> mKeyBuffer;
+ sp<ABuffer> mIvBuffer;
+ sp<ABuffer> mSubSamplesBuffer;
+
+};
+
static void android_media_MediaCodec_queueSecureInputBuffer(
JNIEnv *env,
jobject thiz,
@@ -2227,6 +2500,99 @@
codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto());
}
+static status_t extractCryptoInfosFromObjectArray(JNIEnv * const env,
+ jint * const totalSize,
+ std::vector<std::unique_ptr<CodecCryptoInfo>> * const cryptoInfoObjs,
+ const jobjectArray &objArray,
+ AString * const errorDetailMsg) {
+ if (env == nullptr
+ || cryptoInfoObjs == nullptr
+ || totalSize == nullptr) {
+ if (errorDetailMsg) {
+ *errorDetailMsg = "Error: Null Parameters provided for extracting CryptoInfo";
+ }
+ return BAD_VALUE;
+ }
+ const jsize numEntries = env->GetArrayLength(objArray);
+ if (numEntries <= 0) {
+ if (errorDetailMsg) {
+ *errorDetailMsg = "Error: No CryptoInfo found while queuing for large frame input";
+ }
+ return BAD_VALUE;
+ }
+ cryptoInfoObjs->clear();
+ *totalSize = 0;
+ jint size = 0;
+ for (jsize i = 0; i < numEntries ; i++) {
+ jobject param = env->GetObjectArrayElement(objArray, i);
+ if (param == NULL) {
+ if (errorDetailMsg) {
+ *errorDetailMsg = "Error: Null Parameters provided for extracting CryptoInfo";
+ }
+ return BAD_VALUE;
+ }
+ NativeCryptoInfo nativeInfo(env, param);
+ std::unique_ptr<CodecCryptoInfo> info(new MediaCodecCryptoInfo(nativeInfo));
+ for (int i = 0; i < info->mNumSubSamples; i++) {
+ size += info->mSubSamples[i].mNumBytesOfClearData;
+ size += info->mSubSamples[i].mNumBytesOfEncryptedData;
+ }
+ cryptoInfoObjs->push_back(std::move(info));
+ }
+ *totalSize = size;
+ return OK;
+}
+
+
+static void android_media_MediaCodec_queueSecureInputBuffers(
+ JNIEnv *env,
+ jobject thiz,
+ jint index,
+ jobjectArray bufferInfosObjs,
+ jobjectArray cryptoInfoObjs) {
+ ALOGV("android_media_MediaCodec_queueSecureInputBuffers");
+
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+ if (codec == NULL || codec->initCheck() != OK) {
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
+ return;
+ }
+ sp<BufferInfosWrapper> auInfos =
+ new BufferInfosWrapper{decltype(auInfos->value)()};
+ sp<CryptoInfosWrapper> cryptoInfos =
+ new CryptoInfosWrapper{decltype(cryptoInfos->value)()};
+ AString errorDetailMsg;
+ jint initialOffset = 0;
+ jint totalSize = 0;
+ status_t err = extractInfosFromObject(
+ env,
+ &initialOffset,
+ &totalSize,
+ &auInfos->value,
+ bufferInfosObjs,
+ &errorDetailMsg);
+ if (err == OK) {
+ err = extractCryptoInfosFromObjectArray(env,
+ &totalSize,
+ &cryptoInfos->value,
+ cryptoInfoObjs,
+ &errorDetailMsg);
+ }
+ if (err == OK) {
+ err = codec->queueSecureInputBuffers(
+ index,
+ initialOffset,
+ totalSize,
+ auInfos,
+ cryptoInfos,
+ &errorDetailMsg);
+ }
+ throwExceptionAsNecessary(
+ env, err, ACTION_CODE_FATAL,
+ codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto());
+}
+
static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jclass, jobject bufferObj) {
ALOGV("android_media_MediaCodec_mapHardwareBuffer");
AHardwareBuffer *hardwareBuffer = android_hardware_HardwareBuffer_getNativeHardwareBuffer(
@@ -2559,8 +2925,7 @@
static void android_media_MediaCodec_native_queueLinearBlock(
JNIEnv *env, jobject thiz, jint index, jobject bufferObj,
- jint offset, jint size, jobject cryptoInfoObj,
- jlong presentationTimeUs, jint flags, jobject keys, jobject values) {
+ jobjectArray cryptoInfoArray, jobjectArray objArray, jobject keys, jobject values) {
ALOGV("android_media_MediaCodec_native_queueLinearBlock");
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
@@ -2578,7 +2943,24 @@
"error occurred while converting tunings from Java to native");
return;
}
-
+ jint totalSize = 0;
+ jint initialOffset = 0;
+ std::vector<AccessUnitInfo> infoVec;
+ AString errorDetailMsg;
+ err = extractInfosFromObject(env,
+ &initialOffset,
+ &totalSize,
+ &infoVec,
+ objArray,
+ &errorDetailMsg);
+ if (err != OK) {
+ throwExceptionAsNecessary(
+ env, INVALID_OPERATION, ACTION_CODE_FATAL,
+ codec->getExceptionMessage(errorDetailMsg.c_str()).c_str());
+ return;
+ }
+ sp<BufferInfosWrapper> infos =
+ new BufferInfosWrapper{std::move(infoVec)};
std::shared_ptr<C2Buffer> buffer;
sp<hardware::HidlMemory> memory;
ScopedLocalRef<jobject> lock{env, env->GetObjectField(bufferObj, gLinearBlockInfo.lockId)};
@@ -2587,10 +2969,10 @@
JMediaCodecLinearBlock *context =
(JMediaCodecLinearBlock *)env->GetLongField(bufferObj, gLinearBlockInfo.contextId);
if (codec->hasCryptoOrDescrambler()) {
- extractMemoryFromContext(context, offset, size, &memory);
- offset += context->mHidlMemoryOffset;
+ extractMemoryFromContext(context, initialOffset, totalSize, &memory);
+ initialOffset += context->mHidlMemoryOffset;
} else {
- extractBufferFromContext(context, offset, size, &buffer);
+ extractBufferFromContext(context, initialOffset, totalSize, &buffer);
}
}
env->MonitorExit(lock.get());
@@ -2601,7 +2983,6 @@
return;
}
- AString errorDetailMsg;
if (codec->hasCryptoOrDescrambler()) {
if (!memory) {
// It means there was an unexpected failure in extractMemoryFromContext above
@@ -2614,8 +2995,19 @@
"MediaCodec.LinearBlock#obtain method to obtain a compatible buffer.");
return;
}
- auto cryptoInfo =
- cryptoInfoObj ? NativeCryptoInfo{env, cryptoInfoObj} : NativeCryptoInfo{size};
+ sp<CryptoInfosWrapper> cryptoInfos = new CryptoInfosWrapper{decltype(cryptoInfos->value)()};
+ jint sampleSize = 0;
+ if (cryptoInfoArray != nullptr) {
+ extractCryptoInfosFromObjectArray(env,
+ &sampleSize,
+ &cryptoInfos->value,
+ cryptoInfoArray,
+ &errorDetailMsg);
+ } else {
+ sampleSize = totalSize;
+ std::unique_ptr<CodecCryptoInfo> cryptoInfo{new MediaCodecCryptoInfo(totalSize)};
+ cryptoInfos->value.push_back(std::move(cryptoInfo));
+ }
if (env->ExceptionCheck()) {
// Creation of cryptoInfo failed. Let the exception bubble up.
return;
@@ -2623,13 +3015,10 @@
err = codec->queueEncryptedLinearBlock(
index,
memory,
- offset,
- cryptoInfo.mSubSamples, cryptoInfo.mNumSubSamples,
- (const uint8_t *)cryptoInfo.mKey, (const uint8_t *)cryptoInfo.mIv,
- cryptoInfo.mMode,
- cryptoInfo.mPattern,
- presentationTimeUs,
- flags,
+ initialOffset,
+ sampleSize,
+ infos,
+ cryptoInfos,
tunings,
&errorDetailMsg);
ALOGI_IF(err != OK, "queueEncryptedLinearBlock returned err = %d", err);
@@ -2646,7 +3035,7 @@
return;
}
err = codec->queueBuffer(
- index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg);
+ index, buffer, infos, tunings, &errorDetailMsg);
}
throwExceptionAsNecessary(
env, err, ACTION_CODE_FATAL,
@@ -2704,8 +3093,11 @@
std::shared_ptr<C2Buffer> buffer = C2Buffer::CreateGraphicBuffer(block->share(
block->crop(), C2Fence{}));
AString errorDetailMsg;
+ sp<BufferInfosWrapper> infos =
+ new BufferInfosWrapper{decltype(infos->value)()};
+ infos->value.emplace_back(flags, 0 /*not used*/, presentationTimeUs);
err = codec->queueBuffer(
- index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg);
+ index, buffer, infos, tunings, &errorDetailMsg);
throwExceptionAsNecessary(
env, err, ACTION_CODE_FATAL,
codec->getExceptionMessage(errorDetailMsg.c_str()).c_str());
@@ -3214,6 +3606,10 @@
env->GetFieldID(clazz.get(), "mLinearBlock", "Landroid/media/MediaCodec$LinearBlock;");
CHECK(gFields.outputFrameLinearBlockID != NULL);
+ gFields.outputFramebufferInfosID =
+ env->GetFieldID(clazz.get(), "mBufferInfos", "Ljava/util/ArrayDeque;");
+ CHECK(gFields.outputFramebufferInfosID != NULL);
+
gFields.outputFrameHardwareBufferID =
env->GetFieldID(clazz.get(), "mHardwareBuffer", "Landroid/hardware/HardwareBuffer;");
CHECK(gFields.outputFrameHardwareBufferID != NULL);
@@ -3401,6 +3797,19 @@
gArrayListInfo.addId = env->GetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z");
CHECK(gArrayListInfo.addId != NULL);
+ clazz.reset(env->FindClass("java/util/ArrayDeque"));
+ CHECK(clazz.get() != NULL);
+ gArrayDequeInfo.clazz = (jclass)env->NewGlobalRef(clazz.get());
+
+ gArrayDequeInfo.ctorId = env->GetMethodID(clazz.get(), "<init>", "()V");
+ CHECK(gArrayDequeInfo.ctorId != NULL);
+
+ gArrayDequeInfo.sizeId = env->GetMethodID(clazz.get(), "size", "()I");
+ CHECK(gArrayDequeInfo.sizeId != NULL);
+
+ gArrayDequeInfo.addId = env->GetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z");
+ CHECK(gArrayDequeInfo.addId != NULL);
+
clazz.reset(env->FindClass("android/media/MediaCodec$LinearBlock"));
CHECK(clazz.get() != NULL);
@@ -3444,6 +3853,12 @@
gBufferInfo.setId = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
CHECK(gBufferInfo.setId != NULL);
+
+ gFields.bufferInfoSize = env->GetFieldID(clazz.get(), "size", "I");
+ gFields.bufferInfoFlags = env->GetFieldID(clazz.get(), "flags", "I");
+ gFields.bufferInfoOffset = env->GetFieldID(clazz.get(), "offset", "I");
+ gFields.bufferInfoPresentationTimeUs =
+ env->GetFieldID(clazz.get(), "presentationTimeUs", "J");
}
static void android_media_MediaCodec_native_setup(
@@ -3701,9 +4116,15 @@
{ "native_queueInputBuffer", "(IIIJI)V",
(void *)android_media_MediaCodec_queueInputBuffer },
+ { "native_queueInputBuffers", "(I[Ljava/lang/Object;)V",
+ (void *)android_media_MediaCodec_queueInputBuffers },
+
{ "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
(void *)android_media_MediaCodec_queueSecureInputBuffer },
+ { "native_queueSecureInputBuffers", "(I[Ljava/lang/Object;[Ljava/lang/Object;)V",
+ (void *)android_media_MediaCodec_queueSecureInputBuffers },
+
{ "native_mapHardwareBuffer",
"(Landroid/hardware/HardwareBuffer;)Landroid/media/Image;",
(void *)android_media_MediaCodec_mapHardwareBuffer },
@@ -3711,8 +4132,8 @@
{ "native_closeMediaImage", "(J)V", (void *)android_media_MediaCodec_closeMediaImage },
{ "native_queueLinearBlock",
- "(ILandroid/media/MediaCodec$LinearBlock;IILandroid/media/MediaCodec$CryptoInfo;JI"
- "Ljava/util/ArrayList;Ljava/util/ArrayList;)V",
+ "(ILandroid/media/MediaCodec$LinearBlock;[Ljava/lang/Object;"
+ "[Ljava/lang/Object;Ljava/util/ArrayList;Ljava/util/ArrayList;)V",
(void *)android_media_MediaCodec_native_queueLinearBlock },
{ "native_queueHardwareBuffer",
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index fbaf64f..abb23f5 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -35,6 +35,7 @@
namespace android {
struct ABuffer;
+struct AccessUnitInfo;
struct ALooper;
struct AMessage;
struct AString;
@@ -93,6 +94,13 @@
size_t offset, size_t size, int64_t timeUs, uint32_t flags,
AString *errorDetailMsg);
+ status_t queueInputBuffers(
+ size_t index,
+ size_t offset,
+ size_t size,
+ const sp<RefBase> &auInfo,
+ AString *errorDetailMsg = NULL);
+
status_t queueSecureInputBuffer(
size_t index,
size_t offset,
@@ -106,23 +114,26 @@
uint32_t flags,
AString *errorDetailMsg);
+ status_t queueSecureInputBuffers(
+ size_t index,
+ size_t offset,
+ size_t size,
+ const sp<RefBase> &auInfos,
+ const sp<RefBase> &cryptoInfos,
+ AString *errorDetailMsg);
+
status_t queueBuffer(
size_t index, const std::shared_ptr<C2Buffer> &buffer,
- int64_t timeUs, uint32_t flags, const sp<AMessage> &tunings,
+ const sp<RefBase> &infos, const sp<AMessage> &tunings,
AString *errorDetailMsg);
status_t queueEncryptedLinearBlock(
size_t index,
const sp<hardware::HidlMemory> &buffer,
size_t offset,
- const CryptoPlugin::SubSample *subSamples,
- size_t numSubSamples,
- const uint8_t key[16],
- const uint8_t iv[16],
- CryptoPlugin::Mode mode,
- const CryptoPlugin::Pattern &pattern,
- int64_t presentationTimeUs,
- uint32_t flags,
+ size_t size,
+ const sp<RefBase> &infos,
+ const sp<RefBase> &cryptoInfos,
const sp<AMessage> &tunings,
AString *errorDetailMsg);
diff --git a/media/jni/soundpool/SoundDecoder.cpp b/media/jni/soundpool/SoundDecoder.cpp
index 5ed10b0..ae57634 100644
--- a/media/jni/soundpool/SoundDecoder.cpp
+++ b/media/jni/soundpool/SoundDecoder.cpp
@@ -29,14 +29,15 @@
// before the SoundDecoder thread closes.
static constexpr int32_t kWaitTimeBeforeCloseMs = 1000;
-SoundDecoder::SoundDecoder(SoundManager* soundManager, size_t threads)
+SoundDecoder::SoundDecoder(SoundManager* soundManager, size_t threads, int32_t threadPriority)
: mSoundManager(soundManager)
{
ALOGV("%s(%p, %zu)", __func__, soundManager, threads);
// ThreadPool is created, but we don't launch any threads.
mThreadPool = std::make_unique<ThreadPool>(
std::min(threads, (size_t)std::thread::hardware_concurrency()),
- "SoundDecoder_");
+ "SoundDecoder_",
+ threadPriority);
}
SoundDecoder::~SoundDecoder()
diff --git a/media/jni/soundpool/SoundDecoder.h b/media/jni/soundpool/SoundDecoder.h
index 7b62114..3f44a0d 100644
--- a/media/jni/soundpool/SoundDecoder.h
+++ b/media/jni/soundpool/SoundDecoder.h
@@ -28,7 +28,7 @@
*/
class SoundDecoder {
public:
- SoundDecoder(SoundManager* soundManager, size_t threads);
+ SoundDecoder(SoundManager* soundManager, size_t threads, int32_t threadPriority);
~SoundDecoder();
void loadSound(int32_t soundID) NO_THREAD_SAFETY_ANALYSIS; // uses unique_lock
void quit();
diff --git a/media/jni/soundpool/SoundManager.cpp b/media/jni/soundpool/SoundManager.cpp
index 5b16174..fa35813 100644
--- a/media/jni/soundpool/SoundManager.cpp
+++ b/media/jni/soundpool/SoundManager.cpp
@@ -29,7 +29,7 @@
static const size_t kDecoderThreads = std::thread::hardware_concurrency() >= 4 ? 2 : 1;
SoundManager::SoundManager()
- : mDecoder{std::make_unique<SoundDecoder>(this, kDecoderThreads)}
+ : mDecoder{std::make_unique<SoundDecoder>(this, kDecoderThreads, ANDROID_PRIORITY_NORMAL)}
{
ALOGV("%s()", __func__);
}
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 52060f1..e11ccbc 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -35,10 +35,9 @@
// In R, we change this to true, as it is the correct way per SoundPool documentation.
static constexpr bool kStealActiveStream_OldestFirst = true;
-// kPlayOnCallingThread = true prior to R.
// Changing to false means calls to play() are almost instantaneous instead of taking around
// ~10ms to launch the AudioTrack. It is perhaps 100x faster.
-static constexpr bool kPlayOnCallingThread = true;
+static constexpr bool kPlayOnCallingThread = false;
// Amount of time for a StreamManager thread to wait before closing.
static constexpr int64_t kWaitTimeBeforeCloseNs = 9 * NANOS_PER_SECOND;
@@ -127,7 +126,8 @@
mThreadPool = std::make_unique<ThreadPool>(
std::min((size_t)streams, // do not make more threads than streams to play
std::min(threads, (size_t)std::thread::hardware_concurrency())),
- "SoundPool_");
+ "SoundPool_",
+ ANDROID_PRIORITY_AUDIO);
}
#pragma clang diagnostic pop
diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h
index adbab4b..a4cb286 100644
--- a/media/jni/soundpool/StreamManager.h
+++ b/media/jni/soundpool/StreamManager.h
@@ -46,9 +46,9 @@
*/
class JavaThread {
public:
- JavaThread(std::function<void()> f, const char *name)
+ JavaThread(std::function<void()> f, const char *name, int32_t threadPriority)
: mF{std::move(f)} {
- createThreadEtc(staticFunction, this, name);
+ createThreadEtc(staticFunction, this, name, threadPriority);
}
JavaThread(JavaThread &&) = delete; // uses "this" ptr, not moveable.
@@ -109,9 +109,11 @@
*/
class ThreadPool {
public:
- ThreadPool(size_t maxThreadCount, std::string name)
+ ThreadPool(size_t maxThreadCount, std::string name,
+ int32_t threadPriority = ANDROID_PRIORITY_NORMAL)
: mMaxThreadCount(maxThreadCount)
- , mName{std::move(name)} { }
+ , mName{std::move(name)}
+ , mThreadPriority(threadPriority) {}
~ThreadPool() { quit(); }
@@ -159,7 +161,8 @@
const int32_t id = mNextThreadId;
mThreads.emplace_back(std::make_unique<JavaThread>(
[this, id, mf = std::move(f)] { mf(id); --mActiveThreadCount; },
- (mName + std::to_string(id)).c_str()));
+ (mName + std::to_string(id)).c_str(),
+ mThreadPriority));
++mActiveThreadCount;
return id;
}
@@ -180,6 +183,7 @@
private:
const size_t mMaxThreadCount;
const std::string mName;
+ const int32_t mThreadPriority;
std::atomic_size_t mActiveThreadCount = 0;
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java
index 70202463..c18a2de 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java
@@ -41,7 +41,7 @@
public EffectsTest() {
- Log.d(TAG, "contructor");
+ Log.d(TAG, "constructor");
}
@Override
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
index 388a65d..00068bd 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
@@ -1709,7 +1709,7 @@
* <p>
* Two images are strongly equal if and only if the data, formats, sizes,
* and timestamps are same. For {@link ImageFormat#PRIVATE PRIVATE} format
- * images, the image data is not not accessible thus the data comparison is
+ * images, the image data is not accessible thus the data comparison is
* effectively skipped as the number of planes is zero.
* </p>
* <p>
@@ -2049,7 +2049,7 @@
}
} else {
// Case 2.
- collector.expectEquals("Exif orientaiton should match requested orientation",
+ collector.expectEquals("Exif orientation should match requested orientation",
requestedOrientation, getExifOrientationInDegree(exifOrientation,
collector));
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
index ed70ab9..5dcd1cb 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
@@ -1127,8 +1127,8 @@
* Get aeAvailableModes and do the validation check.
*
* <p>Depending on the check level this class has, for WAR or COLLECT levels,
- * If the aeMode list is invalid, return an empty mode array. The the caller doesn't
- * have to abort the execution even the aeMode list is invalid.</p>
+ * If the aeMode list is invalid, return an empty mode array. The caller doesn't
+ * have to abort the execution even if the aeMode list is invalid.</p>
* @return AE available modes
*/
public int[] getAeAvailableModesChecked() {
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index d74f9b7..985305f 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -1,9 +1,9 @@
LIBANDROID {
global:
- AActivityManager_addUidImportanceListener; # systemapi # introduced=31
- AActivityManager_removeUidImportanceListener; # systemapi # introduced=31
- AActivityManager_isUidActive; # systemapi # introduced=31
- AActivityManager_getUidImportance; # systemapi # introduced=31
+ AActivityManager_addUidImportanceListener; # systemapi introduced=31
+ AActivityManager_removeUidImportanceListener; # systemapi introduced=31
+ AActivityManager_isUidActive; # systemapi introduced=31
+ AActivityManager_getUidImportance; # systemapi introduced=31
AAssetDir_close;
AAssetDir_getNextFileName;
AAssetDir_rewind;
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 10c570b..8ea4632 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -72,6 +72,9 @@
],
},
},
+ stubs: {
+ symbol_file: "libjnigraphics.map.txt",
+ },
}
// The headers module is in frameworks/native/Android.bp.
@@ -93,15 +96,18 @@
],
static_libs: ["libarect"],
fuzz_config: {
- cc: ["dichenzhang@google.com","scroggo@google.com"],
+ cc: [
+ "dichenzhang@google.com",
+ "scroggo@google.com",
+ ],
asan_options: [
"detect_odr_violation=1",
],
hwasan_options: [
- // Image decoders may attempt to allocate a large amount of memory
- // (especially if the encoded image is large). This doesn't
- // necessarily mean there is a bug. Set allocator_may_return_null=1
- // for hwasan so the fuzzer can continue running.
+ // Image decoders may attempt to allocate a large amount of memory
+ // (especially if the encoded image is large). This doesn't
+ // necessarily mean there is a bug. Set allocator_may_return_null=1
+ // for hwasan so the fuzzer can continue running.
"allocator_may_return_null = 1",
],
},
diff --git a/native/graphics/jni/libjnigraphics.map.txt b/native/graphics/jni/libjnigraphics.map.txt
index e0df794..193728a 100644
--- a/native/graphics/jni/libjnigraphics.map.txt
+++ b/native/graphics/jni/libjnigraphics.map.txt
@@ -18,21 +18,21 @@
AImageDecoder_getRepeatCount; # introduced=31
AImageDecoder_advanceFrame; # introduced=31
AImageDecoder_rewind; # introduced=31
- AImageDecoder_getFrameInfo; # introduced = 31
- AImageDecoder_setInternallyHandleDisposePrevious; # introduced = 31
+ AImageDecoder_getFrameInfo; # introduced=31
+ AImageDecoder_setInternallyHandleDisposePrevious; # introduced=31
AImageDecoderHeaderInfo_getWidth; # introduced=30
AImageDecoderHeaderInfo_getHeight; # introduced=30
AImageDecoderHeaderInfo_getMimeType; # introduced=30
AImageDecoderHeaderInfo_getAlphaFlags; # introduced=30
AImageDecoderHeaderInfo_getAndroidBitmapFormat; # introduced=30
AImageDecoderHeaderInfo_getDataSpace; # introduced=30
- AImageDecoderFrameInfo_create; # introduced = 31
- AImageDecoderFrameInfo_delete; # introduced = 31
- AImageDecoderFrameInfo_getDuration; # introduced = 31
- AImageDecoderFrameInfo_getFrameRect; # introduced = 31
- AImageDecoderFrameInfo_hasAlphaWithinBounds; # introduced = 31
- AImageDecoderFrameInfo_getDisposeOp; # introduced = 31
- AImageDecoderFrameInfo_getBlendOp; # introduced = 31
+ AImageDecoderFrameInfo_create; # introduced=31
+ AImageDecoderFrameInfo_delete; # introduced=31
+ AImageDecoderFrameInfo_getDuration; # introduced=31
+ AImageDecoderFrameInfo_getFrameRect; # introduced=31
+ AImageDecoderFrameInfo_hasAlphaWithinBounds; # introduced=31
+ AImageDecoderFrameInfo_getDisposeOp; # introduced=31
+ AImageDecoderFrameInfo_getBlendOp; # introduced=31
AndroidBitmap_getInfo;
AndroidBitmap_getDataSpace;
AndroidBitmap_lockPixels;
diff --git a/nfc-extras/Android.bp b/nfc-extras/Android.bp
index cb9ac6f..1f187e8 100644
--- a/nfc-extras/Android.bp
+++ b/nfc-extras/Android.bp
@@ -23,9 +23,13 @@
default_applicable_licenses: ["frameworks_base_license"],
}
+// TODO(b/303286040): Deprecate this API surface since this is no longer supported (see ag/443092)
java_sdk_library {
name: "com.android.nfc_extras",
srcs: ["java/**/*.java"],
+ libs: [
+ "framework-nfc.impl"
+ ],
api_packages: ["com.android.nfc_extras"],
dist_group: "android",
}
diff --git a/nfc/Android.bp b/nfc/Android.bp
index bf9f47c..2090d339 100644
--- a/nfc/Android.bp
+++ b/nfc/Android.bp
@@ -10,7 +10,15 @@
filegroup {
name: "framework-nfc-non-updatable-sources",
path: "java",
- srcs: [],
+ srcs: [
+ "java/android/nfc/NfcServiceManager.java",
+ "java/android/nfc/cardemulation/ApduServiceInfo.aidl",
+ "java/android/nfc/cardemulation/ApduServiceInfo.java",
+ "java/android/nfc/cardemulation/NfcFServiceInfo.aidl",
+ "java/android/nfc/cardemulation/NfcFServiceInfo.java",
+ "java/android/nfc/cardemulation/AidGroup.aidl",
+ "java/android/nfc/cardemulation/AidGroup.java",
+ ],
}
filegroup {
@@ -30,10 +38,21 @@
libs: [
"unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
],
+ static_libs: [
+ "android.nfc.flags-aconfig-java",
+ ],
srcs: [
":framework-nfc-updatable-sources",
+ ":framework-nfc-javastream-protos",
],
- defaults: ["framework-non-updatable-unbundled-defaults"],
+ defaults: ["framework-module-defaults"],
+ sdk_version: "module_current",
+ min_sdk_version: "34", // should be 35 (making it 34 for compiling for `-next`)
+ installable: true,
+ optimize: {
+ enabled: false,
+ },
+ hostdex: true, // for hiddenapi check
permitted_packages: [
"android.nfc",
"com.android.nfc",
@@ -41,11 +60,18 @@
hidden_api_packages: [
"com.android.nfc",
],
- aidl: {
- include_dirs: [
- // TODO (b/303286040): Remove these when we change to |framework-module-defaults|
- "frameworks/base/nfc/java",
- "frameworks/base/core/java",
- ],
+ impl_library_visibility: [
+ "//frameworks/base:__subpackages__",
+ "//cts/tests/tests/nfc",
+ "//packages/apps/Nfc:__subpackages__",
+ ],
+ jarjar_rules: ":nfc-jarjar-rules",
+ lint: {
+ strict_updatability_linting: true,
},
}
+
+filegroup {
+ name: "nfc-jarjar-rules",
+ srcs: ["jarjar-rules.txt"],
+}
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index d802177..0ab2ef7 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -1 +1,439 @@
// Signature format: 2.0
+package android.nfc {
+
+ public final class AvailableNfcAntenna implements android.os.Parcelable {
+ ctor public AvailableNfcAntenna(int, int);
+ method public int describeContents();
+ method public int getLocationX();
+ method public int getLocationY();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nfc.AvailableNfcAntenna> CREATOR;
+ }
+
+ public class FormatException extends java.lang.Exception {
+ ctor public FormatException();
+ ctor public FormatException(String);
+ ctor public FormatException(String, Throwable);
+ }
+
+ public final class NdefMessage implements android.os.Parcelable {
+ ctor public NdefMessage(byte[]) throws android.nfc.FormatException;
+ ctor public NdefMessage(android.nfc.NdefRecord, android.nfc.NdefRecord...);
+ ctor public NdefMessage(android.nfc.NdefRecord[]);
+ method public int describeContents();
+ method public int getByteArrayLength();
+ method public android.nfc.NdefRecord[] getRecords();
+ method public byte[] toByteArray();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nfc.NdefMessage> CREATOR;
+ }
+
+ public final class NdefRecord implements android.os.Parcelable {
+ ctor public NdefRecord(short, byte[], byte[], byte[]);
+ ctor @Deprecated public NdefRecord(byte[]) throws android.nfc.FormatException;
+ method public static android.nfc.NdefRecord createApplicationRecord(String);
+ method public static android.nfc.NdefRecord createExternal(String, String, byte[]);
+ method public static android.nfc.NdefRecord createMime(String, byte[]);
+ method public static android.nfc.NdefRecord createTextRecord(String, String);
+ method public static android.nfc.NdefRecord createUri(android.net.Uri);
+ method public static android.nfc.NdefRecord createUri(String);
+ method public int describeContents();
+ method public byte[] getId();
+ method public byte[] getPayload();
+ method public short getTnf();
+ method public byte[] getType();
+ method @Deprecated public byte[] toByteArray();
+ method public String toMimeType();
+ method public android.net.Uri toUri();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nfc.NdefRecord> CREATOR;
+ field public static final byte[] RTD_ALTERNATIVE_CARRIER;
+ field public static final byte[] RTD_HANDOVER_CARRIER;
+ field public static final byte[] RTD_HANDOVER_REQUEST;
+ field public static final byte[] RTD_HANDOVER_SELECT;
+ field public static final byte[] RTD_SMART_POSTER;
+ field public static final byte[] RTD_TEXT;
+ field public static final byte[] RTD_URI;
+ field public static final short TNF_ABSOLUTE_URI = 3; // 0x3
+ field public static final short TNF_EMPTY = 0; // 0x0
+ field public static final short TNF_EXTERNAL_TYPE = 4; // 0x4
+ field public static final short TNF_MIME_MEDIA = 2; // 0x2
+ field public static final short TNF_UNCHANGED = 6; // 0x6
+ field public static final short TNF_UNKNOWN = 5; // 0x5
+ field public static final short TNF_WELL_KNOWN = 1; // 0x1
+ }
+
+ public final class NfcAdapter {
+ method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean allowTransaction();
+ method public void disableForegroundDispatch(android.app.Activity);
+ method public void disableReaderMode(android.app.Activity);
+ method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean disallowTransaction();
+ method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]);
+ method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
+ method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
+ method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo();
+ method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
+ method public boolean isEnabled();
+ method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean isObserveModeSupported();
+ method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionEnabled();
+ method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported();
+ method public boolean isSecureNfcEnabled();
+ method public boolean isSecureNfcSupported();
+ method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void resetDiscoveryTechnology(@NonNull android.app.Activity);
+ method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void setDiscoveryTechnology(@NonNull android.app.Activity, int, int);
+ field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
+ field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
+ field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
+ field public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
+ field public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
+ field @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT) public static final String ACTION_TRANSACTION_DETECTED = "android.nfc.action.TRANSACTION_DETECTED";
+ field public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
+ field public static final String EXTRA_AID = "android.nfc.extra.AID";
+ field public static final String EXTRA_DATA = "android.nfc.extra.DATA";
+ field public static final String EXTRA_ID = "android.nfc.extra.ID";
+ field public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
+ field public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON = "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON";
+ field public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
+ field public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
+ field public static final String EXTRA_TAG = "android.nfc.extra.TAG";
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_DISABLE = 0; // 0x0
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_KEEP = -2147483648; // 0x80000000
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_A = 1; // 0x1
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_B = 2; // 0x2
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_F = 4; // 0x4
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_READER_DISABLE = 0; // 0x0
+ field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_READER_KEEP = -2147483648; // 0x80000000
+ field public static final int FLAG_READER_NFC_A = 1; // 0x1
+ field public static final int FLAG_READER_NFC_B = 2; // 0x2
+ field public static final int FLAG_READER_NFC_BARCODE = 16; // 0x10
+ field public static final int FLAG_READER_NFC_F = 4; // 0x4
+ field public static final int FLAG_READER_NFC_V = 8; // 0x8
+ field public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 256; // 0x100
+ field public static final int FLAG_READER_SKIP_NDEF_CHECK = 128; // 0x80
+ field public static final int PREFERRED_PAYMENT_CHANGED = 2; // 0x2
+ field public static final int PREFERRED_PAYMENT_LOADED = 1; // 0x1
+ field public static final int PREFERRED_PAYMENT_UPDATED = 3; // 0x3
+ field public static final int STATE_OFF = 1; // 0x1
+ field public static final int STATE_ON = 3; // 0x3
+ field public static final int STATE_TURNING_OFF = 4; // 0x4
+ field public static final int STATE_TURNING_ON = 2; // 0x2
+ }
+
+ @Deprecated public static interface NfcAdapter.CreateBeamUrisCallback {
+ method @Deprecated public android.net.Uri[] createBeamUris(android.nfc.NfcEvent);
+ }
+
+ @Deprecated public static interface NfcAdapter.CreateNdefMessageCallback {
+ method @Deprecated public android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent);
+ }
+
+ @Deprecated public static interface NfcAdapter.OnNdefPushCompleteCallback {
+ method @Deprecated public void onNdefPushComplete(android.nfc.NfcEvent);
+ }
+
+ public static interface NfcAdapter.OnTagRemovedListener {
+ method public void onTagRemoved();
+ }
+
+ public static interface NfcAdapter.ReaderCallback {
+ method public void onTagDiscovered(android.nfc.Tag);
+ }
+
+ public final class NfcAntennaInfo implements android.os.Parcelable {
+ ctor public NfcAntennaInfo(int, int, boolean, @NonNull java.util.List<android.nfc.AvailableNfcAntenna>);
+ method public int describeContents();
+ method @NonNull public java.util.List<android.nfc.AvailableNfcAntenna> getAvailableNfcAntennas();
+ method public int getDeviceHeight();
+ method public int getDeviceWidth();
+ method public boolean isDeviceFoldable();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nfc.NfcAntennaInfo> CREATOR;
+ }
+
+ public final class NfcEvent {
+ field public final android.nfc.NfcAdapter nfcAdapter;
+ field public final int peerLlcpMajorVersion;
+ field public final int peerLlcpMinorVersion;
+ }
+
+ public final class NfcManager {
+ method public android.nfc.NfcAdapter getDefaultAdapter();
+ }
+
+ public final class Tag implements android.os.Parcelable {
+ method public int describeContents();
+ method public byte[] getId();
+ method public String[] getTechList();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nfc.Tag> CREATOR;
+ }
+
+ public class TagLostException extends java.io.IOException {
+ ctor public TagLostException();
+ ctor public TagLostException(String);
+ }
+
+}
+
+package android.nfc.cardemulation {
+
+ public final class CardEmulation {
+ method public boolean categoryAllowsForegroundPreference(String);
+ method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public java.util.List<java.lang.String> getAidsForPreferredPaymentService();
+ method public java.util.List<java.lang.String> getAidsForService(android.content.ComponentName, String);
+ method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public CharSequence getDescriptionForPreferredPaymentService();
+ method public static android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
+ method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getRouteDestinationForPreferredPaymentService();
+ method public int getSelectionModeForCategory(String);
+ method public boolean isDefaultServiceForAid(android.content.ComponentName, String);
+ method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
+ method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>);
+ method public boolean removeAidsForService(android.content.ComponentName, String);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
+ method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
+ method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setServiceObserveModeDefault(@NonNull android.content.ComponentName, boolean);
+ method public boolean supportsAidPrefixRegistration();
+ method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
+ method public boolean unsetPreferredService(android.app.Activity);
+ field public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
+ field public static final String CATEGORY_OTHER = "other";
+ field public static final String CATEGORY_PAYMENT = "payment";
+ field public static final String EXTRA_CATEGORY = "category";
+ field public static final String EXTRA_SERVICE_COMPONENT = "component";
+ field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1
+ field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2
+ field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
+ }
+
+ public abstract class HostApduService extends android.app.Service {
+ ctor public HostApduService();
+ method public final void notifyUnhandled();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ method public abstract void onDeactivated(int);
+ method public abstract byte[] processCommandApdu(byte[], android.os.Bundle);
+ method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void processPollingFrames(@NonNull java.util.List<android.os.Bundle>);
+ method public final void sendResponseApdu(byte[]);
+ field public static final int DEACTIVATION_DESELECTED = 1; // 0x1
+ field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_DATA_KEY = "android.nfc.cardemulation.DATA";
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_GAIN_KEY = "android.nfc.cardemulation.GAIN";
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_TIMESTAMP_KEY = "android.nfc.cardemulation.TIMESTAMP";
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_A = 65; // 0x0041 'A'
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_B = 66; // 0x0042 'B'
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_F = 70; // 0x0046 'F'
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_TYPE_KEY = "android.nfc.cardemulation.TYPE";
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_OFF = 88; // 0x0058 'X'
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_ON = 79; // 0x004f 'O'
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_UNKNOWN = 85; // 0x0055 'U'
+ field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE";
+ field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service";
+ }
+
+ public abstract class HostNfcFService extends android.app.Service {
+ ctor public HostNfcFService();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ method public abstract void onDeactivated(int);
+ method public abstract byte[] processNfcFPacket(byte[], android.os.Bundle);
+ method public final void sendResponsePacket(byte[]);
+ field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0
+ field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_NFCF_SERVICE";
+ field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_nfcf_service";
+ }
+
+ public final class NfcFCardEmulation {
+ method public boolean disableService(android.app.Activity) throws java.lang.RuntimeException;
+ method public boolean enableService(android.app.Activity, android.content.ComponentName) throws java.lang.RuntimeException;
+ method public static android.nfc.cardemulation.NfcFCardEmulation getInstance(android.nfc.NfcAdapter);
+ method public String getNfcid2ForService(android.content.ComponentName) throws java.lang.RuntimeException;
+ method public String getSystemCodeForService(android.content.ComponentName) throws java.lang.RuntimeException;
+ method public boolean registerSystemCodeForService(android.content.ComponentName, String) throws java.lang.RuntimeException;
+ method public boolean setNfcid2ForService(android.content.ComponentName, String) throws java.lang.RuntimeException;
+ method public boolean unregisterSystemCodeForService(android.content.ComponentName) throws java.lang.RuntimeException;
+ }
+
+ public abstract class OffHostApduService extends android.app.Service {
+ ctor public OffHostApduService();
+ field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE";
+ field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.off_host_apdu_service";
+ }
+
+}
+
+package android.nfc.tech {
+
+ public final class IsoDep implements android.nfc.tech.TagTechnology {
+ method public void close() throws java.io.IOException;
+ method public void connect() throws java.io.IOException;
+ method public static android.nfc.tech.IsoDep get(android.nfc.Tag);
+ method public byte[] getHiLayerResponse();
+ method public byte[] getHistoricalBytes();
+ method public int getMaxTransceiveLength();
+ method public android.nfc.Tag getTag();
+ method public int getTimeout();
+ method public boolean isConnected();
+ method public boolean isExtendedLengthApduSupported();
+ method public void setTimeout(int);
+ method public byte[] transceive(byte[]) throws java.io.IOException;
+ }
+
+ public final class MifareClassic implements android.nfc.tech.TagTechnology {
+ method public boolean authenticateSectorWithKeyA(int, byte[]) throws java.io.IOException;
+ method public boolean authenticateSectorWithKeyB(int, byte[]) throws java.io.IOException;
+ method public int blockToSector(int);
+ method public void close() throws java.io.IOException;
+ method public void connect() throws java.io.IOException;
+ method public void decrement(int, int) throws java.io.IOException;
+ method public static android.nfc.tech.MifareClassic get(android.nfc.Tag);
+ method public int getBlockCount();
+ method public int getBlockCountInSector(int);
+ method public int getMaxTransceiveLength();
+ method public int getSectorCount();
+ method public int getSize();
+ method public android.nfc.Tag getTag();
+ method public int getTimeout();
+ method public int getType();
+ method public void increment(int, int) throws java.io.IOException;
+ method public boolean isConnected();
+ method public byte[] readBlock(int) throws java.io.IOException;
+ method public void restore(int) throws java.io.IOException;
+ method public int sectorToBlock(int);
+ method public void setTimeout(int);
+ method public byte[] transceive(byte[]) throws java.io.IOException;
+ method public void transfer(int) throws java.io.IOException;
+ method public void writeBlock(int, byte[]) throws java.io.IOException;
+ field public static final int BLOCK_SIZE = 16; // 0x10
+ field public static final byte[] KEY_DEFAULT;
+ field public static final byte[] KEY_MIFARE_APPLICATION_DIRECTORY;
+ field public static final byte[] KEY_NFC_FORUM;
+ field public static final int SIZE_1K = 1024; // 0x400
+ field public static final int SIZE_2K = 2048; // 0x800
+ field public static final int SIZE_4K = 4096; // 0x1000
+ field public static final int SIZE_MINI = 320; // 0x140
+ field public static final int TYPE_CLASSIC = 0; // 0x0
+ field public static final int TYPE_PLUS = 1; // 0x1
+ field public static final int TYPE_PRO = 2; // 0x2
+ field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public final class MifareUltralight implements android.nfc.tech.TagTechnology {
+ method public void close() throws java.io.IOException;
+ method public void connect() throws java.io.IOException;
+ method public static android.nfc.tech.MifareUltralight get(android.nfc.Tag);
+ method public int getMaxTransceiveLength();
+ method public android.nfc.Tag getTag();
+ method public int getTimeout();
+ method public int getType();
+ method public boolean isConnected();
+ method public byte[] readPages(int) throws java.io.IOException;
+ method public void setTimeout(int);
+ method public byte[] transceive(byte[]) throws java.io.IOException;
+ method public void writePage(int, byte[]) throws java.io.IOException;
+ field public static final int PAGE_SIZE = 4; // 0x4
+ field public static final int TYPE_ULTRALIGHT = 1; // 0x1
+ field public static final int TYPE_ULTRALIGHT_C = 2; // 0x2
+ field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public final class Ndef implements android.nfc.tech.TagTechnology {
+ method public boolean canMakeReadOnly();
+ method public void close() throws java.io.IOException;
+ method public void connect() throws java.io.IOException;
+ method public static android.nfc.tech.Ndef get(android.nfc.Tag);
+ method public android.nfc.NdefMessage getCachedNdefMessage();
+ method public int getMaxSize();
+ method public android.nfc.NdefMessage getNdefMessage() throws android.nfc.FormatException, java.io.IOException;
+ method public android.nfc.Tag getTag();
+ method public String getType();
+ method public boolean isConnected();
+ method public boolean isWritable();
+ method public boolean makeReadOnly() throws java.io.IOException;
+ method public void writeNdefMessage(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
+ field public static final String MIFARE_CLASSIC = "com.nxp.ndef.mifareclassic";
+ field public static final String NFC_FORUM_TYPE_1 = "org.nfcforum.ndef.type1";
+ field public static final String NFC_FORUM_TYPE_2 = "org.nfcforum.ndef.type2";
+ field public static final String NFC_FORUM_TYPE_3 = "org.nfcforum.ndef.type3";
+ field public static final String NFC_FORUM_TYPE_4 = "org.nfcforum.ndef.type4";
+ }
+
+ public final class NdefFormatable implements android.nfc.tech.TagTechnology {
+ method public void close() throws java.io.IOException;
+ method public void connect() throws java.io.IOException;
+ method public void format(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
+ method public void formatReadOnly(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
+ method public static android.nfc.tech.NdefFormatable get(android.nfc.Tag);
+ method public android.nfc.Tag getTag();
+ method public boolean isConnected();
+ }
+
+ public final class NfcA implements android.nfc.tech.TagTechnology {
+ method public void close() throws java.io.IOException;
+ method public void connect() throws java.io.IOException;
+ method public static android.nfc.tech.NfcA get(android.nfc.Tag);
+ method public byte[] getAtqa();
+ method public int getMaxTransceiveLength();
+ method public short getSak();
+ method public android.nfc.Tag getTag();
+ method public int getTimeout();
+ method public boolean isConnected();
+ method public void setTimeout(int);
+ method public byte[] transceive(byte[]) throws java.io.IOException;
+ }
+
+ public final class NfcB implements android.nfc.tech.TagTechnology {
+ method public void close() throws java.io.IOException;
+ method public void connect() throws java.io.IOException;
+ method public static android.nfc.tech.NfcB get(android.nfc.Tag);
+ method public byte[] getApplicationData();
+ method public int getMaxTransceiveLength();
+ method public byte[] getProtocolInfo();
+ method public android.nfc.Tag getTag();
+ method public boolean isConnected();
+ method public byte[] transceive(byte[]) throws java.io.IOException;
+ }
+
+ public final class NfcBarcode implements android.nfc.tech.TagTechnology {
+ method public void close() throws java.io.IOException;
+ method public void connect() throws java.io.IOException;
+ method public static android.nfc.tech.NfcBarcode get(android.nfc.Tag);
+ method public byte[] getBarcode();
+ method public android.nfc.Tag getTag();
+ method public int getType();
+ method public boolean isConnected();
+ field public static final int TYPE_KOVIO = 1; // 0x1
+ field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public final class NfcF implements android.nfc.tech.TagTechnology {
+ method public void close() throws java.io.IOException;
+ method public void connect() throws java.io.IOException;
+ method public static android.nfc.tech.NfcF get(android.nfc.Tag);
+ method public byte[] getManufacturer();
+ method public int getMaxTransceiveLength();
+ method public byte[] getSystemCode();
+ method public android.nfc.Tag getTag();
+ method public int getTimeout();
+ method public boolean isConnected();
+ method public void setTimeout(int);
+ method public byte[] transceive(byte[]) throws java.io.IOException;
+ }
+
+ public final class NfcV implements android.nfc.tech.TagTechnology {
+ method public void close() throws java.io.IOException;
+ method public void connect() throws java.io.IOException;
+ method public static android.nfc.tech.NfcV get(android.nfc.Tag);
+ method public byte getDsfId();
+ method public int getMaxTransceiveLength();
+ method public byte getResponseFlags();
+ method public android.nfc.Tag getTag();
+ method public boolean isConnected();
+ method public byte[] transceive(byte[]) throws java.io.IOException;
+ }
+
+ public interface TagTechnology extends java.io.Closeable {
+ method public void connect() throws java.io.IOException;
+ method public android.nfc.Tag getTag();
+ method public boolean isConnected();
+ }
+
+}
+
diff --git a/nfc/api/lint-baseline.txt b/nfc/api/lint-baseline.txt
new file mode 100644
index 0000000..ef9aab6
--- /dev/null
+++ b/nfc/api/lint-baseline.txt
@@ -0,0 +1,95 @@
+// Baseline format: 1.0
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
+ Field 'ACTION_ADAPTER_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_PREFERRED_PAYMENT_CHANGED:
+ Field 'ACTION_PREFERRED_PAYMENT_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
+ Field 'ACTION_TRANSACTION_DETECTED' is missing @BroadcastBehavior
+
+
+MissingNullability: android.nfc.cardemulation.OffHostApduService#onBind(android.content.Intent):
+ Missing nullability on method `onBind` return
+MissingNullability: android.nfc.cardemulation.OffHostApduService#onBind(android.content.Intent) parameter #0:
+ Missing nullability on parameter `intent` in method `onBind`
+
+
+RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
+ Method 'disableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
+ Method 'enableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
+ Method 'isDefaultServiceForAid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
+ Method 'isDefaultServiceForCategory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
+ Method 'setOffHostForService' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
+ Method 'authenticateSectorWithKeyA' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
+ Method 'authenticateSectorWithKeyB' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
+ Method 'decrement' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
+ Method 'increment' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
+ Method 'readBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
+ Method 'restore' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
+ Method 'transfer' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
+ Method 'writeBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
+ Method 'readPages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
+ Method 'writePage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
+ Method 'getNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#isWritable():
+ Method 'isWritable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
+ Method 'makeReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
+ Method 'writeNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
+ Method 'format' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
+ Method 'formatReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#close():
+ Method 'close' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#connect():
+ Method 'connect' documentation mentions permissions without declaring @RequiresPermission
diff --git a/nfc/api/module-lib-current.txt b/nfc/api/module-lib-current.txt
index d802177..5ebe911 100644
--- a/nfc/api/module-lib-current.txt
+++ b/nfc/api/module-lib-current.txt
@@ -1 +1,10 @@
// Signature format: 2.0
+package android.nfc {
+
+ public class NfcFrameworkInitializer {
+ method public static void registerServiceWrappers();
+ method public static void setNfcServiceManager(@NonNull android.nfc.NfcServiceManager);
+ }
+
+}
+
diff --git a/nfc/api/module-lib-lint-baseline.txt b/nfc/api/module-lib-lint-baseline.txt
new file mode 100644
index 0000000..f7f8ee3
--- /dev/null
+++ b/nfc/api/module-lib-lint-baseline.txt
@@ -0,0 +1,93 @@
+// Baseline format: 1.0
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
+ Field 'ACTION_ADAPTER_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_PREFERRED_PAYMENT_CHANGED:
+ Field 'ACTION_PREFERRED_PAYMENT_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
+ Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
+ Field 'ACTION_TRANSACTION_DETECTED' is missing @BroadcastBehavior
+
+RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
+ Method 'disableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
+ Method 'enableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
+ Method 'isDefaultServiceForAid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
+ Method 'isDefaultServiceForCategory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
+ Method 'setOffHostForService' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
+ Method 'authenticateSectorWithKeyA' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
+ Method 'authenticateSectorWithKeyB' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
+ Method 'decrement' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
+ Method 'increment' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
+ Method 'readBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
+ Method 'restore' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
+ Method 'transfer' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
+ Method 'writeBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
+ Method 'readPages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
+ Method 'writePage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
+ Method 'getNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#isWritable():
+ Method 'isWritable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
+ Method 'makeReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
+ Method 'writeNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
+ Method 'format' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
+ Method 'formatReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#close():
+ Method 'close' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#connect():
+ Method 'connect' documentation mentions permissions without declaring @RequiresPermission
+
+SdkConstant: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
+ Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
diff --git a/nfc/api/removed.txt b/nfc/api/removed.txt
index d802177..fb82b5d 100644
--- a/nfc/api/removed.txt
+++ b/nfc/api/removed.txt
@@ -1 +1,17 @@
// Signature format: 2.0
+package android.nfc {
+
+ public final class NfcAdapter {
+ method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void disableForegroundNdefPush(android.app.Activity);
+ method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
+ method @Deprecated @android.compat.annotation.UnsupportedAppUsage public boolean invokeBeam(android.app.Activity);
+ method @Deprecated @android.compat.annotation.UnsupportedAppUsage public boolean isNdefPushEnabled();
+ method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void setBeamPushUris(android.net.Uri[], android.app.Activity);
+ method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
+ method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
+ method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
+ method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
+ }
+
+}
+
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index d802177..ece8851 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -1 +1,58 @@
// Signature format: 2.0
+package android.nfc {
+
+ public final class NfcAdapter {
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean addNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler, String[]);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable();
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable(boolean);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
+ method @FlaggedApi("android.nfc.enable_nfc_reader_option") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableReaderOption(boolean);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
+ method @FlaggedApi("android.nfc.enable_nfc_mainline") public int getAdapterState();
+ method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int);
+ method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
+ method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagIntentAppPreferenceSupported();
+ method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
+ method @FlaggedApi("android.nfc.nfc_vendor_cmd") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerNfcVendorNciCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.NfcVendorNciCallback);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
+ method @FlaggedApi("android.nfc.nfc_vendor_cmd") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int sendVendorNciMessage(int, @IntRange(from=0, to=15) int, @IntRange(from=0) int, @NonNull byte[]);
+ 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);
+ method @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void unregisterNfcVendorNciCallback(@NonNull android.nfc.NfcAdapter.NfcVendorNciCallback);
+ field @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC = "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC";
+ field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int MESSAGE_TYPE_COMMAND = 1; // 0x1
+ field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_FAILED = 3; // 0x3
+ field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED = 2; // 0x2
+ field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_REJECTED = 1; // 0x1
+ field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_SUCCESS = 0; // 0x0
+ field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff
+ field public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0; // 0x0
+ field public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2; // 0xfffffffe
+ }
+
+ public static interface NfcAdapter.ControllerAlwaysOnListener {
+ method public void onControllerAlwaysOnChanged(boolean);
+ }
+
+ public static interface NfcAdapter.NfcUnlockHandler {
+ method public boolean onUnlockAttempted(android.nfc.Tag);
+ }
+
+ @FlaggedApi("android.nfc.nfc_vendor_cmd") public static interface NfcAdapter.NfcVendorNciCallback {
+ method @FlaggedApi("android.nfc.nfc_vendor_cmd") public void onVendorNciNotification(@IntRange(from=9, to=15) int, int, @NonNull byte[]);
+ method @FlaggedApi("android.nfc.nfc_vendor_cmd") public void onVendorNciResponse(@IntRange(from=0, to=15) int, int, @NonNull byte[]);
+ }
+
+}
+
+package android.nfc.cardemulation {
+
+ public final class CardEmulation {
+ method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int);
+ }
+
+}
+
diff --git a/nfc/api/system-lint-baseline.txt b/nfc/api/system-lint-baseline.txt
new file mode 100644
index 0000000..761c8e6
--- /dev/null
+++ b/nfc/api/system-lint-baseline.txt
@@ -0,0 +1,105 @@
+// Baseline format: 1.0
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
+ Field 'ACTION_ADAPTER_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_PREFERRED_PAYMENT_CHANGED:
+ Field 'ACTION_PREFERRED_PAYMENT_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
+ Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
+ Field 'ACTION_TRANSACTION_DETECTED' is missing @BroadcastBehavior
+
+
+MissingNullability: android.nfc.cardemulation.OffHostApduService#onBind(android.content.Intent):
+ Missing nullability on method `onBind` return
+MissingNullability: android.nfc.cardemulation.OffHostApduService#onBind(android.content.Intent) parameter #0:
+ Missing nullability on parameter `intent` in method `onBind`
+
+
+RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
+ Method 'disableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
+ Method 'enableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
+ Method 'isDefaultServiceForAid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
+ Method 'isDefaultServiceForCategory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
+ Method 'setOffHostForService' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
+ Method 'authenticateSectorWithKeyA' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
+ Method 'authenticateSectorWithKeyB' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
+ Method 'decrement' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
+ Method 'increment' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
+ Method 'readBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
+ Method 'restore' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
+ Method 'transfer' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
+ Method 'writeBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
+ Method 'readPages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
+ Method 'writePage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
+ Method 'getNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#isWritable():
+ Method 'isWritable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
+ Method 'makeReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
+ Method 'writeNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
+ Method 'format' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
+ Method 'formatReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#getTimeout():
+ Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
+ Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
+ Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#close():
+ Method 'close' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#connect():
+ Method 'connect' documentation mentions permissions without declaring @RequiresPermission
+
+SamShouldBeLast: android.nfc.NfcAdapter#enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle):
+ SAM-compatible parameters (such as parameter 2, "callback", in android.nfc.NfcAdapter.enableReaderMode) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.nfc.NfcAdapter#ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 3, "tagRemovedListener", in android.nfc.NfcAdapter.ignore) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+
+SdkConstant: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
+ Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
diff --git a/nfc/api/system-removed.txt b/nfc/api/system-removed.txt
index d802177..c6eaa57 100644
--- a/nfc/api/system-removed.txt
+++ b/nfc/api/system-removed.txt
@@ -1 +1,12 @@
// Signature format: 2.0
+package android.nfc {
+
+ public final class NfcAdapter {
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush();
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
+ method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
+ field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
+ }
+
+}
+
diff --git a/nfc/jarjar-rules.txt b/nfc/jarjar-rules.txt
new file mode 100644
index 0000000..4cd652d
--- /dev/null
+++ b/nfc/jarjar-rules.txt
@@ -0,0 +1,38 @@
+# Used by framework-nfc for proto debug dumping
+rule android.app.PendingIntentProto* com.android.nfc.x.@0
+rule android.content.ComponentNameProto* com.android.nfc.x.@0
+rule android.content.IntentProto* com.android.nfc.x.@0
+rule android.content.IntentFilterProto* com.android.nfc.x.@0
+rule android.content.AuthorityEntryProto* com.android.nfc.x.@0
+rule android.nfc.cardemulation.AidGroupProto* com.android.nfc.x.@0
+rule android.nfc.cardemulation.ApduServiceInfoProto* com.android.nfc.x.@0
+rule android.nfc.cardemulation.NfcFServiceInfoProto* com.android.nfc.x.@0
+rule android.nfc.NdefMessageProto* com.android.nfc.x.@0
+rule android.nfc.NdefRecordProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.CardEmulationManagerProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.RegisteredServicesCacheProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.RegisteredNfcFServicesCacheProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.PreferredServicesProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.EnabledNfcFServicesProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.RegisteredAidCacheProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.AidRoutingManagerProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.RegisteredT3tIdentifiersCacheProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.SystemCodeRoutingManagerProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.HostEmulationManagerProto* com.android.nfc.x.@0
+rule com.android.nfc.cardemulation.HostNfcFEmulationManagerProto* com.android.nfc.x.@0
+rule com.android.nfc.NfcServiceDumpProto* com.android.nfc.x.@0
+rule com.android.nfc.DiscoveryParamsProto* com.android.nfc.x.@0
+rule com.android.nfc.NfcDispatcherProto* com.android.nfc.x.@0
+rule android.os.PersistableBundleProto* com.android.nfc.x.@0
+
+# Used by framework-nfc for reading trunk stable flags
+rule android.nfc.FakeFeatureFlagsImpl* com.android.nfc.x.@0
+rule android.nfc.FeatureFlags* com.android.nfc.x.@0
+rule android.nfc.Flags* com.android.nfc.x.@0
+rule android.permission.flags.** com.android.nfc.x.@0
+
+# Used by framework-nfc for misc utilities
+rule android.os.PatternMatcher* com.android.nfc.x.@0
+
+rule com.android.incident.Privacy* com.android.nfc.x.@0
+rule com.android.incident.PrivacyFlags* com.android.nfc.x.@0
diff --git a/core/java/android/nfc/ApduList.aidl b/nfc/java/android/nfc/ApduList.aidl
similarity index 100%
rename from core/java/android/nfc/ApduList.aidl
rename to nfc/java/android/nfc/ApduList.aidl
diff --git a/core/java/android/nfc/ApduList.java b/nfc/java/android/nfc/ApduList.java
similarity index 100%
rename from core/java/android/nfc/ApduList.java
rename to nfc/java/android/nfc/ApduList.java
diff --git a/core/java/android/nfc/AvailableNfcAntenna.aidl b/nfc/java/android/nfc/AvailableNfcAntenna.aidl
similarity index 100%
rename from core/java/android/nfc/AvailableNfcAntenna.aidl
rename to nfc/java/android/nfc/AvailableNfcAntenna.aidl
diff --git a/core/java/android/nfc/AvailableNfcAntenna.java b/nfc/java/android/nfc/AvailableNfcAntenna.java
similarity index 100%
rename from core/java/android/nfc/AvailableNfcAntenna.java
rename to nfc/java/android/nfc/AvailableNfcAntenna.java
diff --git a/core/java/android/nfc/Constants.java b/nfc/java/android/nfc/Constants.java
similarity index 100%
rename from core/java/android/nfc/Constants.java
rename to nfc/java/android/nfc/Constants.java
diff --git a/core/java/android/nfc/ErrorCodes.java b/nfc/java/android/nfc/ErrorCodes.java
similarity index 100%
rename from core/java/android/nfc/ErrorCodes.java
rename to nfc/java/android/nfc/ErrorCodes.java
diff --git a/core/java/android/nfc/FormatException.java b/nfc/java/android/nfc/FormatException.java
similarity index 100%
rename from core/java/android/nfc/FormatException.java
rename to nfc/java/android/nfc/FormatException.java
diff --git a/core/java/android/nfc/IAppCallback.aidl b/nfc/java/android/nfc/IAppCallback.aidl
similarity index 100%
rename from core/java/android/nfc/IAppCallback.aidl
rename to nfc/java/android/nfc/IAppCallback.aidl
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl
similarity index 90%
rename from core/java/android/nfc/INfcAdapter.aidl
rename to nfc/java/android/nfc/INfcAdapter.aidl
index f6beec1..8fea5af 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/nfc/java/android/nfc/INfcAdapter.aidl
@@ -24,6 +24,7 @@
import android.nfc.IAppCallback;
import android.nfc.INfcAdapterExtras;
import android.nfc.INfcControllerAlwaysOnListener;
+import android.nfc.INfcVendorNciCallback;
import android.nfc.INfcTag;
import android.nfc.INfcCardEmulation;
import android.nfc.INfcFCardEmulation;
@@ -86,4 +87,8 @@
boolean enableReaderOption(boolean enable);
boolean isObserveModeSupported();
boolean setObserveMode(boolean enabled);
+ void updateDiscoveryTechnology(IBinder b, int pollFlags, int listenFlags);
+ int sendVendorNciMessage(int mt, int gid, int oid, in byte[] payload);
+ void registerVendorExtensionCallback(in INfcVendorNciCallback callbacks);
+ void unregisterVendorExtensionCallback(in INfcVendorNciCallback callbacks);
}
diff --git a/core/java/android/nfc/INfcAdapterExtras.aidl b/nfc/java/android/nfc/INfcAdapterExtras.aidl
similarity index 100%
rename from core/java/android/nfc/INfcAdapterExtras.aidl
rename to nfc/java/android/nfc/INfcAdapterExtras.aidl
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl
similarity index 94%
rename from core/java/android/nfc/INfcCardEmulation.aidl
rename to nfc/java/android/nfc/INfcCardEmulation.aidl
index 191385a..f4b4604 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/nfc/java/android/nfc/INfcCardEmulation.aidl
@@ -43,4 +43,7 @@
ApduServiceInfo getPreferredPaymentService(int userHandle);
boolean setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status);
boolean isDefaultPaymentRegistered();
+
+ boolean overrideRoutingTable(int userHandle, String protocol, String technology);
+ boolean recoverRoutingTable(int userHandle);
}
diff --git a/core/java/android/nfc/INfcControllerAlwaysOnListener.aidl b/nfc/java/android/nfc/INfcControllerAlwaysOnListener.aidl
similarity index 100%
rename from core/java/android/nfc/INfcControllerAlwaysOnListener.aidl
rename to nfc/java/android/nfc/INfcControllerAlwaysOnListener.aidl
diff --git a/core/java/android/nfc/INfcDta.aidl b/nfc/java/android/nfc/INfcDta.aidl
similarity index 100%
rename from core/java/android/nfc/INfcDta.aidl
rename to nfc/java/android/nfc/INfcDta.aidl
diff --git a/core/java/android/nfc/INfcFCardEmulation.aidl b/nfc/java/android/nfc/INfcFCardEmulation.aidl
similarity index 100%
rename from core/java/android/nfc/INfcFCardEmulation.aidl
rename to nfc/java/android/nfc/INfcFCardEmulation.aidl
diff --git a/core/java/android/nfc/INfcTag.aidl b/nfc/java/android/nfc/INfcTag.aidl
similarity index 100%
rename from core/java/android/nfc/INfcTag.aidl
rename to nfc/java/android/nfc/INfcTag.aidl
diff --git a/core/java/android/nfc/INfcUnlockHandler.aidl b/nfc/java/android/nfc/INfcUnlockHandler.aidl
similarity index 100%
rename from core/java/android/nfc/INfcUnlockHandler.aidl
rename to nfc/java/android/nfc/INfcUnlockHandler.aidl
diff --git a/nfc/java/android/nfc/INfcVendorNciCallback.aidl b/nfc/java/android/nfc/INfcVendorNciCallback.aidl
new file mode 100644
index 0000000..821dc6f
--- /dev/null
+++ b/nfc/java/android/nfc/INfcVendorNciCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
+ */
+oneway interface INfcVendorNciCallback {
+ void onVendorResponseReceived(int gid, int oid, in byte[] payload);
+ void onVendorNotificationReceived(int gid, int oid, in byte[] payload);
+}
diff --git a/core/java/android/nfc/ITagRemovedCallback.aidl b/nfc/java/android/nfc/ITagRemovedCallback.aidl
similarity index 100%
rename from core/java/android/nfc/ITagRemovedCallback.aidl
rename to nfc/java/android/nfc/ITagRemovedCallback.aidl
diff --git a/core/java/android/nfc/NdefMessage.aidl b/nfc/java/android/nfc/NdefMessage.aidl
similarity index 100%
rename from core/java/android/nfc/NdefMessage.aidl
rename to nfc/java/android/nfc/NdefMessage.aidl
diff --git a/core/java/android/nfc/NdefMessage.java b/nfc/java/android/nfc/NdefMessage.java
similarity index 100%
rename from core/java/android/nfc/NdefMessage.java
rename to nfc/java/android/nfc/NdefMessage.java
diff --git a/core/java/android/nfc/NdefRecord.aidl b/nfc/java/android/nfc/NdefRecord.aidl
similarity index 100%
rename from core/java/android/nfc/NdefRecord.aidl
rename to nfc/java/android/nfc/NdefRecord.aidl
diff --git a/core/java/android/nfc/NdefRecord.java b/nfc/java/android/nfc/NdefRecord.java
similarity index 100%
rename from core/java/android/nfc/NdefRecord.java
rename to nfc/java/android/nfc/NdefRecord.java
diff --git a/core/java/android/nfc/NfcActivityManager.java b/nfc/java/android/nfc/NfcActivityManager.java
similarity index 79%
rename from core/java/android/nfc/NfcActivityManager.java
rename to nfc/java/android/nfc/NfcActivityManager.java
index 8d75cac..f03fc0a 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/nfc/java/android/nfc/NfcActivityManager.java
@@ -112,6 +112,9 @@
Bundle readerModeExtras = null;
Binder token;
+ int mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ int mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
+
public NfcActivityState(Activity activity) {
if (activity.isDestroyed()) {
throw new IllegalStateException("activity is already destroyed");
@@ -132,6 +135,9 @@
readerModeFlags = 0;
readerModeExtras = null;
token = null;
+
+ mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
}
@Override
public String toString() {
@@ -278,6 +284,9 @@
int readerModeFlags = 0;
Bundle readerModeExtras = null;
Binder token;
+ int pollTech;
+ int listenTech;
+
synchronized (NfcActivityManager.this) {
NfcActivityState state = findActivityState(activity);
if (DBG) Log.d(TAG, "onResume() for " + activity + " " + state);
@@ -286,9 +295,15 @@
token = state.token;
readerModeFlags = state.readerModeFlags;
readerModeExtras = state.readerModeExtras;
+
+ pollTech = state.mPollTech;
+ listenTech = state.mListenTech;
}
if (readerModeFlags != 0) {
setReaderMode(token, readerModeFlags, readerModeExtras);
+ } else if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH
+ || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) {
+ changeDiscoveryTech(token, pollTech, listenTech);
}
requestNfcServiceCallback();
}
@@ -298,6 +313,9 @@
public void onActivityPaused(Activity activity) {
boolean readerModeFlagsSet;
Binder token;
+ int pollTech;
+ int listenTech;
+
synchronized (NfcActivityManager.this) {
NfcActivityState state = findActivityState(activity);
if (DBG) Log.d(TAG, "onPause() for " + activity + " " + state);
@@ -305,10 +323,17 @@
state.resumed = false;
token = state.token;
readerModeFlagsSet = state.readerModeFlags != 0;
+
+ pollTech = state.mPollTech;
+ listenTech = state.mListenTech;
}
if (readerModeFlagsSet) {
// Restore default p2p modes
setReaderMode(token, 0, null);
+ } else if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH
+ || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) {
+ changeDiscoveryTech(token,
+ NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH);
}
}
@@ -333,4 +358,53 @@
}
}
+ /** setDiscoveryTechnology() implementation */
+ public void setDiscoveryTech(Activity activity, int pollTech, int listenTech) {
+ boolean isResumed;
+ Binder token;
+ boolean readerModeFlagsSet;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ readerModeFlagsSet = state.readerModeFlags != 0;
+ state.mListenTech = listenTech;
+ state.mPollTech = pollTech;
+ token = state.token;
+ isResumed = state.resumed;
+ }
+ if (!readerModeFlagsSet && isResumed) {
+ changeDiscoveryTech(token, pollTech, listenTech);
+ } else if (readerModeFlagsSet) {
+ throw new IllegalStateException("Cannot be used when the Reader Mode is enabled");
+ }
+ }
+
+ /** resetDiscoveryTechnology() implementation */
+ public void resetDiscoveryTech(Activity activity) {
+ boolean isResumed;
+ Binder token;
+ boolean readerModeFlagsSet;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ readerModeFlagsSet = state.readerModeFlags != 0;
+ state.mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ state.mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
+ token = state.token;
+ isResumed = state.resumed;
+ }
+ if (readerModeFlagsSet) {
+ disableReaderMode(activity);
+ } else if (isResumed) {
+ changeDiscoveryTech(token, NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH);
+ }
+
+ }
+
+ private void changeDiscoveryTech(Binder token, int pollTech, int listenTech) {
+ try {
+ NfcAdapter.sService.updateDiscoveryTechnology(token, pollTech, listenTech);
+ } catch (RemoteException e) {
+ mAdapter.attemptDeadServiceRecovery(e);
+ }
+ }
+
}
diff --git a/core/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
similarity index 88%
rename from core/java/android/nfc/NfcAdapter.java
rename to nfc/java/android/nfc/NfcAdapter.java
index 98a980f..40bbe74 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -19,6 +19,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -75,6 +76,7 @@
static final String TAG = "NFC";
private final NfcControllerAlwaysOnListener mControllerAlwaysOnListener;
+ private final NfcVendorNciCallbackListener mNfcVendorNciCallbackListener;
/**
* Intent to start an activity when a tag with NDEF payload is discovered.
@@ -284,6 +286,20 @@
public static final int STATE_TURNING_OFF = 4;
/**
+ * Possible states from {@link #getAdapterState}.
+ *
+ * @hide
+ */
+ @IntDef(prefix = { "STATE_" }, value = {
+ STATE_OFF,
+ STATE_TURNING_ON,
+ STATE_ON,
+ STATE_TURNING_OFF
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AdapterState{}
+
+ /**
* Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
* <p>
* Setting this flag enables polling for Nfc-A technology.
@@ -318,6 +334,19 @@
*/
public static final int FLAG_READER_NFC_BARCODE = 0x10;
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_READER_"}, value = {
+ FLAG_READER_KEEP,
+ FLAG_READER_DISABLE,
+ FLAG_READER_NFC_A,
+ FLAG_READER_NFC_B,
+ FLAG_READER_NFC_F,
+ FLAG_READER_NFC_V,
+ FLAG_READER_NFC_BARCODE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PollTechnology {}
+
/**
* Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
* <p>
@@ -345,6 +374,76 @@
public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
/**
+ * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag enables listening for Nfc-A technology.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_NFC_PASSIVE_A = 0x1;
+
+ /**
+ * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag enables listening for Nfc-B technology.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_NFC_PASSIVE_B = 1 << 1;
+
+ /**
+ * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag enables listening for Nfc-F technology.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_NFC_PASSIVE_F = 1 << 2;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag disables listening.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_DISABLE = 0x0;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag disables polling.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_READER_DISABLE = 0x0;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag makes listening to keep the current technology configuration.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_KEEP = 0x80000000;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag makes polling to keep the current technology configuration.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_READER_KEEP = 0x80000000;
+
+ /** @hide */
+ public static final int FLAG_USE_ALL_TECH = 0xff;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_LISTEN_"}, value = {
+ FLAG_LISTEN_KEEP,
+ FLAG_LISTEN_DISABLE,
+ FLAG_LISTEN_NFC_PASSIVE_A,
+ FLAG_LISTEN_NFC_PASSIVE_B,
+ FLAG_LISTEN_NFC_PASSIVE_F
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ListenTechnology {}
+
+ /**
* @hide
* @removed
*/
@@ -422,11 +521,13 @@
@Retention(RetentionPolicy.SOURCE)
public @interface TagIntentAppPreferenceResult {}
- // Guarded by NfcAdapter.class
+ // Guarded by sLock
static boolean sIsInitialized = false;
static boolean sHasNfcFeature;
static boolean sHasCeFeature;
+ static Object sLock = new Object();
+
// Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
// recovery
@@ -762,6 +863,7 @@
mTagRemovedListener = null;
mLock = new Object();
mControllerAlwaysOnListener = new NfcControllerAlwaysOnListener(getService());
+ mNfcVendorNciCallbackListener = new NfcVendorNciCallbackListener(getService());
}
/**
@@ -948,7 +1050,7 @@
*/
@SystemApi
@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public int getAdapterState() {
+ public @AdapterState int getAdapterState() {
try {
return sService.getState();
} catch (RemoteException e) {
@@ -1216,7 +1318,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public void setBeamPushUris(Uri[] uris, Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1286,7 +1388,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1371,7 +1473,7 @@
@UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity,
Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1385,7 +1487,7 @@
@SystemApi
@UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1464,7 +1566,7 @@
@UnsupportedAppUsage
public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1515,7 +1617,7 @@
@UnsupportedAppUsage
public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
Activity activity, Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1558,7 +1660,7 @@
*/
public void enableForegroundDispatch(Activity activity, PendingIntent intent,
IntentFilter[] filters, String[][] techLists) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1593,7 +1695,7 @@
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/
public void disableForegroundDispatch(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1629,7 +1731,7 @@
*/
public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
Bundle extras) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1646,7 +1748,7 @@
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
*/
public void disableReaderMode(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1674,7 +1776,7 @@
@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
@SuppressLint("VisiblySynchronized")
public void setReaderMode(boolean enablePolling) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1689,6 +1791,91 @@
}
/**
+ * Set the NFC controller to enable specific poll/listen technologies,
+ * as specified in parameters, while this Activity is in the foreground.
+ *
+ * Use {@link #FLAG_READER_KEEP} to keep current polling technology.
+ * Use {@link #FLAG_LISTEN_KEEP} to keep current listenig technology.
+ * (if the _KEEP flag is specified the other technology flags shouldn't be set
+ * and are quietly ignored otherwise).
+ * Use {@link #FLAG_READER_DISABLE} to disable polling.
+ * Use {@link #FLAG_LISTEN_DISABLE} to disable listening.
+ * Also refer to {@link #resetDiscoveryTechnology(Activity)} to restore these changes.
+ * </p>
+ * The pollTechnology, listenTechnology parameters can be one or several of below list.
+ * <pre>
+ * Poll Listen
+ * Passive A 0x01 (NFC_A) 0x01 (NFC_PASSIVE_A)
+ * Passive B 0x02 (NFC_B) 0x02 (NFC_PASSIVE_B)
+ * Passive F 0x04 (NFC_F) 0x04 (NFC_PASSIVE_F)
+ * ISO 15693 0x08 (NFC_V) -
+ * Kovio 0x10 (NFC_BARCODE) -
+ * </pre>
+ * <p>Example usage in an Activity that requires to disable poll,
+ * keep current listen technologies:
+ * <pre>
+ * protected void onResume() {
+ * mNfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());
+ * mNfcAdapter.setDiscoveryTechnology(this,
+ * NfcAdapter.FLAG_READER_DISABLE, NfcAdapter.FLAG_LISTEN_KEEP);
+ * }</pre></p>
+ * @param activity The Activity that requests NFC controller to enable specific technologies.
+ * @param pollTechnology Flags indicating poll technologies.
+ * @param listenTechnology Flags indicating listen technologies.
+ * @throws UnsupportedOperationException if FEATURE_NFC,
+ * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF are unavailable.
+ */
+
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public void setDiscoveryTechnology(@NonNull Activity activity,
+ @PollTechnology int pollTechnology, @ListenTechnology int listenTechnology) {
+
+ // A special treatment of the _KEEP flags
+ if ((listenTechnology & FLAG_LISTEN_KEEP) != 0) {
+ listenTechnology = -1;
+ }
+ if ((pollTechnology & FLAG_READER_KEEP) != 0) {
+ pollTechnology = -1;
+ }
+
+ if (listenTechnology == FLAG_LISTEN_DISABLE) {
+ synchronized (sLock) {
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ mNfcActivityManager.enableReaderMode(activity, null, pollTechnology, null);
+ return;
+ }
+ if (pollTechnology == FLAG_READER_DISABLE) {
+ synchronized (sLock) {
+ if (!sHasCeFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ } else {
+ synchronized (sLock) {
+ if (!sHasNfcFeature || !sHasCeFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ }
+ mNfcActivityManager.setDiscoveryTech(activity, pollTechnology, listenTechnology);
+ }
+
+ /**
+ * Restore the poll/listen technologies of NFC controller to its default state,
+ * which were changed by {@link #setDiscoveryTechnology(Activity , int , int)}
+ *
+ * @param activity The Activity that requested to change technologies.
+ */
+
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public void resetDiscoveryTechnology(@NonNull Activity activity) {
+ mNfcActivityManager.resetDiscoveryTech(activity);
+ }
+
+ /**
* Manually invoke Android Beam to share data.
*
* <p>The Android Beam animation is normally only shown when two NFC-capable
@@ -1718,7 +1905,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public boolean invokeBeam(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1756,7 +1943,7 @@
@Deprecated
@UnsupportedAppUsage
public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1786,7 +1973,7 @@
@Deprecated
@UnsupportedAppUsage
public void disableForegroundNdefPush(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2066,7 +2253,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public boolean isNdefPushEnabled() {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2180,7 +2367,7 @@
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler,
String[] tagTechnologies) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2229,7 +2416,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2573,4 +2760,163 @@
return false;
}
}
+
+ /**
+ * Vendor NCI command success.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
+ public static final int SEND_VENDOR_NCI_STATUS_SUCCESS = 0;
+ /**
+ * Vendor NCI command rejected.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
+ public static final int SEND_VENDOR_NCI_STATUS_REJECTED = 1;
+ /**
+ * Vendor NCI command corrupted.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
+ public static final int SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED = 2;
+ /**
+ * Vendor NCI command failed with unknown reason.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
+ public static final int SEND_VENDOR_NCI_STATUS_FAILED = 3;
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ SEND_VENDOR_NCI_STATUS_SUCCESS,
+ SEND_VENDOR_NCI_STATUS_REJECTED,
+ SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED,
+ SEND_VENDOR_NCI_STATUS_FAILED,
+ })
+ @interface SendVendorNciStatus {}
+
+ /**
+ * Message Type for NCI Command.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
+ public static final int MESSAGE_TYPE_COMMAND = 1;
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ MESSAGE_TYPE_COMMAND,
+ })
+ @interface MessageType {}
+
+ /**
+ * Send Vendor specific Nci Messages with custom message type.
+ *
+ * The format of the NCI messages are defined in the NCI specification. The platform is
+ * responsible for fragmenting the payload if necessary.
+ *
+ * Note that mt (message type) is added at the beginning of method parameters as it is more
+ * distinctive than other parameters and was requested from vendor.
+ *
+ * @param mt message Type of the command
+ * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from
+ * the NCI specification
+ * @param oid opcode ID of the command. This is left to the OEM / vendor to decide
+ * @param payload containing vendor Nci message payload
+ * @return message send status
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ public @SendVendorNciStatus int sendVendorNciMessage(@MessageType int mt,
+ @IntRange(from = 0, to = 15) int gid, @IntRange(from = 0) int oid,
+ @NonNull byte[] payload) {
+ Objects.requireNonNull(payload, "Payload must not be null");
+ try {
+ return sService.sendVendorNciMessage(mt, gid, oid, payload);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Register an {@link NfcVendorNciCallback} to listen for Nfc vendor responses and notifications
+ * <p>The provided callback will be invoked by the given {@link Executor}.
+ *
+ * <p>When first registering a callback, the callbacks's
+ * {@link NfcVendorNciCallback#onVendorNciCallBack(byte[])} is immediately invoked to
+ * notify the vendor notification.
+ *
+ * @param executor an {@link Executor} to execute given callback
+ * @param callback user implementation of the {@link NfcVendorNciCallback}
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ public void registerNfcVendorNciCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull NfcVendorNciCallback callback) {
+ mNfcVendorNciCallbackListener.register(executor, callback);
+ }
+
+ /**
+ * Unregister the specified {@link NfcVendorNciCallback}
+ *
+ * <p>The same {@link NfcVendorNciCallback} object used when calling
+ * {@link #registerNfcVendorNciCallback(Executor, NfcVendorNciCallback)} must be used.
+ *
+ * <p>Callbacks are automatically unregistered when application process goes away
+ *
+ * @param callback user implementation of the {@link NfcVendorNciCallback}
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ public void unregisterNfcVendorNciCallback(@NonNull NfcVendorNciCallback callback) {
+ mNfcVendorNciCallbackListener.unregister(callback);
+ }
+
+ /**
+ * Interface for receiving vendor NCI responses and notifications.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
+ public interface NfcVendorNciCallback {
+ /**
+ * Invoked when a vendor specific NCI response is received.
+ *
+ * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from
+ * the NCI specification.
+ * @param oid opcode ID of the command. This is left to the OEM / vendor to decide.
+ * @param payload containing vendor Nci message payload.
+ */
+ @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
+ void onVendorNciResponse(
+ @IntRange(from = 0, to = 15) int gid, int oid, @NonNull byte[] payload);
+
+ /**
+ * Invoked when a vendor specific NCI notification is received.
+ *
+ * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from
+ * the NCI specification.
+ * @param oid opcode ID of the command. This is left to the OEM / vendor to decide.
+ * @param payload containing vendor Nci message payload.
+ */
+ @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
+ void onVendorNciNotification(
+ @IntRange(from = 9, to = 15) int gid, int oid, @NonNull byte[] payload);
+ }
}
diff --git a/core/java/android/nfc/NfcAntennaInfo.aidl b/nfc/java/android/nfc/NfcAntennaInfo.aidl
similarity index 100%
rename from core/java/android/nfc/NfcAntennaInfo.aidl
rename to nfc/java/android/nfc/NfcAntennaInfo.aidl
diff --git a/core/java/android/nfc/NfcAntennaInfo.java b/nfc/java/android/nfc/NfcAntennaInfo.java
similarity index 100%
rename from core/java/android/nfc/NfcAntennaInfo.java
rename to nfc/java/android/nfc/NfcAntennaInfo.java
diff --git a/core/java/android/nfc/NfcControllerAlwaysOnListener.java b/nfc/java/android/nfc/NfcControllerAlwaysOnListener.java
similarity index 100%
rename from core/java/android/nfc/NfcControllerAlwaysOnListener.java
rename to nfc/java/android/nfc/NfcControllerAlwaysOnListener.java
diff --git a/core/java/android/nfc/NfcEvent.java b/nfc/java/android/nfc/NfcEvent.java
similarity index 100%
rename from core/java/android/nfc/NfcEvent.java
rename to nfc/java/android/nfc/NfcEvent.java
diff --git a/core/java/android/nfc/NfcFrameworkInitializer.java b/nfc/java/android/nfc/NfcFrameworkInitializer.java
similarity index 100%
rename from core/java/android/nfc/NfcFrameworkInitializer.java
rename to nfc/java/android/nfc/NfcFrameworkInitializer.java
diff --git a/core/java/android/nfc/NfcManager.java b/nfc/java/android/nfc/NfcManager.java
similarity index 100%
rename from core/java/android/nfc/NfcManager.java
rename to nfc/java/android/nfc/NfcManager.java
diff --git a/core/java/android/nfc/NfcServiceManager.java b/nfc/java/android/nfc/NfcServiceManager.java
similarity index 100%
rename from core/java/android/nfc/NfcServiceManager.java
rename to nfc/java/android/nfc/NfcServiceManager.java
diff --git a/nfc/java/android/nfc/NfcVendorNciCallbackListener.java b/nfc/java/android/nfc/NfcVendorNciCallbackListener.java
new file mode 100644
index 0000000..742d75f
--- /dev/null
+++ b/nfc/java/android/nfc/NfcVendorNciCallbackListener.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import android.annotation.NonNull;
+import android.nfc.NfcAdapter.NfcVendorNciCallback;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ */
+public final class NfcVendorNciCallbackListener extends INfcVendorNciCallback.Stub {
+ private static final String TAG = "Nfc.NfcVendorNciCallbacks";
+ private final INfcAdapter mAdapter;
+ private boolean mIsRegistered = false;
+ private final Map<NfcVendorNciCallback, Executor> mCallbackMap = new HashMap<>();
+
+ public NfcVendorNciCallbackListener(@NonNull INfcAdapter adapter) {
+ mAdapter = adapter;
+ }
+
+ public void register(@NonNull Executor executor, @NonNull NfcVendorNciCallback callback) {
+ synchronized (this) {
+ if (mCallbackMap.containsKey(callback)) {
+ return;
+ }
+ mCallbackMap.put(callback, executor);
+ if (!mIsRegistered) {
+ try {
+ mAdapter.registerVendorExtensionCallback(this);
+ mIsRegistered = true;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to register adapter state callback");
+ mCallbackMap.remove(callback);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
+
+ public void unregister(@NonNull NfcVendorNciCallback callback) {
+ synchronized (this) {
+ if (!mCallbackMap.containsKey(callback) || !mIsRegistered) {
+ return;
+ }
+ if (mCallbackMap.size() == 1) {
+ try {
+ mAdapter.unregisterVendorExtensionCallback(this);
+ mIsRegistered = false;
+ mCallbackMap.remove(callback);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to unregister AdapterStateCallback with service");
+ throw e.rethrowFromSystemServer();
+ }
+ } else {
+ mCallbackMap.remove(callback);
+ }
+ }
+ }
+
+ @Override
+ public void onVendorResponseReceived(int gid, int oid, @NonNull byte[] payload)
+ throws RemoteException {
+ synchronized (this) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ for (NfcVendorNciCallback callback : mCallbackMap.keySet()) {
+ Executor executor = mCallbackMap.get(callback);
+ executor.execute(() -> callback.onVendorNciResponse(gid, oid, payload));
+ }
+ } catch (RuntimeException ex) {
+ throw ex;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ @Override
+ public void onVendorNotificationReceived(int gid, int oid, @NonNull byte[] payload)
+ throws RemoteException {
+ synchronized (this) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ for (NfcVendorNciCallback callback : mCallbackMap.keySet()) {
+ Executor executor = mCallbackMap.get(callback);
+ executor.execute(() -> callback.onVendorNciNotification(gid, oid, payload));
+ }
+ } catch (RuntimeException ex) {
+ throw ex;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+}
diff --git a/core/java/android/nfc/Tag.aidl b/nfc/java/android/nfc/Tag.aidl
similarity index 100%
rename from core/java/android/nfc/Tag.aidl
rename to nfc/java/android/nfc/Tag.aidl
diff --git a/core/java/android/nfc/Tag.java b/nfc/java/android/nfc/Tag.java
similarity index 100%
rename from core/java/android/nfc/Tag.java
rename to nfc/java/android/nfc/Tag.java
diff --git a/core/java/android/nfc/TagLostException.java b/nfc/java/android/nfc/TagLostException.java
similarity index 100%
rename from core/java/android/nfc/TagLostException.java
rename to nfc/java/android/nfc/TagLostException.java
diff --git a/core/java/android/nfc/TechListParcel.aidl b/nfc/java/android/nfc/TechListParcel.aidl
similarity index 100%
rename from core/java/android/nfc/TechListParcel.aidl
rename to nfc/java/android/nfc/TechListParcel.aidl
diff --git a/core/java/android/nfc/TechListParcel.java b/nfc/java/android/nfc/TechListParcel.java
similarity index 100%
rename from core/java/android/nfc/TechListParcel.java
rename to nfc/java/android/nfc/TechListParcel.java
diff --git a/core/java/android/nfc/TransceiveResult.aidl b/nfc/java/android/nfc/TransceiveResult.aidl
similarity index 100%
rename from core/java/android/nfc/TransceiveResult.aidl
rename to nfc/java/android/nfc/TransceiveResult.aidl
diff --git a/core/java/android/nfc/TransceiveResult.java b/nfc/java/android/nfc/TransceiveResult.java
similarity index 100%
rename from core/java/android/nfc/TransceiveResult.java
rename to nfc/java/android/nfc/TransceiveResult.java
diff --git a/core/java/android/nfc/cardemulation/AidGroup.aidl b/nfc/java/android/nfc/cardemulation/AidGroup.aidl
similarity index 100%
rename from core/java/android/nfc/cardemulation/AidGroup.aidl
rename to nfc/java/android/nfc/cardemulation/AidGroup.aidl
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/nfc/java/android/nfc/cardemulation/AidGroup.java
similarity index 100%
rename from core/java/android/nfc/cardemulation/AidGroup.java
rename to nfc/java/android/nfc/cardemulation/AidGroup.java
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.aidl b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.aidl
similarity index 100%
rename from core/java/android/nfc/cardemulation/ApduServiceInfo.aidl
rename to nfc/java/android/nfc/cardemulation/ApduServiceInfo.aidl
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
similarity index 98%
rename from core/java/android/nfc/cardemulation/ApduServiceInfo.java
rename to nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
index e331c95..41dee3a 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -21,10 +21,10 @@
package android.nfc.cardemulation;
import android.annotation.FlaggedApi;
-import android.compat.annotation.UnsupportedAppUsage;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -130,7 +130,7 @@
/**
* State of the service for CATEGORY_OTHER selection
*/
- private boolean mOtherServiceEnabled;
+ private boolean mCategoryOtherServiceEnabled;
/**
* @hide
@@ -183,7 +183,7 @@
this.mBannerResourceId = bannerResource;
this.mUid = uid;
this.mSettingsActivityName = settingsActivityName;
- this.mOtherServiceEnabled = isEnabled;
+ this.mCategoryOtherServiceEnabled = isEnabled;
}
@@ -374,7 +374,7 @@
// Set uid
mUid = si.applicationInfo.uid;
- mOtherServiceEnabled = false; // support other category
+ mCategoryOtherServiceEnabled = true; // support other category
}
@@ -746,7 +746,7 @@
dest.writeInt(mUid);
dest.writeString(mSettingsActivityName);
- dest.writeInt(mOtherServiceEnabled ? 1 : 0);
+ dest.writeInt(mCategoryOtherServiceEnabled ? 1 : 0);
};
@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
@@ -809,7 +809,7 @@
pw.println(" Static AID groups:");
for (AidGroup group : mStaticAidGroups.values()) {
pw.println(" Category: " + group.getCategory()
- + "(enabled: " + mOtherServiceEnabled + ")");
+ + "(enabled: " + mCategoryOtherServiceEnabled + ")");
for (String aid : group.getAids()) {
pw.println(" AID: " + aid);
}
@@ -817,7 +817,7 @@
pw.println(" Dynamic AID groups:");
for (AidGroup group : mDynamicAidGroups.values()) {
pw.println(" Category: " + group.getCategory()
- + "(enabled: " + mOtherServiceEnabled + ")");
+ + "(enabled: " + mCategoryOtherServiceEnabled + ")");
for (String aid : group.getAids()) {
pw.println(" AID: " + aid);
}
@@ -834,8 +834,8 @@
* @param enabled true to indicate if user has enabled this service
*/
@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void setOtherServiceEnabled(boolean enabled) {
- mOtherServiceEnabled = enabled;
+ public void setCategoryOtherServiceEnabled(boolean enabled) {
+ mCategoryOtherServiceEnabled = enabled;
}
@@ -845,8 +845,8 @@
* @return true to indicate if user has enabled this service
*/
@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public boolean isOtherServiceEnabled() {
- return mOtherServiceEnabled;
+ public boolean isCategoryOtherServiceEnabled() {
+ return mCategoryOtherServiceEnabled;
}
/**
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
similarity index 92%
rename from core/java/android/nfc/cardemulation/CardEmulation.java
rename to nfc/java/android/nfc/cardemulation/CardEmulation.java
index 58b6179..ad86d70 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -998,6 +998,87 @@
}
}
+ /**
+ * Setting NFC controller routing table, which includes Protocol Route and Technology Route,
+ * while this Activity is in the foreground.
+ *
+ * The parameter set to null can be used to keep current values for that entry.
+ * <p>
+ * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route:
+ * <pre>
+ * protected void onResume() {
+ * mNfcAdapter.overrideRoutingTable(this , "ESE" , null);
+ * }</pre>
+ * </p>
+ * Also activities must call this method when it goes to the background,
+ * with all parameters set to null.
+ * @param activity The Activity that requests NFC controller routing table to be changed.
+ * @param protocol ISO-DEP route destination, which can be "DH" or "UICC" or "ESE".
+ * @param technology Tech-A, Tech-B route destination, which can be "DH" or "UICC" or "ESE".
+ * @return true if operation is successful and false otherwise
+ *
+ * This is a high risk API and only included to support mainline effort
+ * @hide
+ */
+ public boolean overrideRoutingTable(Activity activity, String protocol, String technology) {
+ if (activity == null) {
+ throw new NullPointerException("activity or service or category is null");
+ }
+ if (!activity.isResumed()) {
+ throw new IllegalArgumentException("Activity must be resumed.");
+ }
+ try {
+ return sService.overrideRoutingTable(UserHandle.myUserId(), protocol, technology);
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.overrideRoutingTable(UserHandle.myUserId(), protocol, technology);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Restore the NFC controller routing table,
+ * which was changed by {@link #overrideRoutingTable(Activity, String, String)}
+ *
+ * @param activity The Activity that requested NFC controller routing table to be changed.
+ * @return true if operation is successful and false otherwise
+ *
+ * @hide
+ */
+ public boolean recoverRoutingTable(Activity activity) {
+ if (activity == null) {
+ throw new NullPointerException("activity is null");
+ }
+ if (!activity.isResumed()) {
+ throw new IllegalArgumentException("Activity must be resumed.");
+ }
+ try {
+ return sService.recoverRoutingTable(UserHandle.myUserId());
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.recoverRoutingTable(UserHandle.myUserId());
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
void recoverService() {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
sService = adapter.getCardEmulationService();
diff --git a/core/java/android/nfc/cardemulation/HostApduService.java b/nfc/java/android/nfc/cardemulation/HostApduService.java
similarity index 100%
rename from core/java/android/nfc/cardemulation/HostApduService.java
rename to nfc/java/android/nfc/cardemulation/HostApduService.java
diff --git a/core/java/android/nfc/cardemulation/HostNfcFService.java b/nfc/java/android/nfc/cardemulation/HostNfcFService.java
similarity index 100%
rename from core/java/android/nfc/cardemulation/HostNfcFService.java
rename to nfc/java/android/nfc/cardemulation/HostNfcFService.java
diff --git a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java b/nfc/java/android/nfc/cardemulation/NfcFCardEmulation.java
similarity index 100%
rename from core/java/android/nfc/cardemulation/NfcFCardEmulation.java
rename to nfc/java/android/nfc/cardemulation/NfcFCardEmulation.java
diff --git a/core/java/android/nfc/cardemulation/NfcFServiceInfo.aidl b/nfc/java/android/nfc/cardemulation/NfcFServiceInfo.aidl
similarity index 100%
rename from core/java/android/nfc/cardemulation/NfcFServiceInfo.aidl
rename to nfc/java/android/nfc/cardemulation/NfcFServiceInfo.aidl
diff --git a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java b/nfc/java/android/nfc/cardemulation/NfcFServiceInfo.java
similarity index 100%
rename from core/java/android/nfc/cardemulation/NfcFServiceInfo.java
rename to nfc/java/android/nfc/cardemulation/NfcFServiceInfo.java
diff --git a/core/java/android/nfc/cardemulation/OWNERS b/nfc/java/android/nfc/cardemulation/OWNERS
similarity index 100%
rename from core/java/android/nfc/cardemulation/OWNERS
rename to nfc/java/android/nfc/cardemulation/OWNERS
diff --git a/core/java/android/nfc/cardemulation/OffHostApduService.java b/nfc/java/android/nfc/cardemulation/OffHostApduService.java
similarity index 100%
rename from core/java/android/nfc/cardemulation/OffHostApduService.java
rename to nfc/java/android/nfc/cardemulation/OffHostApduService.java
diff --git a/core/java/android/nfc/cardemulation/Utils.java b/nfc/java/android/nfc/cardemulation/Utils.java
similarity index 100%
rename from core/java/android/nfc/cardemulation/Utils.java
rename to nfc/java/android/nfc/cardemulation/Utils.java
diff --git a/core/java/android/nfc/dta/NfcDta.java b/nfc/java/android/nfc/dta/NfcDta.java
similarity index 100%
rename from core/java/android/nfc/dta/NfcDta.java
rename to nfc/java/android/nfc/dta/NfcDta.java
diff --git a/core/java/android/nfc/dta/OWNERS b/nfc/java/android/nfc/dta/OWNERS
similarity index 100%
rename from core/java/android/nfc/dta/OWNERS
rename to nfc/java/android/nfc/dta/OWNERS
diff --git a/core/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig
similarity index 67%
rename from core/java/android/nfc/flags.aconfig
rename to nfc/java/android/nfc/flags.aconfig
index 17e0427..cb1a542 100644
--- a/core/java/android/nfc/flags.aconfig
+++ b/nfc/java/android/nfc/flags.aconfig
@@ -48,3 +48,24 @@
description: "Enable NFC Polling Loop Notifications ST shim"
bug: "294217286"
}
+
+flag {
+ name: "enable_tag_detection_broadcasts"
+ namespace: "nfc"
+ description: "Enable sending broadcasts to Wallet role holder when a tag enters/leaves the field."
+ bug: "306203494"
+}
+
+flag {
+ name: "enable_nfc_set_discovery_tech"
+ namespace: "nfc"
+ description: "Flag for NFC set discovery tech API"
+ bug: "300351519"
+}
+
+flag {
+ name: "nfc_vendor_cmd"
+ namespace: "nfc"
+ description: "Enable NFC vendor command support"
+ bug: "289879306"
+}
diff --git a/core/java/android/nfc/package.html b/nfc/java/android/nfc/package.html
similarity index 100%
rename from core/java/android/nfc/package.html
rename to nfc/java/android/nfc/package.html
diff --git a/core/java/android/nfc/tech/BasicTagTechnology.java b/nfc/java/android/nfc/tech/BasicTagTechnology.java
similarity index 100%
rename from core/java/android/nfc/tech/BasicTagTechnology.java
rename to nfc/java/android/nfc/tech/BasicTagTechnology.java
diff --git a/core/java/android/nfc/tech/IsoDep.java b/nfc/java/android/nfc/tech/IsoDep.java
similarity index 100%
rename from core/java/android/nfc/tech/IsoDep.java
rename to nfc/java/android/nfc/tech/IsoDep.java
diff --git a/core/java/android/nfc/tech/MifareClassic.java b/nfc/java/android/nfc/tech/MifareClassic.java
similarity index 100%
rename from core/java/android/nfc/tech/MifareClassic.java
rename to nfc/java/android/nfc/tech/MifareClassic.java
diff --git a/core/java/android/nfc/tech/MifareUltralight.java b/nfc/java/android/nfc/tech/MifareUltralight.java
similarity index 100%
rename from core/java/android/nfc/tech/MifareUltralight.java
rename to nfc/java/android/nfc/tech/MifareUltralight.java
diff --git a/core/java/android/nfc/tech/Ndef.java b/nfc/java/android/nfc/tech/Ndef.java
similarity index 100%
rename from core/java/android/nfc/tech/Ndef.java
rename to nfc/java/android/nfc/tech/Ndef.java
diff --git a/core/java/android/nfc/tech/NdefFormatable.java b/nfc/java/android/nfc/tech/NdefFormatable.java
similarity index 100%
rename from core/java/android/nfc/tech/NdefFormatable.java
rename to nfc/java/android/nfc/tech/NdefFormatable.java
diff --git a/core/java/android/nfc/tech/NfcA.java b/nfc/java/android/nfc/tech/NfcA.java
similarity index 100%
rename from core/java/android/nfc/tech/NfcA.java
rename to nfc/java/android/nfc/tech/NfcA.java
diff --git a/core/java/android/nfc/tech/NfcB.java b/nfc/java/android/nfc/tech/NfcB.java
similarity index 100%
rename from core/java/android/nfc/tech/NfcB.java
rename to nfc/java/android/nfc/tech/NfcB.java
diff --git a/core/java/android/nfc/tech/NfcBarcode.java b/nfc/java/android/nfc/tech/NfcBarcode.java
similarity index 100%
rename from core/java/android/nfc/tech/NfcBarcode.java
rename to nfc/java/android/nfc/tech/NfcBarcode.java
diff --git a/core/java/android/nfc/tech/NfcF.java b/nfc/java/android/nfc/tech/NfcF.java
similarity index 100%
rename from core/java/android/nfc/tech/NfcF.java
rename to nfc/java/android/nfc/tech/NfcF.java
diff --git a/core/java/android/nfc/tech/NfcV.java b/nfc/java/android/nfc/tech/NfcV.java
similarity index 100%
rename from core/java/android/nfc/tech/NfcV.java
rename to nfc/java/android/nfc/tech/NfcV.java
diff --git a/core/java/android/nfc/tech/OWNERS b/nfc/java/android/nfc/tech/OWNERS
similarity index 100%
rename from core/java/android/nfc/tech/OWNERS
rename to nfc/java/android/nfc/tech/OWNERS
diff --git a/core/java/android/nfc/tech/TagTechnology.java b/nfc/java/android/nfc/tech/TagTechnology.java
similarity index 100%
rename from core/java/android/nfc/tech/TagTechnology.java
rename to nfc/java/android/nfc/tech/TagTechnology.java
diff --git a/core/java/android/nfc/tech/package.html b/nfc/java/android/nfc/tech/package.html
similarity index 100%
rename from core/java/android/nfc/tech/package.html
rename to nfc/java/android/nfc/tech/package.html
diff --git a/core/tests/nfctests/Android.bp b/nfc/tests/Android.bp
similarity index 97%
rename from core/tests/nfctests/Android.bp
rename to nfc/tests/Android.bp
index f81be49..62566ee 100644
--- a/core/tests/nfctests/Android.bp
+++ b/nfc/tests/Android.bp
@@ -30,6 +30,7 @@
"truth",
],
libs: [
+ "framework-nfc.impl",
"android.test.runner",
],
srcs: ["src/**/*.java"],
diff --git a/core/tests/nfctests/AndroidManifest.xml b/nfc/tests/AndroidManifest.xml
similarity index 100%
rename from core/tests/nfctests/AndroidManifest.xml
rename to nfc/tests/AndroidManifest.xml
diff --git a/core/tests/nfctests/AndroidTest.xml b/nfc/tests/AndroidTest.xml
similarity index 100%
rename from core/tests/nfctests/AndroidTest.xml
rename to nfc/tests/AndroidTest.xml
diff --git a/core/tests/nfctests/src/android/nfc/NfcControllerAlwaysOnListenerTest.java b/nfc/tests/src/android/nfc/NfcControllerAlwaysOnListenerTest.java
similarity index 100%
rename from core/tests/nfctests/src/android/nfc/NfcControllerAlwaysOnListenerTest.java
rename to nfc/tests/src/android/nfc/NfcControllerAlwaysOnListenerTest.java
diff --git a/core/tests/nfctests/src/android/nfc/TechListParcelTest.java b/nfc/tests/src/android/nfc/TechListParcelTest.java
similarity index 100%
rename from core/tests/nfctests/src/android/nfc/TechListParcelTest.java
rename to nfc/tests/src/android/nfc/TechListParcelTest.java
diff --git a/opengl/java/android/opengl/EGLExt.java b/opengl/java/android/opengl/EGLExt.java
index 1570e0e..31104a0 100644
--- a/opengl/java/android/opengl/EGLExt.java
+++ b/opengl/java/android/opengl/EGLExt.java
@@ -46,14 +46,6 @@
_nativeClassInit();
}
- // C function EGLBoolean eglPresentationTimeANDROID ( EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time )
-
- public static native boolean eglPresentationTimeANDROID(
- EGLDisplay dpy,
- EGLSurface sur,
- long time
- );
-
/**
* Retrieves the SyncFence for an EGLSync created with EGL_SYNC_NATIVE_FENCE_ANDROID
*
@@ -83,4 +75,13 @@
}
private static native int eglDupNativeFenceFDANDROIDImpl(EGLDisplay display, EGLSync sync);
+
+ // C function EGLBoolean eglPresentationTimeANDROID ( EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time )
+
+ public static native boolean eglPresentationTimeANDROID(
+ EGLDisplay dpy,
+ EGLSurface sur,
+ long time
+ );
+
}
diff --git a/packages/CompanionDeviceManager/Android.bp b/packages/CompanionDeviceManager/Android.bp
index f6458c2..ce32ec4 100644
--- a/packages/CompanionDeviceManager/Android.bp
+++ b/packages/CompanionDeviceManager/Android.bp
@@ -46,4 +46,6 @@
],
platform_apis: true,
+
+ generate_product_characteristics_rro: true,
}
diff --git a/packages/CrashRecovery/aconfig/flags.aconfig b/packages/CrashRecovery/aconfig/flags.aconfig
new file mode 100644
index 0000000..5636266
--- /dev/null
+++ b/packages/CrashRecovery/aconfig/flags.aconfig
@@ -0,0 +1,9 @@
+package: "android.crashrecovery.flags"
+
+flag {
+ name: "recoverability_detection"
+ namespace: "package_watchdog"
+ description: "Feature flag for recoverability detection"
+ bug: "310236690"
+ is_fixed_read_only: true
+}
\ No newline at end of file
diff --git a/packages/CrashRecovery/framework/Android.bp b/packages/CrashRecovery/framework/Android.bp
index b2af315..9480327 100644
--- a/packages/CrashRecovery/framework/Android.bp
+++ b/packages/CrashRecovery/framework/Android.bp
@@ -1,9 +1,53 @@
-filegroup {
- name: "framework-crashrecovery-sources",
- srcs: [
- "java/**/*.java",
- "java/**/*.aidl",
+soong_config_module_type {
+ name: "platform_filegroup",
+ module_type: "filegroup",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "crashrecovery_files_in_platform",
],
+ properties: [
+ "srcs",
+ ],
+}
+
+platform_filegroup {
+ name: "framework-crashrecovery-sources",
+ soong_config_variables: {
+ // if this flag is enabled, then files are part of platform
+ crashrecovery_files_in_platform: {
+ srcs: [
+ "java/**/*.java",
+ "java/**/*.aidl",
+ ],
+ },
+ },
path: "java",
visibility: ["//frameworks/base:__subpackages__"],
}
+
+soong_config_module_type {
+ name: "module_filegroup",
+ module_type: "filegroup",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "crashrecovery_files_in_module",
+ ],
+ properties: [
+ "srcs",
+ ],
+}
+
+module_filegroup {
+ name: "framework-crashrecovery-module-sources",
+ soong_config_variables: {
+ // if this flag is enabled, then files are part of module
+ crashrecovery_files_in_module: {
+ srcs: [
+ "java/**/*.java",
+ "java/**/*.aidl",
+ ],
+ },
+ },
+ path: "java",
+ visibility: ["//packages/modules/CrashRecovery/framework"],
+}
diff --git a/packages/CrashRecovery/services/Android.bp b/packages/CrashRecovery/services/Android.bp
index 27ddff9..961b41f 100644
--- a/packages/CrashRecovery/services/Android.bp
+++ b/packages/CrashRecovery/services/Android.bp
@@ -1,9 +1,61 @@
-filegroup {
- name: "services-crashrecovery-sources",
- srcs: [
- "java/**/*.java",
- "java/**/*.aidl",
+soong_config_module_type {
+ name: "platform_filegroup",
+ module_type: "filegroup",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "crashrecovery_files_in_platform",
],
- path: "java",
+ properties: [
+ "srcs",
+ ],
+}
+
+platform_filegroup {
+ name: "services-crashrecovery-sources",
+ soong_config_variables: {
+ // if this flag is enabled, then files are part of platform
+ crashrecovery_files_in_platform: {
+ srcs: [
+ "java/**/*.java",
+ "java/**/*.aidl",
+ ":statslog-crashrecovery-java-gen",
+ ],
+ },
+ },
visibility: ["//frameworks/base:__subpackages__"],
}
+
+soong_config_module_type {
+ name: "module_filegroup",
+ module_type: "filegroup",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "crashrecovery_files_in_module",
+ ],
+ properties: [
+ "srcs",
+ ],
+}
+
+module_filegroup {
+ name: "services-crashrecovery-module-sources",
+ soong_config_variables: {
+ // if this flag is enabled, then files are part of module
+ crashrecovery_files_in_module: {
+ srcs: [
+ "java/**/*.java",
+ "java/**/*.aidl",
+ ":statslog-crashrecovery-java-gen",
+ ],
+ },
+ },
+ visibility: ["//packages/modules/CrashRecovery/service"],
+}
+
+genrule {
+ name: "statslog-crashrecovery-java-gen",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --java $(out) --module crashrecovery " +
+ "--javaPackage com.android.server.crashrecovery.proto --javaClass CrashRecoveryStatsLog --worksource",
+ out: ["com/android/server/crashrecovery/proto/CrashRecoveryStatsLog.java"],
+}
diff --git a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
index d256aea..5d71b7d 100644
--- a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
+++ b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
@@ -33,18 +33,18 @@
import android.os.Process;
import android.os.SystemProperties;
import android.provider.DeviceConfig;
+import android.sysprop.CrashRecoveryProperties;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.BackgroundThread;
import android.util.LongArrayQueue;
-import android.util.MathUtils;
import android.util.Slog;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
@@ -100,13 +100,15 @@
public static final int FAILURE_REASON_EXPLICIT_HEALTH_CHECK = 2;
public static final int FAILURE_REASON_APP_CRASH = 3;
public static final int FAILURE_REASON_APP_NOT_RESPONDING = 4;
+ public static final int FAILURE_REASON_BOOT_LOOP = 5;
@IntDef(prefix = { "FAILURE_REASON_" }, value = {
FAILURE_REASON_UNKNOWN,
FAILURE_REASON_NATIVE_CRASH,
FAILURE_REASON_EXPLICIT_HEALTH_CHECK,
FAILURE_REASON_APP_CRASH,
- FAILURE_REASON_APP_NOT_RESPONDING
+ FAILURE_REASON_APP_NOT_RESPONDING,
+ FAILURE_REASON_BOOT_LOOP
})
@Retention(RetentionPolicy.SOURCE)
public @interface FailureReasons {}
@@ -128,18 +130,9 @@
@VisibleForTesting
static final int DEFAULT_BOOT_LOOP_TRIGGER_COUNT = 5;
+ @VisibleForTesting
static final long DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS = TimeUnit.MINUTES.toMillis(10);
- // These properties track individual system server boot events, and are reset once the boot
- // threshold is met, or the boot loop trigger window is exceeded between boot events.
- private static final String PROP_RESCUE_BOOT_COUNT = "sys.rescue_boot_count";
- private static final String PROP_RESCUE_BOOT_START = "sys.rescue_boot_start";
-
- // These properties track multiple calls made to observers tracking boot loops. They are reset
- // when the de-escalation window is exceeded between boot events.
- private static final String PROP_BOOT_MITIGATION_WINDOW_START = "sys.boot_mitigation_start";
- private static final String PROP_BOOT_MITIGATION_COUNT = "sys.boot_mitigation_count";
-
private long mNumberOfNativeCrashPollsRemaining;
private static final int DB_VERSION = 1;
@@ -551,7 +544,7 @@
mNumberOfNativeCrashPollsRemaining--;
// Check if native watchdog reported a crash
if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) {
- // We rollback everything available when crash is unattributable
+ // We rollback all available low impact rollbacks when crash is unattributable
onPackageFailure(Collections.EMPTY_LIST, FAILURE_REASON_NATIVE_CRASH);
// we stop polling after an attempt to execute rollback, regardless of whether the
// attempt succeeds or not
@@ -581,6 +574,7 @@
PackageHealthObserverImpact.USER_IMPACT_LEVEL_30,
PackageHealthObserverImpact.USER_IMPACT_LEVEL_50,
PackageHealthObserverImpact.USER_IMPACT_LEVEL_70,
+ PackageHealthObserverImpact.USER_IMPACT_LEVEL_90,
PackageHealthObserverImpact.USER_IMPACT_LEVEL_100})
public @interface PackageHealthObserverImpact {
/** No action to take. */
@@ -591,6 +585,7 @@
int USER_IMPACT_LEVEL_30 = 30;
int USER_IMPACT_LEVEL_50 = 50;
int USER_IMPACT_LEVEL_70 = 70;
+ int USER_IMPACT_LEVEL_90 = 90;
/* Action has high user impact, a last resort, user of a device will be very frustrated. */
int USER_IMPACT_LEVEL_100 = 100;
}
@@ -1702,42 +1697,45 @@
setCount(0);
}
- private int getCount() {
- return SystemProperties.getInt(PROP_RESCUE_BOOT_COUNT, 0);
+ protected int getCount() {
+ return CrashRecoveryProperties.rescueBootCount().orElse(0);
}
- private void setCount(int count) {
- SystemProperties.set(PROP_RESCUE_BOOT_COUNT, Integer.toString(count));
+ protected void setCount(int count) {
+ CrashRecoveryProperties.rescueBootCount(count);
}
public long getStart() {
- return SystemProperties.getLong(PROP_RESCUE_BOOT_START, 0);
+ return CrashRecoveryProperties.rescueBootStart().orElse(0L);
}
public int getMitigationCount() {
- return SystemProperties.getInt(PROP_BOOT_MITIGATION_COUNT, 0);
+ return CrashRecoveryProperties.bootMitigationCount().orElse(0);
}
public void setStart(long start) {
- setPropertyStart(PROP_RESCUE_BOOT_START, start);
+ CrashRecoveryProperties.rescueBootStart(getStartTime(start));
}
public void setMitigationStart(long start) {
- setPropertyStart(PROP_BOOT_MITIGATION_WINDOW_START, start);
+ CrashRecoveryProperties.bootMitigationStart(getStartTime(start));
}
public long getMitigationStart() {
- return SystemProperties.getLong(PROP_BOOT_MITIGATION_WINDOW_START, 0);
+ return CrashRecoveryProperties.bootMitigationStart().orElse(0L);
}
public void setMitigationCount(int count) {
- SystemProperties.set(PROP_BOOT_MITIGATION_COUNT, Integer.toString(count));
+ CrashRecoveryProperties.bootMitigationCount(count);
}
- public void setPropertyStart(String property, long start) {
+ private static long constrain(long amount, long low, long high) {
+ return amount < low ? low : (amount > high ? high : amount);
+ }
+
+ public long getStartTime(long start) {
final long now = mSystemClock.uptimeMillis();
- final long newStart = MathUtils.constrain(start, 0, now);
- SystemProperties.set(property, Long.toString(newStart));
+ return constrain(start, 0, now);
}
public void saveMitigationCountToMetadata() {
diff --git a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
index eb65b2a..9217e70 100644
--- a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
+++ b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
@@ -37,20 +37,20 @@
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.sysprop.CrashRecoveryProperties;
import android.text.TextUtils;
import android.util.ArraySet;
-import android.util.ExceptionUtils;
import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.server.PackageWatchdog.FailureReasons;
import com.android.server.PackageWatchdog.PackageHealthObserver;
import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
import com.android.server.am.SettingsToPropertiesMapper;
+import com.android.server.crashrecovery.proto.CrashRecoveryStatsLog;
import java.io.File;
import java.util.ArrayList;
@@ -76,10 +76,6 @@
public class RescueParty {
@VisibleForTesting
static final String PROP_ENABLE_RESCUE = "persist.sys.enable_rescue";
- static final String PROP_ATTEMPTING_FACTORY_RESET = "sys.attempting_factory_reset";
- static final String PROP_ATTEMPTING_REBOOT = "sys.attempting_reboot";
- static final String PROP_MAX_RESCUE_LEVEL_ATTEMPTED = "sys.max_rescue_level_attempted";
- static final String PROP_LAST_FACTORY_RESET_TIME_MS = "persist.sys.last_factory_reset";
@VisibleForTesting
static final int LEVEL_NONE = 0;
@VisibleForTesting
@@ -93,8 +89,6 @@
@VisibleForTesting
static final int LEVEL_FACTORY_RESET = 5;
@VisibleForTesting
- static final String PROP_RESCUE_BOOT_COUNT = "sys.rescue_boot_count";
- @VisibleForTesting
static final String TAG = "RescueParty";
@VisibleForTesting
static final long DEFAULT_OBSERVING_DURATION_MS = TimeUnit.DAYS.toMillis(2);
@@ -143,7 +137,7 @@
}
// We're disabled on all engineering devices
- if (Build.IS_ENG) {
+ if (Build.TYPE.equals("eng")) {
Slog.v(TAG, "Disabled because of eng build");
return true;
}
@@ -151,7 +145,7 @@
// We're disabled on userdebug devices connected over USB, since that's
// a decent signal that someone is actively trying to debug the device,
// or that it's in a lab environment.
- if (Build.IS_USERDEBUG && isUsbActive()) {
+ if (Build.TYPE.equals("userdebug") && isUsbActive()) {
Slog.v(TAG, "Disabled because of active USB connection");
return true;
}
@@ -177,11 +171,34 @@
}
static boolean isFactoryResetPropertySet() {
- return SystemProperties.getBoolean(PROP_ATTEMPTING_FACTORY_RESET, false);
+ return CrashRecoveryProperties.attemptingFactoryReset().orElse(false);
}
static boolean isRebootPropertySet() {
- return SystemProperties.getBoolean(PROP_ATTEMPTING_REBOOT, false);
+ return CrashRecoveryProperties.attemptingReboot().orElse(false);
+ }
+
+ protected static long getLastFactoryResetTimeMs() {
+ return CrashRecoveryProperties.lastFactoryResetTimeMs().orElse(0L);
+ }
+
+ protected static int getMaxRescueLevelAttempted() {
+ return CrashRecoveryProperties.maxRescueLevelAttempted().orElse(LEVEL_NONE);
+ }
+
+ protected static void setFactoryResetProperty(boolean value) {
+ CrashRecoveryProperties.attemptingFactoryReset(value);
+ }
+ protected static void setRebootProperty(boolean value) {
+ CrashRecoveryProperties.attemptingReboot(value);
+ }
+
+ protected static void setLastFactoryResetTimeMs(long value) {
+ CrashRecoveryProperties.lastFactoryResetTimeMs(value);
+ }
+
+ protected static void setMaxRescueLevelAttempted(int level) {
+ CrashRecoveryProperties.maxRescueLevelAttempted(level);
}
/**
@@ -382,7 +399,16 @@
private static void executeRescueLevelInternal(Context context, int level, @Nullable
String failedPackage) throws Exception {
- FrameworkStatsLog.write(FrameworkStatsLog.RESCUE_PARTY_RESET_REPORTED, level);
+
+ if (level <= LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS) {
+ // Disabling flag resets on master branch for trunk stable launch.
+ // TODO(b/287618292): Re-enable them after the trunk stable is launched and we
+ // figured out a way to reset flags without interfering with trunk development.
+ return;
+ }
+
+ CrashRecoveryStatsLog.write(CrashRecoveryStatsLog.RESCUE_PARTY_RESET_REPORTED,
+ level, levelToString(level));
// Try our best to reset all settings possible, and once finished
// rethrow any exception that we encountered
Exception res = null;
@@ -431,7 +457,7 @@
case LEVEL_WARM_REBOOT:
// Request the reboot from a separate thread to avoid deadlock on PackageWatchdog
// when device shutting down.
- SystemProperties.set(PROP_ATTEMPTING_REBOOT, "true");
+ setRebootProperty(true);
runnable = () -> {
try {
PowerManager pm = context.getSystemService(PowerManager.class);
@@ -453,9 +479,9 @@
if (isRebootPropertySet()) {
break;
}
- SystemProperties.set(PROP_ATTEMPTING_FACTORY_RESET, "true");
+ setFactoryResetProperty(true);
long now = System.currentTimeMillis();
- SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(now));
+ setLastFactoryResetTimeMs(now);
runnable = new Runnable() {
@Override
public void run() {
@@ -476,9 +502,18 @@
}
}
+ private static String getCompleteMessage(Throwable t) {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(t.getMessage());
+ while ((t = t.getCause()) != null) {
+ builder.append(": ").append(t.getMessage());
+ }
+ return builder.toString();
+ }
+
private static void logRescueException(int level, @Nullable String failedPackageName,
Throwable t) {
- final String msg = ExceptionUtils.getCompleteMessage(t);
+ final String msg = getCompleteMessage(t);
EventLogTags.writeRescueFailure(level, msg);
String failureMsg = "Failed rescue level " + levelToString(level);
if (!TextUtils.isEmpty(failedPackageName)) {
@@ -505,10 +540,10 @@
private static void resetAllSettingsIfNecessary(Context context, int mode,
int level) throws Exception {
// No need to reset Settings again if they are already reset in the current level once.
- if (SystemProperties.getInt(PROP_MAX_RESCUE_LEVEL_ATTEMPTED, LEVEL_NONE) >= level) {
+ if (getMaxRescueLevelAttempted() >= level) {
return;
}
- SystemProperties.set(PROP_MAX_RESCUE_LEVEL_ATTEMPTED, Integer.toString(level));
+ setMaxRescueLevelAttempted(level);
// Try our best to reset all settings possible, and once finished
// rethrow any exception that we encountered
Exception res = null;
@@ -723,7 +758,7 @@
* Will return {@code false} if a factory reset was already offered recently.
*/
private boolean shouldThrottleReboot() {
- Long lastResetTime = SystemProperties.getLong(PROP_LAST_FACTORY_RESET_TIME_MS, 0);
+ Long lastResetTime = getLastFactoryResetTimeMs();
long now = System.currentTimeMillis();
long throttleDurationMin = SystemProperties.getLong(PROP_THROTTLE_DURATION_MIN_FLAG,
DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN);
diff --git a/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 2007079..0fb9327 100644
--- a/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -28,24 +28,25 @@
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
+import android.crashrecovery.flags.Flags;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager;
import android.os.SystemProperties;
+import android.sysprop.CrashRecoveryProperties;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.Preconditions;
import com.android.server.PackageWatchdog;
import com.android.server.PackageWatchdog.FailureReasons;
import com.android.server.PackageWatchdog.PackageHealthObserver;
import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
-import com.android.server.SystemConfig;
+import com.android.server.crashrecovery.proto.CrashRecoveryStatsLog;
import com.android.server.pm.ApexManager;
import java.io.BufferedReader;
@@ -56,6 +57,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
@@ -70,10 +72,12 @@
final class RollbackPackageHealthObserver implements PackageHealthObserver {
private static final String TAG = "RollbackPackageHealthObserver";
private static final String NAME = "rollback-observer";
- private static final String PROP_ATTEMPTING_REBOOT = "sys.attempting_reboot";
private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT
| ApplicationInfo.FLAG_SYSTEM;
+ private static final String PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG =
+ "persist.device_config.configuration.disable_high_impact_rollback";
+
private final Context mContext;
private final Handler mHandler;
private final ApexManager mApexManager;
@@ -84,7 +88,8 @@
// True if needing to roll back only rebootless apexes when native crash happens
private boolean mTwoPhaseRollbackEnabled;
- RollbackPackageHealthObserver(Context context) {
+ @VisibleForTesting
+ RollbackPackageHealthObserver(Context context, ApexManager apexManager) {
mContext = context;
HandlerThread handlerThread = new HandlerThread("RollbackPackageHealthObserver");
handlerThread.start();
@@ -94,7 +99,7 @@
mLastStagedRollbackIdsFile = new File(dataDir, "last-staged-rollback-ids");
mTwoPhaseRollbackEnabledFile = new File(dataDir, "two-phase-rollback-enabled");
PackageWatchdog.getInstance(mContext).registerHealthObserver(this);
- mApexManager = ApexManager.getInstance();
+ mApexManager = apexManager;
if (SystemProperties.getBoolean("sys.boot_completed", false)) {
// Load the value from the file if system server has crashed and restarted
@@ -107,24 +112,46 @@
}
}
+ RollbackPackageHealthObserver(Context context) {
+ this(context, ApexManager.getInstance());
+ }
+
@Override
public int onHealthCheckFailed(@Nullable VersionedPackage failedPackage,
@FailureReasons int failureReason, int mitigationCount) {
- boolean anyRollbackAvailable = !mContext.getSystemService(RollbackManager.class)
- .getAvailableRollbacks().isEmpty();
int impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
+ if (Flags.recoverabilityDetection()) {
+ List<RollbackInfo> availableRollbacks = getAvailableRollbacks();
+ List<RollbackInfo> lowImpactRollbacks = getRollbacksAvailableForImpactLevel(
+ availableRollbacks, PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ if (!lowImpactRollbacks.isEmpty()) {
+ if (failureReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) {
+ // For native crashes, we will directly roll back any available rollbacks at low
+ // impact level
+ impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30;
+ } else if (getRollbackForPackage(failedPackage, lowImpactRollbacks) != null) {
+ // Rollback is available for crashing low impact package
+ impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30;
+ } else {
+ impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_70;
+ }
+ }
+ } else {
+ boolean anyRollbackAvailable = !mContext.getSystemService(RollbackManager.class)
+ .getAvailableRollbacks().isEmpty();
- if (failureReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH
- && anyRollbackAvailable) {
- // For native crashes, we will directly roll back any available rollbacks
- // Note: For non-native crashes the rollback-all step has higher impact
- impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30;
- } else if (getAvailableRollback(failedPackage) != null) {
- // Rollback is available, we may get a callback into #execute
- impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30;
- } else if (anyRollbackAvailable) {
- // If any rollbacks are available, we will commit them
- impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_70;
+ if (failureReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH
+ && anyRollbackAvailable) {
+ // For native crashes, we will directly roll back any available rollbacks
+ // Note: For non-native crashes the rollback-all step has higher impact
+ impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30;
+ } else if (getAvailableRollback(failedPackage) != null) {
+ // Rollback is available, we may get a callback into #execute
+ impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30;
+ } else if (anyRollbackAvailable) {
+ // If any rollbacks are available, we will commit them
+ impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_70;
+ }
}
return impact;
@@ -133,16 +160,34 @@
@Override
public boolean execute(@Nullable VersionedPackage failedPackage,
@FailureReasons int rollbackReason, int mitigationCount) {
- if (rollbackReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) {
- mHandler.post(() -> rollbackAll(rollbackReason));
- return true;
- }
+ if (Flags.recoverabilityDetection()) {
+ List<RollbackInfo> availableRollbacks = getAvailableRollbacks();
+ if (rollbackReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) {
+ mHandler.post(() -> rollbackAllLowImpact(availableRollbacks, rollbackReason));
+ return true;
+ }
- RollbackInfo rollback = getAvailableRollback(failedPackage);
- if (rollback != null) {
- mHandler.post(() -> rollbackPackage(rollback, failedPackage, rollbackReason));
+ List<RollbackInfo> lowImpactRollbacks = getRollbacksAvailableForImpactLevel(
+ availableRollbacks, PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ RollbackInfo rollback = getRollbackForPackage(failedPackage, lowImpactRollbacks);
+ if (rollback != null) {
+ mHandler.post(() -> rollbackPackage(rollback, failedPackage, rollbackReason));
+ } else if (!lowImpactRollbacks.isEmpty()) {
+ // Apply all available low impact rollbacks.
+ mHandler.post(() -> rollbackAllLowImpact(availableRollbacks, rollbackReason));
+ }
} else {
- mHandler.post(() -> rollbackAll(rollbackReason));
+ if (rollbackReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) {
+ mHandler.post(() -> rollbackAll(rollbackReason));
+ return true;
+ }
+
+ RollbackInfo rollback = getAvailableRollback(failedPackage);
+ if (rollback != null) {
+ mHandler.post(() -> rollbackPackage(rollback, failedPackage, rollbackReason));
+ } else {
+ mHandler.post(() -> rollbackAll(rollbackReason));
+ }
}
// Assume rollbacks executed successfully
@@ -150,6 +195,31 @@
}
@Override
+ public int onBootLoop(int mitigationCount) {
+ int impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
+ if (Flags.recoverabilityDetection()) {
+ List<RollbackInfo> availableRollbacks = getAvailableRollbacks();
+ if (!availableRollbacks.isEmpty()) {
+ impact = getUserImpactBasedOnRollbackImpactLevel(availableRollbacks);
+ }
+ }
+ return impact;
+ }
+
+ @Override
+ public boolean executeBootLoopMitigation(int mitigationCount) {
+ if (Flags.recoverabilityDetection()) {
+ List<RollbackInfo> availableRollbacks = getAvailableRollbacks();
+
+ triggerLeastImpactLevelRollback(availableRollbacks,
+ PackageWatchdog.FAILURE_REASON_BOOT_LOOP);
+ return true;
+ }
+ return false;
+ }
+
+
+ @Override
public String getName() {
return NAME;
}
@@ -161,13 +231,16 @@
@Override
public boolean mayObservePackage(String packageName) {
- if (mContext.getSystemService(RollbackManager.class)
- .getAvailableRollbacks().isEmpty()) {
+ if (getAvailableRollbacks().isEmpty()) {
return false;
}
return isPersistentSystemApp(packageName);
}
+ private List<RollbackInfo> getAvailableRollbacks() {
+ return mContext.getSystemService(RollbackManager.class).getAvailableRollbacks();
+ }
+
private boolean isPersistentSystemApp(@NonNull String packageName) {
PackageManager pm = mContext.getPackageManager();
try {
@@ -272,6 +345,40 @@
return null;
}
+ @AnyThread
+ private RollbackInfo getRollbackForPackage(@Nullable VersionedPackage failedPackage,
+ List<RollbackInfo> availableRollbacks) {
+ if (failedPackage == null) {
+ return null;
+ }
+
+ for (RollbackInfo rollback : availableRollbacks) {
+ for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
+ if (packageRollback.getVersionRolledBackFrom().equals(failedPackage)) {
+ return rollback;
+ }
+ // TODO(b/147666157): Extract version number of apk-in-apex so that we don't have
+ // to rely on complicated reasoning as below
+
+ // Due to b/147666157, for apk in apex, we do not know the version we are rolling
+ // back from. But if a package X is embedded in apex A exclusively (not embedded in
+ // any other apex), which is not guaranteed, then it is sufficient to check only
+ // package names here, as the version of failedPackage and the PackageRollbackInfo
+ // can't be different. If failedPackage has a higher version, then it must have
+ // been updated somehow. There are two ways: it was updated by an update of apex A
+ // or updated directly as apk. In both cases, this rollback would have gotten
+ // expired when onPackageReplaced() was called. Since the rollback exists, it has
+ // same version as failedPackage.
+ if (packageRollback.isApkInApex()
+ && packageRollback.getVersionRolledBackFrom().getPackageName()
+ .equals(failedPackage.getPackageName())) {
+ return rollback;
+ }
+ }
+ }
+ return null;
+ }
+
/**
* Returns {@code true} if staged session associated with {@code rollbackId} was marked
* as handled, {@code false} if already handled.
@@ -396,12 +503,6 @@
@FailureReasons int rollbackReason) {
assertInWorkerThread();
- if (isAutomaticRollbackDenied(SystemConfig.getInstance(), failedPackage)) {
- Slog.d(TAG, "Automatic rollback not allowed for package "
- + failedPackage.getPackageName());
- return;
- }
-
final RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
int reasonToLog = WatchdogRollbackLogger.mapFailureReasonToMetric(rollbackReason);
final String failedPackageToLog;
@@ -418,7 +519,7 @@
final VersionedPackage logPackage = logPackageTemp;
WatchdogRollbackLogger.logEvent(logPackage,
- FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE,
+ CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE,
reasonToLog, failedPackageToLog);
Consumer<Intent> onResult = result -> {
@@ -430,19 +531,19 @@
int rollbackId = rollback.getRollbackId();
saveStagedRollbackId(rollbackId, logPackage);
WatchdogRollbackLogger.logEvent(logPackage,
- FrameworkStatsLog
+ CrashRecoveryStatsLog
.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED,
reasonToLog, failedPackageToLog);
} else {
WatchdogRollbackLogger.logEvent(logPackage,
- FrameworkStatsLog
+ CrashRecoveryStatsLog
.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
reasonToLog, failedPackageToLog);
}
} else {
WatchdogRollbackLogger.logEvent(logPackage,
- FrameworkStatsLog
+ CrashRecoveryStatsLog
.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
reasonToLog, failedPackageToLog);
}
@@ -450,7 +551,7 @@
markStagedSessionHandled(rollback.getRollbackId());
// Wait for all pending staged sessions to get handled before rebooting.
if (isPendingStagedSessionsEmpty()) {
- SystemProperties.set(PROP_ATTEMPTING_REBOOT, "true");
+ CrashRecoveryProperties.attemptingReboot(true);
mContext.getSystemService(PowerManager.class).reboot("Rollback staged install");
}
}
@@ -465,17 +566,6 @@
}
/**
- * Returns true if this package is not eligible for automatic rollback.
- */
- @VisibleForTesting
- @AnyThread
- public static boolean isAutomaticRollbackDenied(SystemConfig systemConfig,
- VersionedPackage versionedPackage) {
- return systemConfig.getAutomaticRollbackDenylistedPackages()
- .contains(versionedPackage.getPackageName());
- }
-
- /**
* Two-phase rollback:
* 1. roll back rebootless apexes first
* 2. roll back all remaining rollbacks if native crash doesn't stop after (1) is done
@@ -495,14 +585,66 @@
boolean found = false;
for (RollbackInfo rollback : rollbacks) {
if (isRebootlessApex(rollback)) {
- VersionedPackage sample = rollback.getPackages().get(0).getVersionRolledBackFrom();
- rollbackPackage(rollback, sample, PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
+ VersionedPackage firstRollback =
+ rollback.getPackages().get(0).getVersionRolledBackFrom();
+ rollbackPackage(rollback, firstRollback,
+ PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
found = true;
}
}
return found;
}
+ /**
+ * Rollback the package that has minimum rollback impact level.
+ * @param availableRollbacks all available rollbacks
+ * @param rollbackReason reason to rollback
+ */
+ private void triggerLeastImpactLevelRollback(List<RollbackInfo> availableRollbacks,
+ @FailureReasons int rollbackReason) {
+ int minRollbackImpactLevel = getMinRollbackImpactLevel(availableRollbacks);
+
+ if (minRollbackImpactLevel == PackageManager.ROLLBACK_USER_IMPACT_LOW) {
+ // Apply all available low impact rollbacks.
+ mHandler.post(() -> rollbackAllLowImpact(availableRollbacks, rollbackReason));
+ } else if (minRollbackImpactLevel == PackageManager.ROLLBACK_USER_IMPACT_HIGH) {
+ // Check disable_high_impact_rollback device config before performing rollback
+ if (SystemProperties.getBoolean(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, false)) {
+ return;
+ }
+ // Rollback one package at a time. If that doesn't resolve the issue, rollback
+ // next with same impact level.
+ mHandler.post(() -> rollbackHighImpact(availableRollbacks, rollbackReason));
+ }
+ }
+
+ /**
+ * sort the available high impact rollbacks by first package name to have a deterministic order.
+ * Apply the first available rollback.
+ * @param availableRollbacks all available rollbacks
+ * @param rollbackReason reason to rollback
+ */
+ @WorkerThread
+ private void rollbackHighImpact(List<RollbackInfo> availableRollbacks,
+ @FailureReasons int rollbackReason) {
+ assertInWorkerThread();
+ List<RollbackInfo> highImpactRollbacks =
+ getRollbacksAvailableForImpactLevel(
+ availableRollbacks, PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+
+ // sort rollbacks based on package name of the first package. This is to have a
+ // deterministic order of rollbacks.
+ List<RollbackInfo> sortedHighImpactRollbacks = highImpactRollbacks.stream().sorted(
+ Comparator.comparing(a -> a.getPackages().get(0).getPackageName())).toList();
+ VersionedPackage firstRollback =
+ sortedHighImpactRollbacks
+ .get(0)
+ .getPackages()
+ .get(0)
+ .getVersionRolledBackFrom();
+ rollbackPackage(sortedHighImpactRollbacks.get(0), firstRollback, rollbackReason);
+ }
+
@WorkerThread
private void rollbackAll(@FailureReasons int rollbackReason) {
assertInWorkerThread();
@@ -522,8 +664,79 @@
}
for (RollbackInfo rollback : rollbacks) {
- VersionedPackage sample = rollback.getPackages().get(0).getVersionRolledBackFrom();
- rollbackPackage(rollback, sample, rollbackReason);
+ VersionedPackage firstRollback =
+ rollback.getPackages().get(0).getVersionRolledBackFrom();
+ rollbackPackage(rollback, firstRollback, rollbackReason);
}
}
+
+ /**
+ * Rollback all available low impact rollbacks
+ * @param availableRollbacks all available rollbacks
+ * @param rollbackReason reason to rollbacks
+ */
+ @WorkerThread
+ private void rollbackAllLowImpact(
+ List<RollbackInfo> availableRollbacks, @FailureReasons int rollbackReason) {
+ assertInWorkerThread();
+
+ List<RollbackInfo> lowImpactRollbacks = getRollbacksAvailableForImpactLevel(
+ availableRollbacks,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ if (useTwoPhaseRollback(lowImpactRollbacks)) {
+ return;
+ }
+
+ Slog.i(TAG, "Rolling back all available low impact rollbacks");
+ // Add all rollback ids to mPendingStagedRollbackIds, so that we do not reboot before all
+ // pending staged rollbacks are handled.
+ for (RollbackInfo rollback : lowImpactRollbacks) {
+ if (rollback.isStaged()) {
+ mPendingStagedRollbackIds.add(rollback.getRollbackId());
+ }
+ }
+
+ for (RollbackInfo rollback : lowImpactRollbacks) {
+ VersionedPackage firstRollback =
+ rollback.getPackages().get(0).getVersionRolledBackFrom();
+ rollbackPackage(rollback, firstRollback, rollbackReason);
+ }
+ }
+
+ private List<RollbackInfo> getRollbacksAvailableForImpactLevel(
+ List<RollbackInfo> availableRollbacks, int impactLevel) {
+ return availableRollbacks.stream()
+ .filter(rollbackInfo -> rollbackInfo.getRollbackImpactLevel() == impactLevel)
+ .toList();
+ }
+
+ private int getMinRollbackImpactLevel(List<RollbackInfo> availableRollbacks) {
+ return availableRollbacks.stream()
+ .mapToInt(RollbackInfo::getRollbackImpactLevel)
+ .min()
+ .orElse(-1);
+ }
+
+ private int getUserImpactBasedOnRollbackImpactLevel(List<RollbackInfo> availableRollbacks) {
+ int impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
+ int minImpact = getMinRollbackImpactLevel(availableRollbacks);
+ switch (minImpact) {
+ case PackageManager.ROLLBACK_USER_IMPACT_LOW:
+ impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_70;
+ break;
+ case PackageManager.ROLLBACK_USER_IMPACT_HIGH:
+ if (!SystemProperties.getBoolean(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, false)) {
+ impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_90;
+ }
+ break;
+ default:
+ impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0;
+ }
+ return impact;
+ }
+
+ @VisibleForTesting
+ Handler getHandler() {
+ return mHandler;
+ }
}
diff --git a/packages/CrashRecovery/services/java/com/android/server/rollback/WatchdogRollbackLogger.java b/packages/CrashRecovery/services/java/com/android/server/rollback/WatchdogRollbackLogger.java
index f9ef994..519c0ed 100644
--- a/packages/CrashRecovery/services/java/com/android/server/rollback/WatchdogRollbackLogger.java
+++ b/packages/CrashRecovery/services/java/com/android/server/rollback/WatchdogRollbackLogger.java
@@ -16,16 +16,17 @@
package com.android.server.rollback;
-import static com.android.internal.util.FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH;
-import static com.android.internal.util.FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING;
-import static com.android.internal.util.FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK;
-import static com.android.internal.util.FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH;
-import static com.android.internal.util.FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH_DURING_BOOT;
-import static com.android.internal.util.FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN;
-import static com.android.internal.util.FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED;
-import static com.android.internal.util.FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE;
-import static com.android.internal.util.FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE;
-import static com.android.internal.util.FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_BOOT_LOOPING;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH_DURING_BOOT;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -42,8 +43,8 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.server.PackageWatchdog;
+import com.android.server.crashrecovery.proto.CrashRecoveryStatsLog;
import java.util.List;
import java.util.Set;
@@ -197,8 +198,8 @@
+ " rollbackReason: " + rollbackReasonToString(rollbackReason)
+ " failedPackageName: " + failingPackageName);
if (logPackage != null) {
- FrameworkStatsLog.write(
- FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED,
+ CrashRecoveryStatsLog.write(
+ CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED,
type,
logPackage.getPackageName(),
logPackage.getVersionCode(),
@@ -208,8 +209,8 @@
} else {
// In the case that the log package is null, still log an empty string as an
// indication that retrieving the logging parent failed.
- FrameworkStatsLog.write(
- FrameworkStatsLog.WATCHDOG_ROLLBACK_OCCURRED,
+ CrashRecoveryStatsLog.write(
+ CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED,
type,
"",
0,
@@ -258,6 +259,8 @@
return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH;
case PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING:
return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING;
+ case PackageWatchdog.FAILURE_REASON_BOOT_LOOP:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_BOOT_LOOPING;
default:
return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN;
}
diff --git a/packages/CrashRecovery/services/java/com/android/util/BackgroundThread.java b/packages/CrashRecovery/services/java/com/android/util/BackgroundThread.java
new file mode 100644
index 0000000..a6ae68f
--- /dev/null
+++ b/packages/CrashRecovery/services/java/com/android/util/BackgroundThread.java
@@ -0,0 +1,103 @@
+/*
+ * * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.HandlerThread;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Thread for asynchronous event processing. This thread is configured as
+ * {@link android.os.Process#THREAD_PRIORITY_BACKGROUND}, which means fewer CPU
+ * resources will be dedicated to it, and it will "have less chance of impacting
+ * the responsiveness of the user interface."
+ * <p>
+ * This thread is best suited for tasks that the user is not actively waiting
+ * for, or for tasks that the user expects to be executed eventually.
+ *
+ * @see com.android.internal.os.BackgroundThread
+ *
+ * TODO: b/326916057 depend on modules-utils-backgroundthread instead
+ * @hide
+ */
+public final class BackgroundThread extends HandlerThread {
+ private static final Object sLock = new Object();
+
+ @GuardedBy("sLock")
+ private static BackgroundThread sInstance;
+ @GuardedBy("sLock")
+ private static Handler sHandler;
+ @GuardedBy("sLock")
+ private static HandlerExecutor sHandlerExecutor;
+
+ private BackgroundThread() {
+ super(BackgroundThread.class.getName(), android.os.Process.THREAD_PRIORITY_BACKGROUND);
+ }
+
+ @GuardedBy("sLock")
+ private static void ensureThreadLocked() {
+ if (sInstance == null) {
+ sInstance = new BackgroundThread();
+ sInstance.start();
+ sHandler = new Handler(sInstance.getLooper());
+ sHandlerExecutor = new HandlerExecutor(sHandler);
+ }
+ }
+
+ /**
+ * Get the singleton instance of this class.
+ *
+ * @return the singleton instance of this class
+ */
+ @NonNull
+ public static BackgroundThread get() {
+ synchronized (sLock) {
+ ensureThreadLocked();
+ return sInstance;
+ }
+ }
+
+ /**
+ * Get the singleton {@link Handler} for this class.
+ *
+ * @return the singleton {@link Handler} for this class.
+ */
+ @NonNull
+ public static Handler getHandler() {
+ synchronized (sLock) {
+ ensureThreadLocked();
+ return sHandler;
+ }
+ }
+
+ /**
+ * Get the singleton {@link Executor} for this class.
+ *
+ * @return the singleton {@link Executor} for this class.
+ */
+ @NonNull
+ public static Executor getExecutor() {
+ synchronized (sLock) {
+ ensureThreadLocked();
+ return sHandlerExecutor;
+ }
+ }
+}
diff --git a/packages/CrashRecovery/services/java/com/android/util/HandlerExecutor.java b/packages/CrashRecovery/services/java/com/android/util/HandlerExecutor.java
new file mode 100644
index 0000000..948ebcca
--- /dev/null
+++ b/packages/CrashRecovery/services/java/com/android/util/HandlerExecutor.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+
+/**
+ * An adapter {@link Executor} that posts all executed tasks onto the given
+ * {@link Handler}.
+ *
+ * TODO: b/326916057 depend on modules-utils-backgroundthread instead
+ * @hide
+ */
+public class HandlerExecutor implements Executor {
+ private final Handler mHandler;
+
+ public HandlerExecutor(@NonNull Handler handler) {
+ mHandler = Objects.requireNonNull(handler);
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ if (!mHandler.post(command)) {
+ throw new RejectedExecutionException(mHandler + " is shutting down");
+ }
+ }
+}
diff --git a/packages/CtsShim/OWNERS b/packages/CtsShim/OWNERS
index 9419771..f5741a0 100644
--- a/packages/CtsShim/OWNERS
+++ b/packages/CtsShim/OWNERS
@@ -1,3 +1,2 @@
-ioffe@google.com
-toddke@google.com
-patb@google.com
\ No newline at end of file
+include /PACKAGE_MANAGER_OWNERS
+ioffe@google.com
\ No newline at end of file
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index 933be11..6a4bb21 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -134,8 +134,7 @@
@UsesReflection({
// As the runtime class name is used to generate the returned name, and the returned
// name may be used used with reflection, generate the necessary keep rules.
- @KeepTarget(classConstant = LocalTransport.class),
- @KeepTarget(extendsClassConstant = LocalTransport.class)
+ @KeepTarget(instanceOfClassConstant = LocalTransport.class)
})
@Override
public String name() {
diff --git a/packages/PackageInstaller/OWNERS b/packages/PackageInstaller/OWNERS
index 2736870..acbdff8 100644
--- a/packages/PackageInstaller/OWNERS
+++ b/packages/PackageInstaller/OWNERS
@@ -1,5 +1,4 @@
-svetoslavganov@google.com
+# Bug component: 1002434
include /PACKAGE_MANAGER_OWNERS
-# For automotive related changes
-rogerxue@google.com
+sumedhsen@google.com
\ No newline at end of file
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 8cb25dc..bb05a75 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -368,7 +368,7 @@
final SessionInfo info = mInstaller.getSessionInfo(sessionId);
String resolvedPath = info != null ? info.getResolvedBaseApkPath() : null;
if (info == null || !info.isSealed() || resolvedPath == null) {
- Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
+ Log.w(TAG, "Session " + sessionId + " in funky state; ignoring");
finish();
return;
}
@@ -383,7 +383,7 @@
-1 /* defaultValue */);
final SessionInfo info = mInstaller.getSessionInfo(sessionId);
if (info == null || !info.isPreApprovalRequested()) {
- Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
+ Log.w(TAG, "Session " + sessionId + " in funky state; ignoring");
finish();
return;
}
@@ -797,7 +797,9 @@
// work for the multiple user case, i.e. the caller task user and started
// Activity user are not the same. To avoid having multiple PIAs in the task,
// finish the current PackageInstallerActivity
- finish();
+ // Because finish() is overridden to set the installation result, we must use
+ // the original finish() method, or the confirmation dialog fails to appear.
+ PackageInstallerActivity.super.finish();
}
}, 500);
diff --git a/packages/SettingsLib/AdaptiveIcon/Android.bp b/packages/SettingsLib/AdaptiveIcon/Android.bp
index 934aacf..83524a2 100644
--- a/packages/SettingsLib/AdaptiveIcon/Android.bp
+++ b/packages/SettingsLib/AdaptiveIcon/Android.bp
@@ -14,9 +14,12 @@
resource_dirs: ["res"],
static_libs: [
- "androidx.annotation_annotation",
- "SettingsLibTile"
+ "androidx.annotation_annotation",
+ "SettingsLibTile",
],
min_sdk_version: "21",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index c244ca0..cceead2 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -69,6 +69,9 @@
"src/**/*.java",
"src/**/*.kt",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
// NOTE: Keep this module in sync with ./common.mk
diff --git a/packages/SettingsLib/EmergencyNumber/Android.bp b/packages/SettingsLib/EmergencyNumber/Android.bp
index 25b4905..ebc830c3 100644
--- a/packages/SettingsLib/EmergencyNumber/Android.bp
+++ b/packages/SettingsLib/EmergencyNumber/Android.bp
@@ -16,4 +16,7 @@
],
sdk_version: "system_current",
min_sdk_version: "21",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/SettingsLib/MainSwitchPreference/Android.bp b/packages/SettingsLib/MainSwitchPreference/Android.bp
index 33aa985..a4743a4 100644
--- a/packages/SettingsLib/MainSwitchPreference/Android.bp
+++ b/packages/SettingsLib/MainSwitchPreference/Android.bp
@@ -28,4 +28,7 @@
"com.android.extservices",
"com.android.healthfitness",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/SettingsLib/RestrictedLockUtils/Android.bp b/packages/SettingsLib/RestrictedLockUtils/Android.bp
index 6a8fef3..2f32141 100644
--- a/packages/SettingsLib/RestrictedLockUtils/Android.bp
+++ b/packages/SettingsLib/RestrictedLockUtils/Android.bp
@@ -29,4 +29,7 @@
"//apex_available:platform",
"com.android.permission",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/SettingsLib/SchedulesProvider/Android.bp b/packages/SettingsLib/SchedulesProvider/Android.bp
index c4373bb..cc74feb 100644
--- a/packages/SettingsLib/SchedulesProvider/Android.bp
+++ b/packages/SettingsLib/SchedulesProvider/Android.bp
@@ -13,9 +13,12 @@
srcs: ["src/**/*.java"],
static_libs: [
- "androidx.annotation_annotation",
+ "androidx.annotation_annotation",
],
sdk_version: "system_current",
min_sdk_version: "21",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/SettingsLib/SearchProvider/Android.bp b/packages/SettingsLib/SearchProvider/Android.bp
index f96011a..7e31dc6 100644
--- a/packages/SettingsLib/SearchProvider/Android.bp
+++ b/packages/SettingsLib/SearchProvider/Android.bp
@@ -14,4 +14,7 @@
sdk_version: "system_current",
min_sdk_version: "21",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MoreOptions.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MoreOptions.kt
index 84fea15..d92a863 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MoreOptions.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MoreOptions.kt
@@ -35,8 +35,8 @@
/**
* Scope for the children of [MoreOptionsAction].
*/
-interface MoreOptionsScope {
- fun dismiss()
+abstract class MoreOptionsScope {
+ abstract fun dismiss()
@Composable
fun MenuItem(text: String, enabled: Boolean = true, onClick: () -> Unit) {
@@ -60,7 +60,7 @@
val onDismiss = { expanded = false }
DropdownMenu(expanded = expanded, onDismissRequest = onDismiss) {
val moreOptionsScope = remember(this) {
- object : MoreOptionsScope {
+ object : MoreOptionsScope() {
override fun dismiss() {
onDismiss()
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
index 1a7d896..1859c9b 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
@@ -37,6 +37,7 @@
interface AppRepository {
fun loadLabel(app: ApplicationInfo): String
+ @Suppress("ABSTRACT_COMPOSABLE_DEFAULT_PARAMETER_VALUE")
@Composable
fun produceLabel(app: ApplicationInfo, isClonedAppPage: Boolean = false): State<String> {
val context = LocalContext.current
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItemTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItemTest.kt
index 983284c..2ccf323 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItemTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItemTest.kt
@@ -130,7 +130,7 @@
}
private fun setContent(restrictions: Restrictions) {
- val fakeMoreOptionsScope = object : MoreOptionsScope {
+ val fakeMoreOptionsScope = object : MoreOptionsScope() {
override fun dismiss() {}
}
composeTestRule.setContent {
diff --git a/packages/SettingsLib/Tile/Android.bp b/packages/SettingsLib/Tile/Android.bp
index cc570cc..62c839b3 100644
--- a/packages/SettingsLib/Tile/Android.bp
+++ b/packages/SettingsLib/Tile/Android.bp
@@ -13,8 +13,11 @@
srcs: ["src/**/*.java"],
static_libs: [
- "androidx.annotation_annotation",
+ "androidx.annotation_annotation",
],
min_sdk_version: "21",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/SettingsLib/Utils/Android.bp b/packages/SettingsLib/Utils/Android.bp
index dc2b52d..00b172d 100644
--- a/packages/SettingsLib/Utils/Android.bp
+++ b/packages/SettingsLib/Utils/Android.bp
@@ -30,4 +30,7 @@
"com.android.healthfitness",
"com.android.permission",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 3adb882..e067a08 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -526,7 +526,7 @@
</string-array>
<!-- USB configuration values for Developer Settings.
- These are lists of USB functions passed to the USB Manager to change USB configuraton.
+ These are lists of USB functions passed to the USB Manager to change USB configuration.
This can be overridden by devices with additional USB configurations.
Do not translate. -->
<string-array name="usb_configuration_values" translatable="false">
diff --git a/packages/SettingsLib/search/Android.bp b/packages/SettingsLib/search/Android.bp
index 918d696..9ae2dd7 100644
--- a/packages/SettingsLib/search/Android.bp
+++ b/packages/SettingsLib/search/Android.bp
@@ -12,6 +12,9 @@
visibility: ["//visibility:private"],
srcs: ["interface-src/**/*.java"],
host_supported: true,
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
android_library {
@@ -23,6 +26,9 @@
sdk_version: "system_current",
min_sdk_version: "21",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_plugin {
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
index 1d433e7..943e3fc2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
@@ -59,7 +59,7 @@
@Override
public boolean isAvailable() {
- return true;
+ return mWifiManager != null;
}
@Override
@@ -70,10 +70,8 @@
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- if (isAvailable()) {
- mWifiMacAddress = screen.findPreference(KEY_WIFI_MAC_ADDRESS);
- updateConnectivity();
- }
+ mWifiMacAddress = screen.findPreference(KEY_WIFI_MAC_ADDRESS);
+ updateConnectivity();
}
@Override
@@ -84,16 +82,16 @@
@SuppressLint("HardwareIds")
@Override
protected void updateConnectivity() {
+ if (mWifiManager == null || mWifiMacAddress == null) {
+ return;
+ }
+
final String[] macAddresses = mWifiManager.getFactoryMacAddresses();
String macAddress = null;
if (macAddresses != null && macAddresses.length > 0) {
macAddress = macAddresses[0];
}
- if (mWifiMacAddress == null) {
- return;
- }
-
if (TextUtils.isEmpty(macAddress) || macAddress.equals(WifiInfo.DEFAULT_MAC_ADDRESS)) {
mWifiMacAddress.setSummary(R.string.status_unavailable);
} else {
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 91c72b5..bc93c5b 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -280,6 +280,7 @@
Settings.Global.ENABLE_ADB_INCREMENTAL_INSTALL_DEFAULT,
Settings.Global.ENABLE_MULTI_SLOT_TIMEOUT_MILLIS,
Settings.Global.ENHANCED_4G_MODE_ENABLED,
+ Settings.Global.ENABLE_16K_PAGES, // Added for 16K developer option
Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
Settings.Global.ERROR_LOGCAT_PREFIX,
Settings.Global.EUICC_PROVISIONED,
diff --git a/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java
index 56b940c..1073f61 100644
--- a/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java
+++ b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java
@@ -300,6 +300,8 @@
}
};
installTask.execute(data.getData());
+ } else if (requestCode == ADD_FILE_REQUEST_CODE && resultCode == RESULT_CANCELED) {
+ setupAlert();
}
}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index ad08c51..99383d9 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -15,6 +15,7 @@
//
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
}
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 967a36b..78cacec 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -39,7 +39,6 @@
hyunyoungs@google.com
ikateryna@google.com
iyz@google.com
-jaggies@google.com
jamesoleary@google.com
jbolinger@google.com
jdemeulenaere@google.com
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index f358417..1568d59 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -15,6 +15,7 @@
//
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
index 17db1ac..06ace37 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
@@ -15,6 +15,7 @@
//
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp
index 6f53b42..d700f87 100644
--- a/packages/SystemUI/animation/Android.bp
+++ b/packages/SystemUI/animation/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/checks/Android.bp b/packages/SystemUI/checks/Android.bp
index d3f66e3..4cbc18c 100644
--- a/packages/SystemUI/checks/Android.bp
+++ b/packages/SystemUI/checks/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/packages/SystemUI/common/Android.bp b/packages/SystemUI/common/Android.bp
index e36ada8..53bdf38 100644
--- a/packages/SystemUI/common/Android.bp
+++ b/packages/SystemUI/common/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/compose/core/Android.bp b/packages/SystemUI/compose/core/Android.bp
index ab3efb8..ce9445e 100644
--- a/packages/SystemUI/compose/core/Android.bp
+++ b/packages/SystemUI/compose/core/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/compose/core/tests/Android.bp b/packages/SystemUI/compose/core/tests/Android.bp
index c008bb1..ce2ba03 100644
--- a/packages/SystemUI/compose/core/tests/Android.bp
+++ b/packages/SystemUI/compose/core/tests/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/compose/features/Android.bp b/packages/SystemUI/compose/features/Android.bp
index c6438c9..0fc91c8 100644
--- a/packages/SystemUI/compose/features/Android.bp
+++ b/packages/SystemUI/compose/features/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/compose/features/tests/Android.bp b/packages/SystemUI/compose/features/tests/Android.bp
index c7c9140..77a60b8 100644
--- a/packages/SystemUI/compose/features/tests/Android.bp
+++ b/packages/SystemUI/compose/features/tests/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/customization/Android.bp b/packages/SystemUI/customization/Android.bp
index fc37b355..7fbcb0d 100644
--- a/packages/SystemUI/customization/Android.bp
+++ b/packages/SystemUI/customization/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/log/Android.bp b/packages/SystemUI/log/Android.bp
index 627ac4b..36d5c2f 100644
--- a/packages/SystemUI/log/Android.bp
+++ b/packages/SystemUI/log/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/monet/Android.bp b/packages/SystemUI/monet/Android.bp
index 507ea25..98f7ace 100644
--- a/packages/SystemUI/monet/Android.bp
+++ b/packages/SystemUI/monet/Android.bp
@@ -14,6 +14,7 @@
// limitations under the License.
//
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/packages/SystemUI/plugin/Android.bp b/packages/SystemUI/plugin/Android.bp
index bb47a2f..cb8ec9a 100644
--- a/packages/SystemUI/plugin/Android.bp
+++ b/packages/SystemUI/plugin/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/plugin/ExamplePlugin/Android.bp b/packages/SystemUI/plugin/ExamplePlugin/Android.bp
index 3f0fded..cbfa3f8 100644
--- a/packages/SystemUI/plugin/ExamplePlugin/Android.bp
+++ b/packages/SystemUI/plugin/ExamplePlugin/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/plugin_core/Android.bp b/packages/SystemUI/plugin_core/Android.bp
index 4e39f1a..e8e54c3 100644
--- a/packages/SystemUI/plugin_core/Android.bp
+++ b/packages/SystemUI/plugin_core/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
diff --git a/packages/SystemUI/res/drawable/stat_sys_no_internet_branded_vpn.xml b/packages/SystemUI/res/drawable/stat_sys_no_internet_branded_vpn.xml
new file mode 100644
index 0000000..2161a62
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_no_internet_branded_vpn.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="17dp"
+ android:height="17dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h4V9H12.09zM18,13hv3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H18V13z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M22,10h-2v8h2V10z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M22,20h-2v2h2V20z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_no_internet_vpn_ic.xml b/packages/SystemUI/res/drawable/stat_sys_no_internet_vpn_ic.xml
new file mode 100644
index 0000000..2161a62
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_no_internet_vpn_ic.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="17dp"
+ android:height="17dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h4V9H12.09zM18,13hv3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H18V13z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M22,10h-2v8h2V10z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M22,20h-2v2h2V20z"/>
+</vector>
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index ca30e15..ffa398b 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
@@ -34,6 +35,9 @@
srcs: [
":statslog-SystemUI-java-gen",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
android_library {
@@ -66,6 +70,9 @@
min_sdk_version: "current",
plugins: ["dagger2-compiler"],
kotlincflags: ["-Xjvm-default=all"],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_library {
@@ -77,6 +84,9 @@
static_kotlin_stdlib: false,
java_version: "1.8",
min_sdk_version: "current",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_library {
@@ -96,4 +106,7 @@
},
java_version: "1.8",
min_sdk_version: "current",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index c6d1471..edf9517 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -33,7 +33,7 @@
public abstract class KeyguardAbsKeyInputView extends KeyguardInputView {
protected View mEcaView;
- // To avoid accidental lockout due to events while the device in in the pocket, ignore
+ // To avoid accidental lockout due to events while the device in the pocket, ignore
// any passwords with length less than or equal to this length.
protected static final int MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT = 3;
private KeyDownListener mKeyDownListener;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
index bc12aee..ce03072 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
@@ -132,7 +132,7 @@
boolean shouldSubtleWindowAnimationsForUnlock();
/**
- * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the
+ * Starts the animation before we dismiss Keyguard, i.e. a disappearing animation on the
* security view of the bouncer.
*
* @param finishRunnable the runnable to be run after the animation finished, or {@code null} if
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndication.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndication.java
index 9b83b75..ee3706a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndication.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndication.java
@@ -80,7 +80,7 @@
}
/**
- * Click listener for messsage.
+ * Click listener for message.
*/
public @Nullable View.OnClickListener getClickListener() {
return mOnClickListener;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 1ae5d0a..c385011 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -437,7 +437,7 @@
/**
* Whether a hide is pending and we are just waiting for #startKeyguardExitAnimation to be
* called.
- * */
+ */
private boolean mHiding;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/media/OWNERS b/packages/SystemUI/src/com/android/systemui/media/OWNERS
index 69ea57b..5eb14fc 100644
--- a/packages/SystemUI/src/com/android/systemui/media/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/media/OWNERS
@@ -1 +1,9 @@
-per-file MediaProjectionPermissionActivity.java = michaelwr@google.com
+# Bug component: 78010
+
+asc@google.com
+ethibodeau@google.com
+michaelmikhil@google.com
+
+# Audio team
+per-file RingtonePlayer.java = file:/services/core/java/com/android/server/audio/OWNERS
+per-file NotificationPlayer.java = file:/services/core/java/com/android/server/audio/OWNERS
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS b/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS
new file mode 100644
index 0000000..95b8fa7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 1280508
+
+# Files in this directory should still be reviewed by a member of SystemUI team
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/OWNERS b/packages/SystemUI/src/com/android/systemui/mediaprojection/OWNERS
new file mode 100644
index 0000000..bd74077
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 1345447
+
+include /media/java/android/media/projection/OWNERS
+chrisgollner@google.com
+nickchameyev@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6dbf707..4a5d84a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -22,6 +22,7 @@
import android.app.ActivityTaskManager;
import android.app.AlarmManager;
import android.app.AlarmManager.AlarmClockInfo;
+import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -376,7 +377,7 @@
}
@Override
- public void onConfigChanged(ZenModeConfig config) {
+ public void onConsolidatedPolicyChanged(NotificationManager.Policy policy) {
updateVolumeZen();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 344e56c..ae7c170 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -118,15 +118,25 @@
private void updateVpn() {
boolean vpnVisible = mSecurityController.isVpnEnabled();
- int vpnIconId = currentVpnIconId(mSecurityController.isVpnBranded());
+ int vpnIconId = currentVpnIconId(
+ mSecurityController.isVpnBranded(),
+ mSecurityController.isVpnValidated());
mIconController.setIcon(mSlotVpn, vpnIconId,
mContext.getResources().getString(R.string.accessibility_vpn_on));
mIconController.setIconVisibility(mSlotVpn, vpnVisible);
}
- private int currentVpnIconId(boolean isBranded) {
- return isBranded ? R.drawable.stat_sys_branded_vpn : R.drawable.stat_sys_vpn_ic;
+ private int currentVpnIconId(boolean isBranded, boolean isValidated) {
+ if (isBranded) {
+ return isValidated
+ ? R.drawable.stat_sys_branded_vpn
+ : R.drawable.stat_sys_no_internet_branded_vpn;
+ } else {
+ return isValidated
+ ? R.drawable.stat_sys_vpn_ic
+ : R.drawable.stat_sys_no_internet_vpn_ic;
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
index 3be14bc..10bf0680 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
@@ -48,6 +48,8 @@
boolean isNetworkLoggingEnabled();
boolean isVpnEnabled();
boolean isVpnRestricted();
+ /** Whether the VPN network is validated. */
+ boolean isVpnValidated();
/** Whether the VPN app should use branded VPN iconography. */
boolean isVpnBranded();
String getPrimaryVpnName();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 03656f0..ada2196 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -15,6 +15,9 @@
*/
package com.android.systemui.statusbar.policy;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+
import android.annotation.Nullable;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManager;
@@ -32,7 +35,9 @@
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.VpnManager;
import android.os.Handler;
@@ -76,7 +81,10 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final NetworkRequest REQUEST =
- new NetworkRequest.Builder().clearCapabilities().build();
+ new NetworkRequest.Builder()
+ .clearCapabilities()
+ .addTransportType(TRANSPORT_VPN)
+ .build();
private static final int NO_NETWORK = -1;
private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED";
@@ -99,6 +107,8 @@
private SparseArray<VpnConfig> mCurrentVpns = new SparseArray<>();
private int mCurrentUserId;
private int mVpnUserId;
+ @GuardedBy("mNetworkProperties")
+ private final SparseArray<NetworkProperties> mNetworkProperties = new SparseArray<>();
// Key: userId, Value: whether the user has CACerts installed
// Needs to be cached here since the query has to be asynchronous
@@ -162,6 +172,21 @@
pw.print(mCurrentVpns.valueAt(i).user);
}
pw.println("}");
+ pw.print(" mNetworkProperties={");
+ synchronized (mNetworkProperties) {
+ for (int i = 0; i < mNetworkProperties.size(); ++i) {
+ if (i > 0) {
+ pw.print(", ");
+ }
+ pw.print(mNetworkProperties.keyAt(i));
+ pw.print("={");
+ pw.print(mNetworkProperties.valueAt(i).interfaceName);
+ pw.print(", ");
+ pw.print(mNetworkProperties.valueAt(i).validated);
+ pw.print("}");
+ }
+ }
+ pw.println("}");
}
@Override
@@ -304,6 +329,26 @@
}
@Override
+ public boolean isVpnValidated() {
+ // Prioritize reporting the network status of the parent user.
+ final VpnConfig primaryVpnConfig = mCurrentVpns.get(mVpnUserId);
+ if (primaryVpnConfig != null) {
+ return getVpnValidationStatus(primaryVpnConfig);
+ }
+ // Identify any Unvalidated status in each active VPN network within other profiles.
+ for (int profileId : mUserManager.getEnabledProfileIds(mVpnUserId)) {
+ final VpnConfig vpnConfig = mCurrentVpns.get(profileId);
+ if (vpnConfig == null) {
+ continue;
+ }
+ if (!getVpnValidationStatus(vpnConfig)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
public boolean hasCACertInCurrentUser() {
Boolean hasCACerts = mHasCACerts.get(mCurrentUserId);
return hasCACerts != null && hasCACerts.booleanValue();
@@ -491,11 +536,74 @@
@Override
public void onLost(Network network) {
if (DEBUG) Log.d(TAG, "onLost " + network.getNetId());
+ synchronized (mNetworkProperties) {
+ mNetworkProperties.delete(network.getNetId());
+ }
updateState();
fireCallbacks();
};
+
+
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
+ if (DEBUG) Log.d(TAG, "onCapabilitiesChanged " + network.getNetId());
+ final NetworkProperties properties;
+ synchronized (mNetworkProperties) {
+ properties = mNetworkProperties.get(network.getNetId());
+ }
+ // When a new network appears, the system first notifies the application about
+ // its capabilities through onCapabilitiesChanged. This initial notification
+ // will be skipped because the interface information is included in the
+ // subsequent onLinkPropertiesChanged call. After validating the network, the
+ // system might send another onCapabilitiesChanged notification if the network
+ // becomes validated.
+ if (properties == null) {
+ return;
+ }
+ final boolean validated = nc.hasCapability(NET_CAPABILITY_VALIDATED);
+ if (properties.validated != validated) {
+ properties.validated = validated;
+ fireCallbacks();
+ }
+ }
+
+ @Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
+ if (DEBUG) Log.d(TAG, "onLinkPropertiesChanged " + network.getNetId());
+ final String interfaceName = linkProperties.getInterfaceName();
+ if (interfaceName == null) {
+ Log.w(TAG, "onLinkPropertiesChanged event with null interface");
+ return;
+ }
+ synchronized (mNetworkProperties) {
+ final NetworkProperties properties = mNetworkProperties.get(network.getNetId());
+ if (properties == null) {
+ mNetworkProperties.put(
+ network.getNetId(),
+ new NetworkProperties(interfaceName, false));
+ } else {
+ properties.interfaceName = interfaceName;
+ }
+ }
+ }
};
+ /**
+ * Retrieve the validation status of the VPN network associated with the given VpnConfig.
+ */
+ private boolean getVpnValidationStatus(@NonNull VpnConfig vpnConfig) {
+ synchronized (mNetworkProperties) {
+ // Find the network has the same interface as the VpnConfig
+ for (int i = 0; i < mNetworkProperties.size(); ++i) {
+ if (mNetworkProperties.valueAt(i).interfaceName.equals(vpnConfig.interfaze)) {
+ return mNetworkProperties.valueAt(i).validated;
+ }
+ }
+ }
+ // If no matching network is found, consider it validated.
+ return true;
+ }
+
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
if (KeyChain.ACTION_TRUST_STORE_CHANGED.equals(intent.getAction())) {
@@ -506,4 +614,17 @@
}
}
};
+
+ /**
+ * A data class to hold specific Network properties received through the NetworkCallback.
+ */
+ private static class NetworkProperties {
+ public String interfaceName;
+ public boolean validated;
+
+ NetworkProperties(@NonNull String interfaceName, boolean validated) {
+ this.interfaceName = interfaceName;
+ this.validated = validated;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS
index a601e9b..0b9f559 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS
@@ -4,5 +4,4 @@
galinap@google.com
patrikf@google.com
robhor@google.com
-sergeynv@google.com
diff --git a/packages/SystemUI/tests/Android.bp b/packages/SystemUI/tests/Android.bp
index 3c418ed..1594ec5 100644
--- a/packages/SystemUI/tests/Android.bp
+++ b/packages/SystemUI/tests/Android.bp
@@ -15,6 +15,7 @@
//
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS
new file mode 100644
index 0000000..e6f218f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/src/com/android/systemui/media/OWNERS
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/OWNERS
new file mode 100644
index 0000000..100dd2e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS
diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/OWNERS
new file mode 100644
index 0000000..f87d93a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/OWNERS
@@ -0,0 +1 @@
+include /packages/SystemUI/src/com/android/systemui/mediaprojection/OWNERS
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
index c35bc69..bcc9272 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.policy;
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -213,7 +214,8 @@
public void testNetworkRequest() {
verify(mConnectivityManager, times(1)).registerNetworkCallback(argThat(
(NetworkRequest request) ->
- request.equals(new NetworkRequest.Builder().clearCapabilities().build())
+ request.equals(new NetworkRequest.Builder()
+ .clearCapabilities().addTransportType(TRANSPORT_VPN).build())
), any(NetworkCallback.class));
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt
index 021e7df..ac90a45 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt
@@ -77,6 +77,8 @@
override fun isVpnBranded(): Boolean = fakeState.isVpnBranded
+ override fun isVpnValidated(): Boolean = fakeState.isVpnValidated
+
override fun getPrimaryVpnName(): String? = fakeState.primaryVpnName
override fun getWorkProfileVpnName(): String? = fakeState.workProfileVpnName
@@ -110,6 +112,7 @@
var isVpnEnabled: Boolean = false,
var isVpnRestricted: Boolean = false,
var isVpnBranded: Boolean = false,
+ var isVpnValidated: Boolean = false,
var primaryVpnName: String? = null,
var workProfileVpnName: String? = null,
var hasCACertInCurrentUser: Boolean = false,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeSecurityController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeSecurityController.java
index 76199e3..791165d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeSecurityController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeSecurityController.java
@@ -109,6 +109,11 @@
}
@Override
+ public boolean isVpnValidated() {
+ return false;
+ }
+
+ @Override
public String getPrimaryVpnName() {
return null;
}
diff --git a/packages/SystemUI/unfold/Android.bp b/packages/SystemUI/unfold/Android.bp
index 1f0181f..c8109e6 100644
--- a/packages/SystemUI/unfold/Android.bp
+++ b/packages/SystemUI/unfold/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
@@ -38,4 +39,7 @@
sdk_version: "current",
min_sdk_version: "current",
plugins: ["dagger2-compiler"],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/overlays/Android.bp b/packages/overlays/Android.bp
new file mode 100644
index 0000000..5e001fb
--- /dev/null
+++ b/packages/overlays/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "frameworks_base_license",
+ ],
+}
+
+phony {
+ name: "frameworks-base-overlays",
+ required: [
+ "DisplayCutoutEmulationCornerOverlay",
+ "DisplayCutoutEmulationDoubleOverlay",
+ "DisplayCutoutEmulationHoleOverlay",
+ "DisplayCutoutEmulationTallOverlay",
+ "DisplayCutoutEmulationWaterfallOverlay",
+ "FontNotoSerifSourceOverlay",
+ "NavigationBarMode3ButtonOverlay",
+ "NavigationBarModeGesturalOverlay",
+ "NavigationBarModeGesturalOverlayNarrowBack",
+ "NavigationBarModeGesturalOverlayWideBack",
+ "NavigationBarModeGesturalOverlayExtraWideBack",
+ "TransparentNavigationBarOverlay",
+ "NotesRoleEnabledOverlay",
+ "preinstalled-packages-platform-overlays.xml",
+ ],
+}
+
+phony {
+ name: "frameworks-base-overlays-debug",
+}
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
deleted file mode 100644
index a41d0e5..0000000
--- a/packages/overlays/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := frameworks-base-overlays
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-LOCAL_REQUIRED_MODULES := \
- DisplayCutoutEmulationCornerOverlay \
- DisplayCutoutEmulationDoubleOverlay \
- DisplayCutoutEmulationHoleOverlay \
- DisplayCutoutEmulationTallOverlay \
- DisplayCutoutEmulationWaterfallOverlay \
- FontNotoSerifSourceOverlay \
- NavigationBarMode3ButtonOverlay \
- NavigationBarModeGesturalOverlay \
- NavigationBarModeGesturalOverlayNarrowBack \
- NavigationBarModeGesturalOverlayWideBack \
- NavigationBarModeGesturalOverlayExtraWideBack \
- TransparentNavigationBarOverlay \
- NotesRoleEnabledOverlay \
- preinstalled-packages-platform-overlays.xml
-
-include $(BUILD_PHONY_PACKAGE)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := frameworks-base-overlays-debug
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-
-include $(BUILD_PHONY_PACKAGE)
-include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java
index 67c2caa..e9f6031 100644
--- a/rs/java/android/renderscript/ScriptC.java
+++ b/rs/java/android/renderscript/ScriptC.java
@@ -38,12 +38,12 @@
private static final String TAG = "ScriptC";
/**
- * In targetSdkVersion 35 and above, Renderscript's ScriptC stops being supported
+ * In targetSdkVersion 36 and above, Renderscript's ScriptC stops being supported
* and an exception is thrown when the class is instantiated.
- * In targetSdkVersion 34 and below, Renderscript's ScriptC still works.
+ * In targetSdkVersion 35 and below, Renderscript's ScriptC still works.
*/
@ChangeId
- @EnabledAfter(targetSdkVersion = 35)
+ @EnabledAfter(targetSdkVersion = 36)
private static final long RENDERSCRIPT_SCRIPTC_DEPRECATION_CHANGE_ID = 297019750L;
/**
@@ -101,9 +101,21 @@
setID(id);
}
- private static void throwExceptionIfSDKTooHigh() {
+ private static void throwExceptionIfScriptCUnsupported() {
+ // Checks that this device actually does have an ABI that supports ScriptC.
+ //
+ // For an explanation as to why `System.loadLibrary` is used, see discussion at
+ // https://android-review.googlesource.com/c/platform/frameworks/base/+/2957974/comment/2f908b80_a05292ee
+ try {
+ System.loadLibrary("RS");
+ } catch (UnsatisfiedLinkError e) {
+ String s = "This device does not have an ABI that supports ScriptC.";
+ throw new UnsupportedOperationException(s);
+ }
+
+ // Throw an exception if the target API is 36 or above
String message =
- "ScriptC scripts are not supported when targeting an API Level >= 35. Please refer "
+ "ScriptC scripts are not supported when targeting an API Level >= 36. Please refer "
+ "to https://developer.android.com/guide/topics/renderscript/migration-guide "
+ "for proposed alternatives.";
Slog.w(TAG, message);
@@ -113,7 +125,7 @@
}
private static synchronized long internalCreate(RenderScript rs, Resources resources, int resourceID) {
- throwExceptionIfSDKTooHigh();
+ throwExceptionIfScriptCUnsupported();
byte[] pgm;
int pgmLength;
InputStream is = resources.openRawResource(resourceID);
@@ -150,7 +162,7 @@
private static synchronized long internalStringCreate(RenderScript rs, String resName, byte[] bitcode) {
// Log.v(TAG, "Create script for resource = " + resName);
- throwExceptionIfSDKTooHigh();
+ throwExceptionIfScriptCUnsupported();
return rs.nScriptCCreate(resName, RenderScript.getCachePath(), bitcode, bitcode.length);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index da9235f..5b06894 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -16,7 +16,6 @@
package com.android.server.autofill;
-import static android.Manifest.permission.PROVIDE_OWN_AUTOFILL_SUGGESTIONS;
import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
import static android.service.autofill.AutofillService.EXTRA_FILL_RESPONSE;
import static android.service.autofill.Dataset.PICK_REASON_NO_PCC;
@@ -109,8 +108,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.graphics.Bitmap;
import android.graphics.Rect;
@@ -1528,6 +1525,17 @@
return;
}
+ if (mSessionFlags.mShowingSaveUi) {
+ // Even though the session has not yet been destroyed at this point, after the
+ // saveUi gets closed, the session will be destroyed and AutofillManager will reset
+ // its state. Processing the fill request will result in a great chance of corrupt
+ // state in Autofill.
+ Slog.w(TAG, "Call to Session#onFillRequestSuccess() rejected - session: "
+ + id + " is showing saveUi");
+ mFillResponseEventLogger.maybeSetResponseStatus(RESPONSE_STATUS_SESSION_DESTROYED);
+ mFillResponseEventLogger.logAndEndEvent();
+ return;
+ }
requestLog = mRequestLogs.get(requestId);
if (requestLog != null) {
diff --git a/services/backup/Android.bp b/services/backup/Android.bp
index b086406..f959ef4 100644
--- a/services/backup/Android.bp
+++ b/services/backup/Android.bp
@@ -20,4 +20,7 @@
srcs: [":services.backup-sources"],
libs: ["services.core"],
static_libs: ["app-compat-annotations"],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
index a248d9e5..de44378 100644
--- a/services/companion/Android.bp
+++ b/services/companion/Android.bp
@@ -27,4 +27,7 @@
static_libs: [
"ukey2_jni",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
index 720687e..0e66fbc 100644
--- a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
+++ b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
@@ -23,12 +23,12 @@
import android.os.Build;
import android.util.Slog;
-import com.google.security.cryptauth.lib.securegcm.BadHandleException;
-import com.google.security.cryptauth.lib.securegcm.CryptoException;
-import com.google.security.cryptauth.lib.securegcm.D2DConnectionContextV1;
-import com.google.security.cryptauth.lib.securegcm.D2DHandshakeContext;
-import com.google.security.cryptauth.lib.securegcm.D2DHandshakeContext.Role;
-import com.google.security.cryptauth.lib.securegcm.HandshakeException;
+import com.google.security.cryptauth.lib.securegcm.ukey2.BadHandleException;
+import com.google.security.cryptauth.lib.securegcm.ukey2.CryptoException;
+import com.google.security.cryptauth.lib.securegcm.ukey2.D2DConnectionContextV1;
+import com.google.security.cryptauth.lib.securegcm.ukey2.D2DHandshakeContext;
+import com.google.security.cryptauth.lib.securegcm.ukey2.D2DHandshakeContext.Role;
+import com.google.security.cryptauth.lib.securegcm.ukey2.HandshakeException;
import libcore.io.IoUtils;
import libcore.io.Streams;
diff --git a/services/contextualsearch/OWNERS b/services/contextualsearch/OWNERS
new file mode 100644
index 0000000..0c2612c
--- /dev/null
+++ b/services/contextualsearch/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/contextualsearch/OWNERS
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 8d88b61..2ed75d9 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -190,6 +190,8 @@
"com.android.sysprop.watchdog",
"ImmutabilityAnnotation",
"securebox",
+ "net_flags_lib",
+ "core_os_flags_lib",
],
javac_shard_size: 50,
javacflags: [
@@ -199,6 +201,9 @@
"-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_genrule {
@@ -217,6 +222,9 @@
java_library {
name: "services.core",
static_libs: ["services.core.priorityboosted"],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_library_host {
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 3aa275c..89fb9ce 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -27,6 +27,7 @@
per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS
per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS
per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
+per-file *SecurityStateManager* = file:/SECURITY_STATE_OWNERS
per-file *SoundTrigger* = file:/media/java/android/media/soundtrigger/OWNERS
per-file *Storage* = file:/core/java/android/os/storage/OWNERS
per-file *TimeUpdate* = file:/services/core/java/com/android/server/timezonedetector/OWNERS
@@ -37,8 +38,12 @@
per-file PackageWatchdog.java, RescueParty.java = file:/services/core/java/com/android/server/rollback/OWNERS
per-file PinnerService.java = file:/apct-tests/perftests/OWNERS
per-file RescueParty.java = shuc@google.com, ancr@google.com, harshitmahajan@google.com
+per-file SensitiveContentProtectionManagerService.java = file:/core/java/android/permission/OWNERS
per-file SystemClockTime.java = file:/services/core/java/com/android/server/timedetector/OWNERS
per-file SystemTimeZone.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS
per-file TelephonyRegistry.java = file:/telephony/OWNERS
per-file UiModeManagerService.java = file:/packages/SystemUI/OWNERS
per-file VcnManagementService.java = file:/services/core/java/com/android/server/vcn/OWNERS
+
+# SystemConfig
+per-file SystemConfig.java = file:/PACKAGE_MANAGER_OWNERS
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 1595a35..f952c99 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1341,8 +1341,8 @@
final int flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
for (UserInfo user : users) {
- prepareUserStorageInternal(fromVolumeUuid, user.id, user.serialNumber, flags);
- prepareUserStorageInternal(toVolumeUuid, user.id, user.serialNumber, flags);
+ prepareUserStorageInternal(fromVolumeUuid, user.id, flags);
+ prepareUserStorageInternal(toVolumeUuid, user.id, flags);
}
}
@@ -3210,12 +3210,12 @@
@android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL)
@Override
- public void createUserStorageKeys(int userId, int serialNumber, boolean ephemeral) {
+ public void createUserStorageKeys(int userId, boolean ephemeral) {
super.createUserStorageKeys_enforcePermission();
try {
- mVold.createUserStorageKeys(userId, serialNumber, ephemeral);
+ mVold.createUserStorageKeys(userId, ephemeral);
// Since the user's CE key was just created, the user's CE storage is now unlocked.
synchronized (mLock) {
mCeUnlockedUsers.append(userId);
@@ -3255,12 +3255,11 @@
/* Only for use by LockSettingsService */
@android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL)
@Override
- public void unlockCeStorage(@UserIdInt int userId, int serialNumber, byte[] secret)
- throws RemoteException {
+ public void unlockCeStorage(@UserIdInt int userId, byte[] secret) throws RemoteException {
super.unlockCeStorage_enforcePermission();
if (StorageManager.isFileEncrypted()) {
- mVold.unlockCeStorage(userId, serialNumber, HexDump.toHexString(secret));
+ mVold.unlockCeStorage(userId, HexDump.toHexString(secret));
}
synchronized (mLock) {
mCeUnlockedUsers.append(userId);
@@ -3327,27 +3326,27 @@
continue;
}
- prepareUserStorageInternal(vol.fsUuid, user.id, user.serialNumber, flags);
+ prepareUserStorageInternal(vol.fsUuid, user.id, flags);
}
}
@android.annotation.EnforcePermission(android.Manifest.permission.STORAGE_INTERNAL)
@Override
- public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
+ public void prepareUserStorage(String volumeUuid, int userId, int flags) {
super.prepareUserStorage_enforcePermission();
try {
- prepareUserStorageInternal(volumeUuid, userId, serialNumber, flags);
+ prepareUserStorageInternal(volumeUuid, userId, flags);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
- private void prepareUserStorageInternal(String volumeUuid, int userId, int serialNumber,
- int flags) throws Exception {
+ private void prepareUserStorageInternal(String volumeUuid, int userId, int flags)
+ throws Exception {
try {
- mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
+ mVold.prepareUserStorage(volumeUuid, userId, flags);
// After preparing user storage, we should check if we should mount data mirror again,
// and we do it for user 0 only as we only need to do once for all users.
if (volumeUuid != null) {
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index bca2d60..31db840 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -316,12 +316,16 @@
private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
private final ArraySet<String> mAppDataIsolationWhitelistedApps = new ArraySet<>();
+ // These packages will be set as 'prevent disable', where they are no longer possible
+ // for the end user to disable via settings. This flag should only be used for packages
+ // which meet the 'force or keep enabled apps' policy.
+ private final ArrayList<String> mPreventUserDisablePackages = new ArrayList<>();
+
// Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService().
private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>();
private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>();
private final ArraySet<String> mRollbackWhitelistedPackages = new ArraySet<>();
- private final ArraySet<String> mAutomaticRollbackDenylistedPackages = new ArraySet<>();
private final ArraySet<String> mWhitelistedStagedInstallers = new ArraySet<>();
// A map from package name of vendor APEXes that can be updated to an installer package name
// allowed to install updates for it.
@@ -470,10 +474,6 @@
return mRollbackWhitelistedPackages;
}
- public Set<String> getAutomaticRollbackDenylistedPackages() {
- return mAutomaticRollbackDenylistedPackages;
- }
-
public Set<String> getWhitelistedStagedInstallers() {
return mWhitelistedStagedInstallers;
}
@@ -501,6 +501,10 @@
return mAppDataIsolationWhitelistedApps;
}
+ public @NonNull ArrayList<String> getPreventUserDisablePackages() {
+ return mPreventUserDisablePackages;
+ }
+
/**
* Gets map of packagesNames to userTypes, dictating on which user types each package should be
* initially installed, and then removes this map from SystemConfig.
@@ -1303,6 +1307,16 @@
}
XmlUtils.skipCurrentTag(parser);
} break;
+ case "prevent-disable": {
+ String pkgname = parser.getAttributeValue(null, "package");
+ if (pkgname == null) {
+ Slog.w(TAG, "<" + name + "> without package in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else {
+ mPreventUserDisablePackages.add(pkgname);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ } break;
case "install-in-user-type": {
// NB: We allow any directory permission to declare install-in-user-type.
readInstallInUserType(parser,
@@ -1377,16 +1391,6 @@
}
XmlUtils.skipCurrentTag(parser);
} break;
- case "automatic-rollback-denylisted-app": {
- String pkgname = parser.getAttributeValue(null, "package");
- if (pkgname == null) {
- Slog.w(TAG, "<" + name + "> without package in " + permFile
- + " at " + parser.getPositionDescription());
- } else {
- mAutomaticRollbackDenylistedPackages.add(pkgname);
- }
- XmlUtils.skipCurrentTag(parser);
- } break;
case "whitelisted-staged-installer": {
if (allowAppConfigs) {
String pkgname = parser.getAttributeValue(null, "package");
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 2ba3a1d..1d1e2d9 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -30,7 +30,6 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
-import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.IVpnManager;
import android.net.Network;
@@ -89,8 +88,6 @@
private final Context mUserAllContext;
private final Dependencies mDeps;
-
- private final ConnectivityManager mCm;
private final VpnProfileStore mVpnProfileStore;
private final INetworkManagementService mNMS;
private final INetd mNetd;
@@ -164,7 +161,6 @@
mHandler = mHandlerThread.getThreadHandler();
mVpnProfileStore = mDeps.getVpnProfileStore();
mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
- mCm = mContext.getSystemService(ConnectivityManager.class);
mNMS = mDeps.getINetworkManagementService();
mNetd = mDeps.getNetd();
mUserManager = mContext.getSystemService(UserManager.class);
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index df86c5e..a564b7d 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -129,6 +129,7 @@
"media.swcodec", // /apex/com.android.media.swcodec/bin/mediaswcodec
"media.transcoding", // Media transcoding service
"com.android.bluetooth", // Bluetooth service
+ "/apex/com.android.art/bin/artd", // ART daemon
"/apex/com.android.os.statsd/bin/statsd", // Stats daemon
};
@@ -163,6 +164,7 @@
public static final String[] AIDL_INTERFACE_PREFIXES_OF_INTEREST = new String[] {
"android.hardware.audio.core.IModule/",
"android.hardware.audio.core.IConfig/",
+ "android.hardware.audio.effect.IFactory/",
"android.hardware.biometrics.face.IFace/",
"android.hardware.biometrics.fingerprint.IFingerprint/",
"android.hardware.bluetooth.IBluetoothHci/",
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index 627a62e..34c3d7e 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -246,16 +246,6 @@
@Override
public void run() {
- if (mGuid.isEmpty()) {
- Slog.e(TAG, "adbwifi guid was not set");
- return;
- }
- mPort = native_pairing_start(mGuid, mPairingCode);
- if (mPort <= 0 || mPort > 65535) {
- Slog.e(TAG, "Unable to start pairing server");
- return;
- }
-
// Register the mdns service
NsdServiceInfo serviceInfo = new NsdServiceInfo();
serviceInfo.setServiceName(mServiceName);
@@ -288,6 +278,28 @@
mHandler.sendMessage(message);
}
+ @Override
+ public void start() {
+ /*
+ * If a user is fast enough to click cancel, native_pairing_cancel can be invoked
+ * while native_pairing_start is running which run the destruction of the object
+ * while it is being constructed. Here we start the pairing server on foreground
+ * Thread so native_pairing_cancel can never be called concurrently. Then we let
+ * the pairing server run on a background Thread.
+ */
+ if (mGuid.isEmpty()) {
+ Slog.e(TAG, "adbwifi guid was not set");
+ return;
+ }
+ mPort = native_pairing_start(mGuid, mPairingCode);
+ if (mPort <= 0) {
+ Slog.e(TAG, "Unable to start pairing server");
+ return;
+ }
+
+ super.start();
+ }
+
public void cancelPairing() {
native_pairing_cancel();
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 1b83327..ac8d56b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -396,7 +396,7 @@
case "get-bg-restriction-level":
return runGetBgRestrictionLevel(pw);
case "observe-foreground-process":
- return runGetCurrentForegroundProcess(pw, mInternal, mTaskInterface);
+ return runGetCurrentForegroundProcess(pw, mInternal);
case "reset-dropbox-rate-limiter":
return runResetDropboxRateLimiter();
case "list-displays-for-starting-users":
@@ -3644,11 +3644,10 @@
return -1;
}
- private int runGetCurrentForegroundProcess(PrintWriter pw,
- IActivityManager iam, IActivityTaskManager iatm)
+ private int runGetCurrentForegroundProcess(PrintWriter pw, IActivityManager iam)
throws RemoteException {
- ProcessObserver observer = new ProcessObserver(pw, iam, iatm, mInternal);
+ ProcessObserver observer = new ProcessObserver(pw, iam);
iam.registerProcessObserver(observer);
final InputStream mInput = getRawInputStream();
@@ -3683,15 +3682,10 @@
private PrintWriter mPw;
private IActivityManager mIam;
- private IActivityTaskManager mIatm;
- private ActivityManagerService mInternal;
- ProcessObserver(PrintWriter mPw, IActivityManager mIam,
- IActivityTaskManager mIatm, ActivityManagerService ams) {
+ ProcessObserver(PrintWriter mPw, IActivityManager mIam) {
this.mPw = mPw;
this.mIam = mIam;
- this.mIatm = mIatm;
- this.mInternal = ams;
}
@Override
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index db93323..0caf26a 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -264,7 +264,7 @@
@VisibleForTesting static final String DEFAULT_COMPACT_PROC_STATE_THROTTLE =
String.valueOf(ActivityManager.PROCESS_STATE_RECEIVER);
@VisibleForTesting static final long DEFAULT_FREEZER_DEBOUNCE_TIMEOUT = 10_000L;
- @VisibleForTesting static final boolean DEFAULT_FREEZER_EXEMPT_INST_PKG = true;
+ @VisibleForTesting static final boolean DEFAULT_FREEZER_EXEMPT_INST_PKG = false;
@VisibleForTesting static final boolean DEFAULT_FREEZER_BINDER_ENABLED = true;
@VisibleForTesting static final long DEFAULT_FREEZER_BINDER_DIVISOR = 4;
@VisibleForTesting static final int DEFAULT_FREEZER_BINDER_OFFSET = 500;
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 2aed847..0f75ad48 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -31,7 +31,7 @@
30017 am_low_memory (Num Processes|1|1)
# Kill a process to reclaim memory.
-30023 am_kill (User|1|5),(PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3)
+30023 am_kill (User|1|5),(PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3),(Rss|2|2)
# Discard an undelivered serialized broadcast (timeout/ANR/crash)
30024 am_broadcast_discard_filter (User|1|5),(Broadcast|1|5),(Action|3),(Receiver Number|1|1),(BroadcastFilter|1|5)
30025 am_broadcast_discard_app (User|1|5),(Broadcast|1|5),(Action|3),(Receiver Number|1|1),(App|3)
diff --git a/services/core/java/com/android/server/am/OomConnection.java b/services/core/java/com/android/server/am/OomConnection.java
new file mode 100644
index 0000000..17a4ce5
--- /dev/null
+++ b/services/core/java/com/android/server/am/OomConnection.java
@@ -0,0 +1,63 @@
+/*
+ * 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.am;
+
+import android.os.OomKillRecord;
+import android.util.Slog;
+
+/** Connection to the out-of-memory (OOM) events' file */
+public final class OomConnection {
+ private static final String TAG = "OomConnection";
+
+ /** Connection listener interface */
+ public interface OomConnectionListener {
+
+ /**
+ * Callback function to handle the newest OOM kills.
+ *
+ * @param oomKills List of oom kills received from `waitOom()`
+ */
+ void handleOomEvent(OomKillRecord[] oomKills);
+ }
+
+ private final OomConnectionListener mOomListener;
+
+ private final OomConnectionThread mOomConnectionThread;
+
+ private static native OomKillRecord[] waitOom();
+
+ public OomConnection(OomConnectionListener listener) {
+ mOomListener = listener;
+ mOomConnectionThread = new OomConnectionThread();
+ mOomConnectionThread.start();
+ }
+
+ private final class OomConnectionThread extends Thread {
+ public void run() {
+ while (true) {
+ OomKillRecord[] oom_kills = null;
+ try {
+ oom_kills = waitOom();
+ mOomListener.handleOomEvent(oom_kills);
+ } catch (RuntimeException e) {
+ Slog.e(TAG, "failed waiting for OOM events: " + e);
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/PhantomProcessRecord.java b/services/core/java/com/android/server/am/PhantomProcessRecord.java
index 1a692df..ac96bdc 100644
--- a/services/core/java/com/android/server/am/PhantomProcessRecord.java
+++ b/services/core/java/com/android/server/am/PhantomProcessRecord.java
@@ -105,6 +105,11 @@
}
}
+ public long getRss(int pid) {
+ long[] rss = Process.getRss(pid);
+ return (rss != null && rss.length > 0) ? rss[0] : 0;
+ }
+
@GuardedBy("mLock")
void killLocked(String reason, boolean noisy) {
if (!mKilled) {
@@ -115,7 +120,7 @@
}
if (mPid > 0) {
EventLog.writeEvent(EventLogTags.AM_KILL, UserHandle.getUserId(mUid),
- mPid, mProcessName, mAdj, reason);
+ mPid, mProcessName, mAdj, reason, getRss(mPid));
if (!Process.supportsPidFd()) {
onProcDied(false);
} else {
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 667e883..eddd56ad 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -299,6 +299,11 @@
SparseBooleanArray lastPids = new SparseBooleanArray(20);
ActivityManagerService.VolatileDropboxEntryStates volatileDropboxEntriyStates = null;
+ if (mApp.isDebugging()) {
+ Slog.i(TAG, "Skipping debugged app ANR: " + this + " " + annotation);
+ return;
+ }
+
mApp.getWindowProcessController().appEarlyNotResponding(annotation, () -> {
latencyTracker.waitingOnAMSLockStarted();
synchronized (mService) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 9c82a8d..1ad85426 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -97,6 +97,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.OomKillRecord;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteCallbackList;
@@ -412,6 +413,8 @@
private static LmkdConnection sLmkdConnection = null;
+ private static OomConnection sOomConnection = null;
+
private boolean mOomLevelsSet = false;
private boolean mAppDataIsolationEnabled = false;
@@ -855,6 +858,21 @@
THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
sKillThread.start();
sKillHandler = new KillHandler(sKillThread.getLooper());
+ sOomConnection = new OomConnection(new OomConnection.OomConnectionListener() {
+ @Override
+ public void handleOomEvent(OomKillRecord[] oomKills) {
+ for (OomKillRecord oomKill: oomKills) {
+ synchronized (mProcLock) {
+ noteAppKill(
+ oomKill.getPid(),
+ oomKill.getUid(),
+ ApplicationExitInfo.REASON_LOW_MEMORY,
+ ApplicationExitInfo.SUBREASON_OOM_KILL,
+ "oom");
+ }
+ }
+ }
+ });
sLmkdConnection = new LmkdConnection(sKillThread.getLooper().getQueue(),
new LmkdConnection.LmkdConnectionListener() {
@Override
@@ -2861,7 +2879,11 @@
return true;
}
- private static void freezeBinderAndPackageCgroup(ArrayList<Pair<ProcessRecord, Boolean>> procs,
+ private static boolean unfreezePackageCgroup(int packageUID) {
+ return freezePackageCgroup(packageUID, false);
+ }
+
+ private static void freezeBinderAndPackageCgroup(List<Pair<ProcessRecord, Boolean>> procs,
int packageUID) {
// Freeze all binder processes under the target UID (whose cgroup is about to be frozen).
// Since we're going to kill these, we don't need to unfreze them later.
@@ -2869,12 +2891,9 @@
// processes (forks) should not be Binder users.
int N = procs.size();
for (int i = 0; i < N; i++) {
- final int uid = procs.get(i).first.uid;
final int pid = procs.get(i).first.getPid();
int nRetries = 0;
- // We only freeze the cgroup of the target package, so we do not need to freeze the
- // Binder interfaces of dependant processes in other UIDs.
- if (pid > 0 && uid == packageUID) {
+ if (pid > 0) {
try {
int rc;
do {
@@ -2888,12 +2907,19 @@
}
// We freeze the entire UID (parent) cgroup so that newly-specialized processes also freeze
- // despite being added to a new child cgroup. The cgroups of package dependant processes are
- // not frozen, since it's possible this would freeze processes with no dependency on the
- // package being killed here.
+ // despite being added to a child cgroup created after this call that would otherwise be
+ // unfrozen.
freezePackageCgroup(packageUID, true);
}
+ private static List<Pair<ProcessRecord, Boolean>> getUIDSublist(
+ List<Pair<ProcessRecord, Boolean>> procs, int startIdx) {
+ final int uid = procs.get(startIdx).first.uid;
+ int endIdx = startIdx + 1;
+ while (endIdx < procs.size() && procs.get(endIdx).first.uid == uid) ++endIdx;
+ return procs.subList(startIdx, endIdx);
+ }
+
@GuardedBy({"mService", "mProcLock"})
boolean killPackageProcessesLSP(String packageName, int appId,
int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
@@ -2989,25 +3015,36 @@
}
}
- final int packageUID = UserHandle.getUid(userId, appId);
- final boolean doFreeze = appId >= Process.FIRST_APPLICATION_UID
- && appId <= Process.LAST_APPLICATION_UID;
- if (doFreeze) {
- freezeBinderAndPackageCgroup(procs, packageUID);
+ final boolean killingUserApp = appId >= Process.FIRST_APPLICATION_UID
+ && appId <= Process.LAST_APPLICATION_UID;
+
+ if (killingUserApp) {
+ procs.sort((o1, o2) -> Integer.compare(o1.first.uid, o2.first.uid));
}
- int N = procs.size();
- for (int i=0; i<N; i++) {
- final Pair<ProcessRecord, Boolean> proc = procs.get(i);
- removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second,
- reasonCode, subReason, reason, !doFreeze /* async */);
+ int idx = 0;
+ while (idx < procs.size()) {
+ final List<Pair<ProcessRecord, Boolean>> uidProcs = getUIDSublist(procs, idx);
+ final int packageUID = uidProcs.get(0).first.uid;
+
+ // Do not freeze for system apps or for dependencies of the targeted package, but
+ // make sure to freeze the targeted package for all users if called with USER_ALL.
+ final boolean doFreeze = killingUserApp && UserHandle.getAppId(packageUID) == appId;
+
+ if (doFreeze) freezeBinderAndPackageCgroup(uidProcs, packageUID);
+
+ for (Pair<ProcessRecord, Boolean> proc : uidProcs) {
+ removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second,
+ reasonCode, subReason, reason, !doFreeze /* async */);
+ }
+ killAppZygotesLocked(packageName, appId, userId, false /* force */);
+
+ if (doFreeze) unfreezePackageCgroup(packageUID);
+
+ idx += uidProcs.size();
}
- killAppZygotesLocked(packageName, appId, userId, false /* force */);
mService.updateOomAdjLocked(OOM_ADJ_REASON_PROCESS_END);
- if (doFreeze) {
- freezePackageCgroup(packageUID, false);
- }
- return N > 0;
+ return procs.size() > 0;
}
@GuardedBy("mService")
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 908827b..113e2fa 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1170,6 +1170,11 @@
}
}
+ public long getRss(int pid) {
+ long[] rss = Process.getRss(pid);
+ return (rss != null && rss.length > 0) ? rss[0] : 0;
+ }
+
@GuardedBy("mService")
void killLocked(String reason, @Reason int reasonCode, boolean noisy) {
killLocked(reason, reasonCode, ApplicationExitInfo.SUBREASON_UNKNOWN, noisy, true);
@@ -1213,7 +1218,7 @@
if (mPid > 0) {
mService.mProcessList.noteAppKill(this, reasonCode, subReason, description);
EventLog.writeEvent(EventLogTags.AM_KILL,
- userId, mPid, processName, mState.getSetAdj(), reason);
+ userId, mPid, processName, mState.getSetAdj(), reason, getRss(mPid));
Process.killProcessQuiet(mPid);
killProcessGroupIfNecessaryLocked(asyncKPG);
} else {
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index 7ff6d11..1420671 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -341,8 +341,10 @@
mHasAboveClient = false;
for (int i = mConnections.size() - 1; i >= 0; i--) {
ConnectionRecord cr = mConnections.valueAt(i);
- if (cr.binding.service.app.mServices != this
- && cr.hasFlag(Context.BIND_ABOVE_CLIENT)) {
+
+ final boolean isSameProcess = cr.binding.service.app != null
+ && cr.binding.service.app.mServices == this;
+ if (!isSameProcess && cr.hasFlag(Context.BIND_ABOVE_CLIENT)) {
mHasAboveClient = true;
break;
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index b9535d6..43ecec4 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1024,11 +1024,9 @@
private void initAudioHalBluetoothState() {
synchronized (mBluetoothAudioStateLock) {
mBluetoothScoOnApplied = false;
- AudioSystem.setParameters("BT_SCO=off");
mBluetoothA2dpSuspendedApplied = false;
- AudioSystem.setParameters("A2dpSuspended=false");
mBluetoothLeSuspendedApplied = false;
- AudioSystem.setParameters("LeAudioSuspended=false");
+ reapplyAudioHalBluetoothState();
}
}
@@ -1091,6 +1089,34 @@
}
}
+ @GuardedBy("mBluetoothAudioStateLock")
+ private void reapplyAudioHalBluetoothState() {
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "reapplyAudioHalBluetoothState() mBluetoothScoOnApplied: "
+ + mBluetoothScoOnApplied + ", mBluetoothA2dpSuspendedApplied: "
+ + mBluetoothA2dpSuspendedApplied + ", mBluetoothLeSuspendedApplied: "
+ + mBluetoothLeSuspendedApplied);
+ }
+ // Note: the order of parameters is important.
+ if (mBluetoothScoOnApplied) {
+ AudioSystem.setParameters("A2dpSuspended=true");
+ AudioSystem.setParameters("LeAudioSuspended=true");
+ AudioSystem.setParameters("BT_SCO=on");
+ } else {
+ AudioSystem.setParameters("BT_SCO=off");
+ if (mBluetoothA2dpSuspendedApplied) {
+ AudioSystem.setParameters("A2dpSuspended=true");
+ } else {
+ AudioSystem.setParameters("A2dpSuspended=false");
+ }
+ if (mBluetoothLeSuspendedApplied) {
+ AudioSystem.setParameters("LeAudioSuspended=true");
+ } else {
+ AudioSystem.setParameters("LeAudioSuspended=false");
+ }
+ }
+ }
+
/*package*/ void setBluetoothScoOn(boolean on, String eventSource) {
if (AudioService.DEBUG_COMM_RTE) {
Log.v(TAG, "setBluetoothScoOn: " + on + " " + eventSource);
@@ -1727,6 +1753,9 @@
initRoutingStrategyIds();
updateActiveCommunicationDevice();
mDeviceInventory.onRestoreDevices();
+ synchronized (mBluetoothAudioStateLock) {
+ reapplyAudioHalBluetoothState();
+ }
mBtHelper.onAudioServerDiedRestoreA2dp();
updateCommunicationRoute("MSG_RESTORE_DEVICES");
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index b555a52..e9acce6 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -7629,7 +7629,6 @@
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_BLE_SET);
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
- DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_HDMI);
}
/** only public for mocking/spying, do not call outside of AudioService */
@@ -12053,12 +12052,16 @@
public @Nullable AudioHalVersionInfo getHalVersion() {
for (AudioHalVersionInfo version : AudioHalVersionInfo.VERSIONS) {
try {
- // TODO: check AIDL service.
String versionStr = version.getMajorVersion() + "." + version.getMinorVersion();
- HwBinder.getService(
- String.format("android.hardware.audio@%s::IDevicesFactory", versionStr),
- "default");
- return version;
+ final String aidlStr = "android.hardware.audio.core.IModule/default";
+ final String hidlStr = String.format("android.hardware.audio@%s::IDevicesFactory",
+ versionStr);
+ if (null != ServiceManager.checkService(aidlStr)) {
+ return version;
+ } else {
+ HwBinder.getService(hidlStr, "default");
+ return version;
+ }
} catch (NoSuchElementException e) {
// Ignore, the specified HAL interface is not found.
} catch (RemoteException re) {
diff --git a/services/core/java/com/android/server/biometrics/OWNERS b/services/core/java/com/android/server/biometrics/OWNERS
index 1bf2aef..4703efb 100644
--- a/services/core/java/com/android/server/biometrics/OWNERS
+++ b/services/core/java/com/android/server/biometrics/OWNERS
@@ -2,7 +2,6 @@
graciecheng@google.com
ilyamaty@google.com
-jaggies@google.com
jbolinger@google.com
jeffpu@google.com
joshmccloskey@google.com
diff --git a/services/core/java/com/android/server/broadcastradio/OWNERS b/services/core/java/com/android/server/broadcastradio/OWNERS
index d2bdd64..51a85e4 100644
--- a/services/core/java/com/android/server/broadcastradio/OWNERS
+++ b/services/core/java/com/android/server/broadcastradio/OWNERS
@@ -1,3 +1,3 @@
xuweilin@google.com
oscarazu@google.com
-keunyoung@google.com
+ericjeong@google.com
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 74310b5..a895ac9 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -1344,7 +1344,11 @@
String defaultIme = Settings.Secure.getStringForUser(getContext().getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD, userId);
if (!TextUtils.isEmpty(defaultIme)) {
- final String imePkg = ComponentName.unflattenFromString(defaultIme).getPackageName();
+ final ComponentName imeComponent = ComponentName.unflattenFromString(defaultIme);
+ if (imeComponent == null) {
+ return false;
+ }
+ final String imePkg = imeComponent.getPackageName();
return imePkg.equals(packageName);
}
return false;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index c517058..b7ece2ea 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1299,7 +1299,7 @@
}
try {
- mNms.denyProtect(mOwnerUID);
+ mNetd.networkSetProtectDeny(mOwnerUID);
} catch (Exception e) {
Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e);
}
@@ -1309,7 +1309,7 @@
mOwnerUID = getAppUid(mContext, newPackage, mUserId);
mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage);
try {
- mNms.allowProtect(mOwnerUID);
+ mNetd.networkSetProtectAllow(mOwnerUID);
} catch (Exception e) {
Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e);
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 6a36fbe..87778a1 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -574,8 +574,8 @@
pw.println(" mCurrentLightSensorRate=" + mCurrentLightSensorRate);
pw.println(" mAmbientLux=" + mAmbientLux);
pw.println(" mAmbientLuxValid=" + mAmbientLuxValid);
- pw.println(" mPreThesholdLux=" + mPreThresholdLux);
- pw.println(" mPreThesholdBrightness=" + mPreThresholdBrightness);
+ pw.println(" mPreThresholdLux=" + mPreThresholdLux);
+ pw.println(" mPreThresholdBrightness=" + mPreThresholdBrightness);
pw.println(" mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold);
pw.println(" mAmbientDarkeningThreshold=" + mAmbientDarkeningThreshold);
pw.println(" mScreenBrighteningThreshold=" + mScreenBrighteningThreshold);
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 2464eb0..a454a36 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -1940,7 +1940,7 @@
final List<SdrHdrRatioPoint> points = sdrHdrRatioMap.getPoint();
final int size = points.size();
- if (size <= 0) {
+ if (size == 0) {
return null;
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index bc7e156..dde5120 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -4337,8 +4337,10 @@
if ((flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
final DisplayPowerControllerInterface displayPowerController =
mDisplayPowerControllers.get(id);
- ready &= displayPowerController.requestPowerState(request,
- waitForNegativeProximity);
+ if (displayPowerController != null) {
+ ready &= displayPowerController.requestPowerState(request,
+ waitForNegativeProximity);
+ }
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index da38a344..534197b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -717,7 +717,10 @@
// Programmed
int programedInfo = params[offset] & 0x0F;
if (isValidProgrammedInfo(programedInfo)) {
- if (programedInfo == 0x09 || programedInfo == 0x0B) {
+ offset = offset + 1;
+ // Duration Available (2 bytes)
+ if ((programedInfo == 0x09 || programedInfo == 0x0B)
+ && params.length - offset >= 2) {
durationAvailable = true;
} else {
return true;
@@ -727,16 +730,17 @@
// Non programmed
int nonProgramedErrorInfo = params[offset] & 0x0F;
if (isValidNotProgrammedErrorInfo(nonProgramedErrorInfo)) {
- if (nonProgramedErrorInfo == 0x0E) {
+ offset = offset + 1;
+ // Duration Available (2 bytes)
+ if (nonProgramedErrorInfo == 0x0E && params.length - offset >= 2) {
durationAvailable = true;
} else {
return true;
}
}
}
- offset = offset + 1;
// Duration Available (2 bytes)
- if (durationAvailable && params.length - offset >= 2) {
+ if (durationAvailable) {
return (isValidDurationHours(params[offset]) && isValidMinute(params[offset + 1]));
}
return false;
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 2f9149a..dea5f82f 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1336,6 +1336,11 @@
}
@Override // Binder call
+ public int getMousePointerSpeed() {
+ return mNative.getMousePointerSpeed();
+ }
+
+ @Override // Binder call
public void tryPointerSpeed(int speed) {
if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
"tryPointerSpeed()")) {
diff --git a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
index 08e5977..8e2484e 100644
--- a/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
+++ b/services/core/java/com/android/server/input/KeyboardMetricsCollector.java
@@ -369,15 +369,15 @@
if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
return;
}
- int vendorId = inputDevice.getVendorId();
- int productId = inputDevice.getProductId();
if (keyboardSystemEvent == null) {
Slog.w(TAG, "Invalid keyboard event logging, keycode = " + Arrays.toString(keyCodes)
+ ", modifier state = " + modifierState);
return;
}
FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED,
- vendorId, productId, keyboardSystemEvent.getIntValue(), keyCodes, modifierState);
+ inputDevice.getVendorId(), inputDevice.getProductId(),
+ keyboardSystemEvent.getIntValue(), keyCodes, modifierState,
+ inputDevice.getDeviceBus());
if (DEBUG) {
Slog.d(TAG, "Logging Keyboard system event: " + keyboardSystemEvent.mName);
@@ -402,7 +402,7 @@
// Push the atom to Statsd
FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_CONFIGURED,
event.isFirstConfiguration(), event.getVendorId(), event.getProductId(),
- proto.getBytes());
+ proto.getBytes(), event.getDeviceBus());
if (DEBUG) {
Slog.d(TAG, "Logging Keyboard configuration event: " + event);
@@ -467,6 +467,10 @@
return mInputDevice.getProductId();
}
+ public int getDeviceBus() {
+ return mInputDevice.getDeviceBus();
+ }
+
public boolean isFirstConfiguration() {
return mIsFirstConfiguration;
}
@@ -479,6 +483,7 @@
public String toString() {
return "InputDevice = {VendorId = " + Integer.toHexString(getVendorId())
+ ", ProductId = " + Integer.toHexString(getProductId())
+ + ", Device Bus = " + Integer.toHexString(getDeviceBus())
+ "}, isFirstConfiguration = " + mIsFirstConfiguration
+ ", LayoutConfigurations = " + mLayoutConfigurations;
}
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index 363bc94..79c042d 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -117,6 +117,8 @@
*/
boolean transferTouch(IBinder destChannelToken, int displayId);
+ int getMousePointerSpeed();
+
void setPointerSpeed(int speed);
void setPointerAcceleration(float acceleration);
@@ -343,6 +345,9 @@
public native boolean transferTouch(IBinder destChannelToken, int displayId);
@Override
+ public native int getMousePointerSpeed();
+
+ @Override
public native void setPointerSpeed(int speed);
@Override
diff --git a/services/core/java/com/android/server/inputmethod/OWNERS b/services/core/java/com/android/server/inputmethod/OWNERS
index aa638aa..e507c6b 100644
--- a/services/core/java/com/android/server/inputmethod/OWNERS
+++ b/services/core/java/com/android/server/inputmethod/OWNERS
@@ -6,5 +6,8 @@
fstern@google.com
cosminbaies@google.com
+# Automotive
+kanant@google.com
+
ogunwale@google.com #{LAST_RESORT_SUGGESTION}
jjaggi@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 115421d..bcbd36c 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -1321,7 +1321,9 @@
"setAutomotiveGnssSuspended only allowed on automotive devices");
}
- mGnssManagerService.setAutomotiveGnssSuspended(suspended);
+ if (mGnssManagerService != null) {
+ mGnssManagerService.setAutomotiveGnssSuspended(suspended);
+ }
}
@android.annotation.EnforcePermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS)
@@ -1336,7 +1338,10 @@
"isAutomotiveGnssSuspended only allowed on automotive devices");
}
- return mGnssManagerService.isAutomotiveGnssSuspended();
+ if (mGnssManagerService != null) {
+ return mGnssManagerService.isAutomotiveGnssSuspended();
+ }
+ return false;
}
@Override
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 0c2eee5..939423f 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -16,6 +16,7 @@
package com.android.server.locksettings;
+import static android.security.Flags.reportPrimaryAuthAttempts;
import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS;
@@ -139,6 +140,7 @@
import com.android.internal.widget.IWeakEscrowTokenRemovedListener;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockSettingsInternal;
+import com.android.internal.widget.LockSettingsStateListener;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.RebootEscrowListener;
import com.android.internal.widget.VerifyCredentialResponse;
@@ -180,6 +182,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -327,6 +330,9 @@
private HashMap<UserHandle, UserManager> mUserManagerCache = new HashMap<>();
+ private final CopyOnWriteArrayList<LockSettingsStateListener> mLockSettingsStateListeners =
+ new CopyOnWriteArrayList<>();
+
// This class manages life cycle events for encrypted users on File Based Encryption (FBE)
// devices. The most basic of these is to show/hide notifications about missing features until
// the user unlocks the account and credential-encrypted storage is available.
@@ -2118,11 +2124,10 @@
Slogf.d(TAG, "CE storage for user %d is already unlocked", userId);
return;
}
- final UserInfo userInfo = mUserManager.getUserInfo(userId);
final String userType = isUserSecure(userId) ? "secured" : "unsecured";
final byte[] secret = sp.deriveFileBasedEncryptionKey();
try {
- mStorageManager.unlockCeStorage(userId, userInfo.serialNumber, secret);
+ mStorageManager.unlockCeStorage(userId, 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);
@@ -2343,9 +2348,24 @@
requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
}
}
+ if (reportPrimaryAuthAttempts()) {
+ final boolean success =
+ response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK;
+ notifyLockSettingsStateListeners(success, userId);
+ }
return response;
}
+ private void notifyLockSettingsStateListeners(boolean success, int userId) {
+ for (LockSettingsStateListener listener : mLockSettingsStateListeners) {
+ if (success) {
+ listener.onAuthenticationSucceeded(userId);
+ } else {
+ listener.onAuthenticationFailed(userId);
+ }
+ }
+ }
+
@Override
public VerifyCredentialResponse verifyTiedProfileChallenge(LockscreenCredential credential,
int userId, @LockPatternUtils.VerifyFlag int flags) {
@@ -3663,6 +3683,18 @@
public void refreshStrongAuthTimeout(int userId) {
mStrongAuth.refreshStrongAuthTimeout(userId);
}
+
+ @Override
+ public void registerLockSettingsStateListener(@NonNull LockSettingsStateListener listener) {
+ Objects.requireNonNull(listener, "listener cannot be null");
+ mLockSettingsStateListeners.add(listener);
+ }
+
+ @Override
+ public void unregisterLockSettingsStateListener(
+ @NonNull LockSettingsStateListener listener) {
+ mLockSettingsStateListeners.remove(listener);
+ }
}
private class RebootEscrowCallbacks implements RebootEscrowManager.Callbacks {
diff --git a/services/core/java/com/android/server/locksettings/OWNERS b/services/core/java/com/android/server/locksettings/OWNERS
index 5d49863..48da270 100644
--- a/services/core/java/com/android/server/locksettings/OWNERS
+++ b/services/core/java/com/android/server/locksettings/OWNERS
@@ -1,4 +1,3 @@
# Bug component: 1333694
ebiggers@google.com
-jaggies@google.com
rubinxu@google.com
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index cc205d4..cc58f38 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -1541,8 +1541,14 @@
*/
public @NonNull AuthenticationResult unlockTokenBasedProtector(
IGateKeeperService gatekeeper, long protectorId, byte[] token, int userId) {
- SyntheticPasswordBlob blob = SyntheticPasswordBlob.fromBytes(loadState(SP_BLOB_NAME,
- protectorId, userId));
+ byte[] data = loadState(SP_BLOB_NAME, protectorId, userId);
+ if (data == null) {
+ AuthenticationResult result = new AuthenticationResult();
+ result.gkResponse = VerifyCredentialResponse.ERROR;
+ Slogf.w(TAG, "spblob not found for protector %016x, user %d", protectorId, userId);
+ return result;
+ }
+ SyntheticPasswordBlob blob = SyntheticPasswordBlob.fromBytes(data);
return unlockTokenBasedProtectorInternal(gatekeeper, protectorId, blob.mProtectorType,
token, userId);
}
diff --git a/services/core/java/com/android/server/net/Android.bp b/services/core/java/com/android/server/net/Android.bp
new file mode 100644
index 0000000..71d8e6b
--- /dev/null
+++ b/services/core/java/com/android/server/net/Android.bp
@@ -0,0 +1,10 @@
+aconfig_declarations {
+ name: "net_flags",
+ package: "com.android.server.net",
+ srcs: ["*.aconfig"],
+}
+
+java_aconfig_library {
+ name: "net_flags_lib",
+ aconfig_declarations: "net_flags",
+}
diff --git a/services/core/java/com/android/server/net/NetworkManagementService.java b/services/core/java/com/android/server/net/NetworkManagementService.java
index 681d1a0..d25f529 100644
--- a/services/core/java/com/android/server/net/NetworkManagementService.java
+++ b/services/core/java/com/android/server/net/NetworkManagementService.java
@@ -17,6 +17,7 @@
package com.android.server.net;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
@@ -27,6 +28,7 @@
import static android.net.INetd.FIREWALL_DENYLIST;
import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_BACKGROUND;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
@@ -187,6 +189,13 @@
*/
@GuardedBy("mRulesLock")
private final SparseIntArray mUidFirewallLowPowerStandbyRules = new SparseIntArray();
+
+ /**
+ * Contains the per-UID firewall rules that are used when Background chain is enabled.
+ */
+ @GuardedBy("mRulesLock")
+ private final SparseIntArray mUidFirewallBackgroundRules = new SparseIntArray();
+
/** Set of states for the child firewall chains. True if the chain is active. */
@GuardedBy("mRulesLock")
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -449,13 +458,15 @@
syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
syncFirewallChainLocked(FIREWALL_CHAIN_RESTRICTED, "restricted ");
syncFirewallChainLocked(FIREWALL_CHAIN_LOW_POWER_STANDBY, "low power standby ");
+ syncFirewallChainLocked(FIREWALL_CHAIN_BACKGROUND, FIREWALL_CHAIN_NAME_BACKGROUND);
final int[] chains = {
FIREWALL_CHAIN_STANDBY,
FIREWALL_CHAIN_DOZABLE,
FIREWALL_CHAIN_POWERSAVE,
FIREWALL_CHAIN_RESTRICTED,
- FIREWALL_CHAIN_LOW_POWER_STANDBY
+ FIREWALL_CHAIN_LOW_POWER_STANDBY,
+ FIREWALL_CHAIN_BACKGROUND,
};
for (int chain : chains) {
@@ -1206,6 +1217,8 @@
return FIREWALL_CHAIN_NAME_RESTRICTED;
case FIREWALL_CHAIN_LOW_POWER_STANDBY:
return FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
+ case FIREWALL_CHAIN_BACKGROUND:
+ return FIREWALL_CHAIN_NAME_BACKGROUND;
default:
throw new IllegalArgumentException("Bad child chain: " + chain);
}
@@ -1223,6 +1236,8 @@
return FIREWALL_ALLOWLIST;
case FIREWALL_CHAIN_LOW_POWER_STANDBY:
return FIREWALL_ALLOWLIST;
+ case FIREWALL_CHAIN_BACKGROUND:
+ return FIREWALL_ALLOWLIST;
default:
return isFirewallEnabled() ? FIREWALL_ALLOWLIST : FIREWALL_DENYLIST;
}
@@ -1343,6 +1358,8 @@
return mUidFirewallRestrictedRules;
case FIREWALL_CHAIN_LOW_POWER_STANDBY:
return mUidFirewallLowPowerStandbyRules;
+ case FIREWALL_CHAIN_BACKGROUND:
+ return mUidFirewallBackgroundRules;
case FIREWALL_CHAIN_NONE:
return mUidFirewallRules;
default:
@@ -1395,6 +1412,10 @@
pw.println(getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY));
dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY,
mUidFirewallLowPowerStandbyRules);
+
+ pw.print("UID firewall background chain enabled: ");
+ pw.println(getFirewallChainState(FIREWALL_CHAIN_BACKGROUND));
+ dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_BACKGROUND, mUidFirewallBackgroundRules);
}
pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
@@ -1494,6 +1515,11 @@
if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of low power standby");
return true;
}
+ if (getFirewallChainState(FIREWALL_CHAIN_BACKGROUND)
+ && mUidFirewallBackgroundRules.get(uid) != FIREWALL_RULE_ALLOW) {
+ if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because it is in background");
+ return true;
+ }
if (mUidRejectOnMetered.get(uid)) {
if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
+ " in the background");
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 85731651..8e2d778 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -16,6 +16,7 @@
package com.android.server.net;
import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
@@ -24,6 +25,7 @@
import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_BACKGROUND;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
@@ -389,6 +391,8 @@
return FIREWALL_CHAIN_NAME_RESTRICTED;
case FIREWALL_CHAIN_LOW_POWER_STANDBY:
return FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
+ case FIREWALL_CHAIN_BACKGROUND:
+ return FIREWALL_CHAIN_NAME_BACKGROUND;
default:
return String.valueOf(chain);
}
@@ -413,7 +417,7 @@
private static final Date sDate = new Date();
public LogBuffer(int capacity) {
- super(Data.class, capacity);
+ super(Data::new, Data[]::new, capacity);
}
public void uidStateChanged(int uid, int procState, long procStateSeq,
@@ -689,11 +693,8 @@
/**
* Container class for all networkpolicy events data.
- *
- * Note: This class needs to be public for RingBuffer class to be able to create
- * new instances of this.
*/
- public static final class Data {
+ private static final class Data {
public int type;
public long timeStamp;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 52734a4..44c4b57 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -26,6 +26,8 @@
import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.ActivityManager.isProcStateConsideredInteraction;
import static android.app.ActivityManager.printCapabilitiesSummary;
@@ -47,6 +49,7 @@
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_MASK;
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
+import static android.net.ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND;
import static android.net.ConnectivityManager.BLOCKED_REASON_APP_STANDBY;
import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE;
@@ -54,6 +57,7 @@
import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.net.ConnectivityManager.BLOCKED_REASON_RESTRICTED_MODE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
@@ -77,13 +81,16 @@
import static android.net.NetworkPolicyManager.ALLOWED_REASON_FOREGROUND;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_NOT_IN_BACKGROUND;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_ALLOWLIST;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP;
+import static android.net.NetworkPolicyManager.BACKGROUND_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
+import static android.net.NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
@@ -94,8 +101,10 @@
import static android.net.NetworkPolicyManager.RULE_REJECT_RESTRICTED_MODE;
import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED;
+import static android.net.NetworkPolicyManager.TOP_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.allowedReasonsToString;
import static android.net.NetworkPolicyManager.blockedReasonsToString;
+import static android.net.NetworkPolicyManager.isProcStateAllowedNetworkWhileBackground;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileInLowPowerStandby;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
@@ -201,12 +210,12 @@
import android.os.MessageQueue.IdleHandler;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
+import android.os.PowerExemptionManager;
import android.os.PowerExemptionManager.ReasonCode;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
-import android.os.PowerWhitelistManager;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -242,6 +251,7 @@
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.util.SparseSetArray;
+import android.util.TimeUtils;
import android.util.Xml;
import com.android.internal.R;
@@ -457,7 +467,14 @@
*/
private static final int MSG_UIDS_BLOCKED_REASONS_CHANGED = 23;
- private static final int UID_MSG_STATE_CHANGED = 100;
+ /**
+ * Message to update background restriction rules for uids that should lose network access
+ * due to being in the background.
+ */
+ private static final int MSG_PROCESS_BACKGROUND_TRANSITIONING_UIDS = 24;
+
+ @VisibleForTesting
+ static final int UID_MSG_STATE_CHANGED = 100;
private static final int UID_MSG_GONE = 101;
private static final String PROP_SUB_PLAN_OWNER = "persist.sys.sub_plan_owner";
@@ -475,7 +492,7 @@
private ConnectivityManager mConnManager;
private PowerManagerInternal mPowerManagerInternal;
- private PowerWhitelistManager mPowerWhitelistManager;
+ private PowerExemptionManager mPowerExemptionManager;
@NonNull
private final Dependencies mDeps;
@@ -490,6 +507,12 @@
// Denotes the status of restrict background read from disk.
private boolean mLoadedRestrictBackground;
+ /**
+ * Whether or not network for apps in proc-states greater than
+ * {@link NetworkPolicyManager#BACKGROUND_THRESHOLD_STATE} is always blocked.
+ */
+ private boolean mBackgroundNetworkRestricted;
+
// See main javadoc for instructions on how to use these locks.
final Object mUidRulesFirstLock = new Object();
final Object mNetworkPoliciesSecondLock = new Object();
@@ -514,6 +537,15 @@
private volatile boolean mNetworkManagerReady;
+ /**
+ * Delay after which a uid going into a process state greater than or equal to
+ * {@link NetworkPolicyManager#BACKGROUND_THRESHOLD_STATE} will lose network access.
+ * The delay is meant to prevent churn due to quick process-state changes.
+ * Note that there is no delay while granting network access.
+ */
+ @VisibleForTesting
+ long mBackgroundRestrictionDelayMs = TimeUnit.SECONDS.toMillis(5);
+
/** Defined network policies. */
@GuardedBy("mNetworkPoliciesSecondLock")
final ArrayMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = new ArrayMap<>();
@@ -545,6 +577,8 @@
@GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
@GuardedBy("mUidRulesFirstLock")
+ final SparseIntArray mUidFirewallBackgroundRules = new SparseIntArray();
+ @GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidFirewallRestrictedModeRules = new SparseIntArray();
@GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidFirewallLowPowerStandbyModeRules = new SparseIntArray();
@@ -624,6 +658,14 @@
@GuardedBy("mUidRulesFirstLock")
private final SparseArray<UidBlockedState> mTmpUidBlockedState = new SparseArray<>();
+ /**
+ * Stores a map of uids to the time their transition to background is considered complete. They
+ * will lose network access after this time. This is used to prevent churn in rules due to quick
+ * process-state transitions.
+ */
+ @GuardedBy("mUidRulesFirstLock")
+ private final SparseLongArray mBackgroundTransitioningUids = new SparseLongArray();
+
/** Map from network ID to last observed meteredness state */
@GuardedBy("mNetworkPoliciesSecondLock")
private final SparseBooleanArray mNetworkMetered = new SparseBooleanArray();
@@ -684,7 +726,7 @@
* Map of uid -> UidStateCallbackInfo objects holding the data received from
* {@link IUidObserver#onUidStateChanged(int, int, long, int)} callbacks. In order to avoid
* creating a new object for every callback received, we hold onto the object created for each
- * uid and reuse it.
+ * uid and reuse it until the uid stays alive.
*
* Note that the lock used for accessing this object should not be used for anything else and we
* should not be acquiring new locks or doing any heavy work while this lock is held since this
@@ -757,6 +799,13 @@
Clock.systemUTC());
}
+ @VisibleForTesting
+ UidState getUidStateForTest(int uid) {
+ synchronized (mUidRulesFirstLock) {
+ return mUidState.get(uid);
+ }
+ }
+
static class Dependencies {
final Context mContext;
final NetworkStatsManager mNetworkStatsManager;
@@ -823,7 +872,7 @@
mContext = Objects.requireNonNull(context, "missing context");
mActivityManager = Objects.requireNonNull(activityManager, "missing activityManager");
mNetworkManager = Objects.requireNonNull(networkManagement, "missing networkManagement");
- mPowerWhitelistManager = mContext.getSystemService(PowerWhitelistManager.class);
+ mPowerExemptionManager = mContext.getSystemService(PowerExemptionManager.class);
mClock = Objects.requireNonNull(clock, "missing Clock");
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
@@ -859,15 +908,15 @@
@GuardedBy("mUidRulesFirstLock")
private void updatePowerSaveAllowlistUL() {
- int[] whitelist = mPowerWhitelistManager.getWhitelistedAppIds(/* includingIdle */ false);
+ int[] allowlist = mPowerExemptionManager.getAllowListedAppIds(/* includingIdle */ false);
mPowerSaveWhitelistExceptIdleAppIds.clear();
- for (int uid : whitelist) {
+ for (int uid : allowlist) {
mPowerSaveWhitelistExceptIdleAppIds.put(uid, true);
}
- whitelist = mPowerWhitelistManager.getWhitelistedAppIds(/* includingIdle */ true);
+ allowlist = mPowerExemptionManager.getAllowListedAppIds(/* includingIdle */ true);
mPowerSaveWhitelistAppIds.clear();
- for (int uid : whitelist) {
+ for (int uid : allowlist) {
mPowerSaveWhitelistAppIds.put(uid, true);
}
}
@@ -1017,6 +1066,14 @@
writePolicyAL();
}
+ // The flag is boot-stable.
+ mBackgroundNetworkRestricted = Flags.networkBlockedForTopSleepingAndAbove();
+ if (mBackgroundNetworkRestricted) {
+ // Firewall rules and UidBlockedState will get updated in
+ // updateRulesForGlobalChangeAL below.
+ enableFirewallChainUL(FIREWALL_CHAIN_BACKGROUND, true);
+ }
+
setRestrictBackgroundUL(mLoadedRestrictBackground, "init_service");
updateRulesForGlobalChangeAL(false);
updateNotificationsNL();
@@ -1027,17 +1084,20 @@
final int changes = ActivityManager.UID_OBSERVER_PROCSTATE
| ActivityManager.UID_OBSERVER_GONE
| ActivityManager.UID_OBSERVER_CAPABILITY;
+
+ final int cutpoint = mBackgroundNetworkRestricted ? PROCESS_STATE_UNKNOWN
+ : NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE;
mActivityManagerInternal.registerNetworkPolicyUidObserver(mUidObserver, changes,
- NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE, "android");
+ cutpoint, "android");
mNetworkManager.registerObserver(mAlertObserver);
} catch (RemoteException e) {
// ignored; both services live in system_server
}
// listen for changes to power save allowlist
- final IntentFilter whitelistFilter = new IntentFilter(
+ final IntentFilter allowlistFilter = new IntentFilter(
PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
- mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler);
+ mContext.registerReceiver(mPowerSaveAllowlistReceiver, allowlistFilter, null, mHandler);
// watch for network interfaces to be claimed
final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
@@ -1135,6 +1195,51 @@
}
final private IUidObserver mUidObserver = new UidObserver() {
+
+ /**
+ * Returns whether the uid state change information is relevant for the service. If the
+ * state information does not lead to any change in the network rules, it can safely be
+ * ignored.
+ */
+ @GuardedBy("mUidStateCallbackInfos")
+ private boolean isUidStateChangeRelevant(UidStateCallbackInfo previousInfo,
+ int newProcState, long newProcStateSeq, int newCapability) {
+ if (previousInfo.procStateSeq == -1) {
+ // No previous record. Always process the first state change callback.
+ return true;
+ }
+ if (newProcStateSeq <= previousInfo.procStateSeq) {
+ // Stale callback. Ignore.
+ return false;
+ }
+ final int previousProcState = previousInfo.procState;
+ if (mBackgroundNetworkRestricted && (previousProcState >= BACKGROUND_THRESHOLD_STATE)
+ != (newProcState >= BACKGROUND_THRESHOLD_STATE)) {
+ // Proc-state change crossed BACKGROUND_THRESHOLD_STATE: Network rules for the
+ // BACKGROUND chain may change.
+ return true;
+ }
+ if ((previousProcState <= TOP_THRESHOLD_STATE)
+ != (newProcState <= TOP_THRESHOLD_STATE)) {
+ // Proc-state change crossed TOP_THRESHOLD_STATE: Network rules for the
+ // LOW_POWER_STANDBY chain may change.
+ return true;
+ }
+ if ((previousProcState <= FOREGROUND_THRESHOLD_STATE)
+ != (newProcState <= FOREGROUND_THRESHOLD_STATE)) {
+ // Proc-state change crossed FOREGROUND_THRESHOLD_STATE: Network rules for many
+ // different chains may change.
+ return true;
+ }
+ final int networkCapabilities = PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
+ | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
+ if ((previousInfo.capability & networkCapabilities)
+ != (newCapability & networkCapabilities)) {
+ return true;
+ }
+ return false;
+ }
+
@Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
@ProcessCapability int capability) {
synchronized (mUidStateCallbackInfos) {
@@ -1143,18 +1248,22 @@
callbackInfo = new UidStateCallbackInfo();
mUidStateCallbackInfos.put(uid, callbackInfo);
}
- if (callbackInfo.procStateSeq == -1 || procStateSeq > callbackInfo.procStateSeq) {
+ if (isUidStateChangeRelevant(callbackInfo, procState, procStateSeq, capability)) {
callbackInfo.update(uid, procState, procStateSeq, capability);
- }
- if (!callbackInfo.isPending) {
- mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED, callbackInfo)
- .sendToTarget();
- callbackInfo.isPending = true;
+ if (!callbackInfo.isPending) {
+ mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED, callbackInfo)
+ .sendToTarget();
+ callbackInfo.isPending = true;
+ }
}
}
}
@Override public void onUidGone(int uid, boolean disabled) {
+ synchronized (mUidStateCallbackInfos) {
+ mUidStateCallbackInfos.remove(uid);
+ }
+ // TODO: b/327058756 - Remove any pending UID_MSG_STATE_CHANGED on the handler.
mUidEventHandler.obtainMessage(UID_MSG_GONE, uid, 0).sendToTarget();
}
};
@@ -1188,12 +1297,15 @@
}
}
- final private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() {
+ private final BroadcastReceiver mPowerSaveAllowlistReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
synchronized (mUidRulesFirstLock) {
updatePowerSaveAllowlistUL();
+ if (mBackgroundNetworkRestricted) {
+ updateRulesForBackgroundChainUL();
+ }
updateRulesForRestrictPowerUL();
updateRulesForAppIdleUL();
}
@@ -3901,6 +4013,11 @@
}
fout.println();
+ fout.println("Flags:");
+ fout.println("Network blocked for TOP_SLEEPING and above: "
+ + mBackgroundNetworkRestricted);
+
+ fout.println();
fout.println("mRestrictBackgroundLowPowerMode: " + mRestrictBackgroundLowPowerMode);
fout.println("mRestrictBackgroundBeforeBsm: " + mRestrictBackgroundBeforeBsm);
fout.println("mLoadedRestrictBackground: " + mLoadedRestrictBackground);
@@ -4042,6 +4159,22 @@
fout.decreaseIndent();
}
+ size = mBackgroundTransitioningUids.size();
+ if (size > 0) {
+ final long nowUptime = SystemClock.uptimeMillis();
+ fout.println("Uids transitioning to background:");
+ fout.increaseIndent();
+ for (int i = 0; i < size; i++) {
+ fout.print("UID=");
+ fout.print(mBackgroundTransitioningUids.keyAt(i));
+ fout.print(", ");
+ TimeUtils.formatDuration(mBackgroundTransitioningUids.valueAt(i), nowUptime,
+ fout);
+ fout.println();
+ }
+ fout.decreaseIndent();
+ }
+
final SparseBooleanArray knownUids = new SparseBooleanArray();
collectKeys(mUidState, knownUids);
synchronized (mUidBlockedState) {
@@ -4163,6 +4296,12 @@
return isProcStateAllowedWhileInLowPowerStandby(uidState);
}
+ @GuardedBy("mUidRulesFirstLock")
+ private boolean isUidExemptFromBackgroundRestrictions(int uid) {
+ return mBackgroundTransitioningUids.indexOfKey(uid) >= 0
+ || isProcStateAllowedNetworkWhileBackground(mUidState.get(uid));
+ }
+
/**
* Process state of UID changed; if needed, will trigger
* {@link #updateRulesForDataUsageRestrictionsUL(int)} and
@@ -4188,6 +4327,8 @@
// state changed, push updated rules
mUidState.put(uid, newUidState);
updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, newUidState);
+
+ boolean updatePowerRestrictionRules = false;
boolean allowedWhileIdleOrPowerSaveModeChanged =
isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
!= isProcStateAllowedWhileIdleOrPowerSaveMode(newUidState);
@@ -4199,19 +4340,44 @@
if (mRestrictPower) {
updateRuleForRestrictPowerUL(uid);
}
- updateRulesForPowerRestrictionsUL(uid, procState);
+ updatePowerRestrictionRules = true;
+ }
+ if (mBackgroundNetworkRestricted) {
+ final boolean wasAllowed = isProcStateAllowedNetworkWhileBackground(
+ oldUidState);
+ final boolean isAllowed = isProcStateAllowedNetworkWhileBackground(newUidState);
+ if (!wasAllowed && isAllowed) {
+ mBackgroundTransitioningUids.delete(uid);
+ updateRuleForBackgroundUL(uid);
+ updatePowerRestrictionRules = true;
+ } else if (wasAllowed && !isAllowed) {
+ final long completionTimeMs = SystemClock.uptimeMillis()
+ + mBackgroundRestrictionDelayMs;
+ if (mBackgroundTransitioningUids.indexOfKey(uid) < 0) {
+ // This is just a defensive check in case the upstream code ever makes
+ // multiple calls for the same process state change.
+ mBackgroundTransitioningUids.put(uid, completionTimeMs);
+ }
+ if (!mHandler.hasMessages(MSG_PROCESS_BACKGROUND_TRANSITIONING_UIDS)) {
+ // Many uids may be in this "transitioning" state at the same time, so
+ // using one message at a time to avoid congestion in the MessageQueue.
+ mHandler.sendEmptyMessageAtTime(
+ MSG_PROCESS_BACKGROUND_TRANSITIONING_UIDS, completionTimeMs);
+ }
+ }
}
if (mLowPowerStandbyActive) {
boolean allowedInLpsChanged =
isProcStateAllowedWhileInLowPowerStandby(oldUidState)
!= isProcStateAllowedWhileInLowPowerStandby(newUidState);
if (allowedInLpsChanged) {
- if (!allowedWhileIdleOrPowerSaveModeChanged) {
- updateRulesForPowerRestrictionsUL(uid, procState);
- }
updateRuleForLowPowerStandbyUL(uid);
+ updatePowerRestrictionRules = true;
}
}
+ if (updatePowerRestrictionRules) {
+ updateRulesForPowerRestrictionsUL(uid, procState);
+ }
return true;
}
} finally {
@@ -4234,6 +4400,12 @@
if (mRestrictPower) {
updateRuleForRestrictPowerUL(uid);
}
+ if (mBackgroundNetworkRestricted) {
+ // Uid is no longer running, there is no point in any grace period of network
+ // access during transitions to lower importance proc-states.
+ mBackgroundTransitioningUids.delete(uid);
+ updateRuleForBackgroundUL(uid);
+ }
updateRulesForPowerRestrictionsUL(uid);
if (mLowPowerStandbyActive) {
updateRuleForLowPowerStandbyUL(uid);
@@ -4441,11 +4613,41 @@
}
}
+ /**
+ * Updates the rules for apps allowlisted to use network while in the background.
+ */
+ @GuardedBy("mUidRulesFirstLock")
+ private void updateRulesForBackgroundChainUL() {
+ Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForBackgroundChainUL");
+ try {
+ final SparseIntArray uidRules = mUidFirewallBackgroundRules;
+ uidRules.clear();
+
+ final List<UserInfo> users = mUserManager.getUsers();
+ for (int ui = users.size() - 1; ui >= 0; ui--) {
+ final UserInfo user = users.get(ui);
+ updateRulesForAllowlistedAppIds(uidRules, mPowerSaveTempWhitelistAppIds, user.id);
+ updateRulesForAllowlistedAppIds(uidRules, mPowerSaveWhitelistAppIds, user.id);
+ updateRulesForAllowlistedAppIds(uidRules, mPowerSaveWhitelistExceptIdleAppIds,
+ user.id);
+ }
+ for (int i = mUidState.size() - 1; i >= 0; i--) {
+ if (mBackgroundTransitioningUids.indexOfKey(mUidState.keyAt(i)) >= 0
+ || isProcStateAllowedNetworkWhileBackground(mUidState.valueAt(i))) {
+ uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);
+ }
+ }
+ setUidFirewallRulesUL(FIREWALL_CHAIN_BACKGROUND, uidRules);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_NETWORK);
+ }
+ }
+
private void updateRulesForAllowlistedAppIds(final SparseIntArray uidRules,
- final SparseBooleanArray whitelistedAppIds, int userId) {
- for (int i = whitelistedAppIds.size() - 1; i >= 0; --i) {
- if (whitelistedAppIds.valueAt(i)) {
- final int appId = whitelistedAppIds.keyAt(i);
+ final SparseBooleanArray allowlistedAppIds, int userId) {
+ for (int i = allowlistedAppIds.size() - 1; i >= 0; --i) {
+ if (allowlistedAppIds.valueAt(i)) {
+ final int appId = allowlistedAppIds.keyAt(i);
final int uid = UserHandle.getUid(userId, appId);
uidRules.put(uid, FIREWALL_RULE_ALLOW);
}
@@ -4504,12 +4706,12 @@
@GuardedBy("mUidRulesFirstLock")
private boolean isAllowlistedFromPowerSaveUL(int uid, boolean deviceIdleMode) {
final int appId = UserHandle.getAppId(uid);
- boolean isWhitelisted = mPowerSaveTempWhitelistAppIds.get(appId)
+ boolean allowlisted = mPowerSaveTempWhitelistAppIds.get(appId)
|| mPowerSaveWhitelistAppIds.get(appId);
if (!deviceIdleMode) {
- isWhitelisted = isWhitelisted || isAllowlistedFromPowerSaveExceptIdleUL(uid);
+ allowlisted = allowlisted || isAllowlistedFromPowerSaveExceptIdleUL(uid);
}
- return isWhitelisted;
+ return allowlisted;
}
/**
@@ -4598,6 +4800,38 @@
}
/**
+ * Update firewall rule for a single uid whenever there are any interesting changes in the uid.
+ * Currently, it is called when:
+ * - The uid is added to or removed from power allowlists
+ * - The uid undergoes a process-state change
+ * - A package belonging to this uid is added
+ * - The uid is evicted from memory
+ */
+ @GuardedBy("mUidRulesFirstLock")
+ void updateRuleForBackgroundUL(int uid) {
+ if (!isUidValidForAllowlistRulesUL(uid)) {
+ return;
+ }
+
+ Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRuleForBackgroundUL: " + uid);
+ try {
+ // The uid should be absent from mUidState and mBackgroundTransitioningUids if it is
+ // not running when this method is called. Then, the firewall state will depend on the
+ // allowlist alone. This is the desired behavior.
+ if (isAllowlistedFromPowerSaveUL(uid, false)
+ || isUidExemptFromBackgroundRestrictions(uid)) {
+ setUidFirewallRuleUL(FIREWALL_CHAIN_BACKGROUND, uid, FIREWALL_RULE_ALLOW);
+ if (LOGD) Log.d(TAG, "updateRuleForBackgroundUL ALLOW " + uid);
+ } else {
+ setUidFirewallRuleUL(FIREWALL_CHAIN_BACKGROUND, uid, FIREWALL_RULE_DEFAULT);
+ if (LOGD) Log.d(TAG, "updateRuleForBackgroundUL " + uid + " to DEFAULT");
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
+ }
+ }
+
+ /**
* Toggle the firewall standby chain and inform listeners if the uid rules have effectively
* changed.
*/
@@ -4644,6 +4878,9 @@
"updateRulesForGlobalChangeAL: " + (restrictedNetworksChanged ? "R" : "-"));
}
try {
+ if (mBackgroundNetworkRestricted) {
+ updateRulesForBackgroundChainUL();
+ }
updateRulesForAppIdleUL();
updateRulesForRestrictPowerUL();
updateRulesForRestrictBackgroundUL();
@@ -4803,6 +5040,9 @@
updateRuleForAppIdleUL(uid, PROCESS_STATE_UNKNOWN);
updateRuleForDeviceIdleUL(uid);
updateRuleForRestrictPowerUL(uid);
+ if (mBackgroundNetworkRestricted) {
+ updateRuleForBackgroundUL(uid);
+ }
// Update internal rules.
updateRulesForPowerRestrictionsUL(uid);
}
@@ -4940,6 +5180,8 @@
mUidFirewallStandbyRules.delete(uid);
mUidFirewallDozableRules.delete(uid);
mUidFirewallPowerSaveRules.delete(uid);
+ mUidFirewallBackgroundRules.delete(uid);
+ mBackgroundTransitioningUids.delete(uid);
mPowerSaveWhitelistExceptIdleAppIds.delete(uid);
mPowerSaveWhitelistAppIds.delete(uid);
mPowerSaveTempWhitelistAppIds.delete(uid);
@@ -4973,6 +5215,9 @@
updateRuleForDeviceIdleUL(uid);
updateRuleForAppIdleUL(uid, PROCESS_STATE_UNKNOWN);
updateRuleForRestrictPowerUL(uid);
+ if (mBackgroundNetworkRestricted) {
+ updateRuleForBackgroundUL(uid);
+ }
// If the uid has the necessary permissions, then it should be added to the restricted mode
// firewall allowlist.
@@ -5157,7 +5402,6 @@
* Similar to above but ignores idle state if app standby is currently disabled by parole.
*
* @param uid the uid of the app to update rules for
- * @param oldUidRules the current rules for the uid, in order to determine if there's a change
* @param isUidIdle whether uid is idle or not
*/
@GuardedBy("mUidRulesFirstLock")
@@ -5203,6 +5447,7 @@
newBlockedReasons |= (mLowPowerStandbyActive ? BLOCKED_REASON_LOW_POWER_STANDBY : 0);
newBlockedReasons |= (isUidIdle ? BLOCKED_REASON_APP_STANDBY : 0);
newBlockedReasons |= (uidBlockedState.blockedReasons & BLOCKED_REASON_RESTRICTED_MODE);
+ newBlockedReasons |= mBackgroundNetworkRestricted ? BLOCKED_REASON_APP_BACKGROUND : 0;
newAllowedReasons |= (isSystem(uid) ? ALLOWED_REASON_SYSTEM : 0);
newAllowedReasons |= (isForeground ? ALLOWED_REASON_FOREGROUND : 0);
@@ -5215,6 +5460,9 @@
& ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS);
newAllowedReasons |= (isAllowlistedFromLowPowerStandbyUL(uid))
? ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST : 0;
+ newAllowedReasons |= (mBackgroundNetworkRestricted
+ && isUidExemptFromBackgroundRestrictions(uid))
+ ? ALLOWED_REASON_NOT_IN_BACKGROUND : 0;
uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
& BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
@@ -5236,7 +5484,7 @@
oldEffectiveBlockedReasons = previousUidBlockedState.effectiveBlockedReasons;
newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
- uidRules = oldEffectiveBlockedReasons == newEffectiveBlockedReasons
+ uidRules = (oldEffectiveBlockedReasons == newEffectiveBlockedReasons)
? RULE_NONE
: uidBlockedState.deriveUidRules();
}
@@ -5429,6 +5677,28 @@
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
return true;
}
+ case MSG_PROCESS_BACKGROUND_TRANSITIONING_UIDS: {
+ final long now = SystemClock.uptimeMillis();
+ long nextCheckTime = Long.MAX_VALUE;
+ synchronized (mUidRulesFirstLock) {
+ for (int i = mBackgroundTransitioningUids.size() - 1; i >= 0; i--) {
+ final long completionTimeMs = mBackgroundTransitioningUids.valueAt(i);
+ if (completionTimeMs > now) {
+ nextCheckTime = Math.min(nextCheckTime, completionTimeMs);
+ continue;
+ }
+ final int uid = mBackgroundTransitioningUids.keyAt(i);
+ mBackgroundTransitioningUids.removeAt(i);
+ updateRuleForBackgroundUL(uid);
+ updateRulesForPowerRestrictionsUL(uid, false);
+ }
+ }
+ if (nextCheckTime < Long.MAX_VALUE) {
+ mHandler.sendEmptyMessageAtTime(MSG_PROCESS_BACKGROUND_TRANSITIONING_UIDS,
+ nextCheckTime);
+ }
+ return true;
+ }
case MSG_POLICIES_CHANGED: {
final int uid = msg.arg1;
final int policy = msg.arg2;
@@ -5637,7 +5907,7 @@
void handleUidGone(int uid) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "onUidGone");
try {
- boolean updated;
+ final boolean updated;
synchronized (mUidRulesFirstLock) {
updated = removeUidStateUL(uid);
}
@@ -5840,6 +6110,8 @@
mUidFirewallRestrictedModeRules.put(uid, rule);
} else if (chain == FIREWALL_CHAIN_LOW_POWER_STANDBY) {
mUidFirewallLowPowerStandbyModeRules.put(uid, rule);
+ } else if (chain == FIREWALL_CHAIN_BACKGROUND) {
+ mUidFirewallBackgroundRules.put(uid, rule);
}
try {
@@ -5896,6 +6168,8 @@
FIREWALL_RULE_DEFAULT);
mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, uid,
FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_BACKGROUND, uid,
+ FIREWALL_RULE_DEFAULT);
mNetworkManager.setUidOnMeteredNetworkAllowlist(uid, false);
mLogger.meteredAllowlistChanged(uid, false);
mNetworkManager.setUidOnMeteredNetworkDenylist(uid, false);
@@ -6420,10 +6694,12 @@
effectiveBlockedReasons &= ~BLOCKED_REASON_BATTERY_SAVER;
effectiveBlockedReasons &= ~BLOCKED_REASON_DOZE;
effectiveBlockedReasons &= ~BLOCKED_REASON_APP_STANDBY;
+ effectiveBlockedReasons &= ~BLOCKED_REASON_APP_BACKGROUND;
}
if ((allowedReasons & ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST) != 0) {
effectiveBlockedReasons &= ~BLOCKED_REASON_BATTERY_SAVER;
effectiveBlockedReasons &= ~BLOCKED_REASON_APP_STANDBY;
+ effectiveBlockedReasons &= ~BLOCKED_REASON_APP_BACKGROUND;
}
if ((allowedReasons & ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS) != 0) {
effectiveBlockedReasons &= ~BLOCKED_REASON_RESTRICTED_MODE;
@@ -6434,19 +6710,24 @@
if ((allowedReasons & ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST) != 0) {
effectiveBlockedReasons &= ~BLOCKED_REASON_LOW_POWER_STANDBY;
}
+ if ((allowedReasons & ALLOWED_REASON_NOT_IN_BACKGROUND) != 0) {
+ effectiveBlockedReasons &= ~BLOCKED_REASON_APP_BACKGROUND;
+ }
return effectiveBlockedReasons;
}
static int getAllowedReasonsForProcState(int procState) {
- if (procState > NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE) {
- return ALLOWED_REASON_NONE;
- } else if (procState <= NetworkPolicyManager.TOP_THRESHOLD_STATE) {
+ if (procState <= NetworkPolicyManager.TOP_THRESHOLD_STATE) {
return ALLOWED_REASON_TOP | ALLOWED_REASON_FOREGROUND
- | ALLOWED_METERED_REASON_FOREGROUND;
- } else {
- return ALLOWED_REASON_FOREGROUND | ALLOWED_METERED_REASON_FOREGROUND;
+ | ALLOWED_METERED_REASON_FOREGROUND | ALLOWED_REASON_NOT_IN_BACKGROUND;
+ } else if (procState <= NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE) {
+ return ALLOWED_REASON_FOREGROUND | ALLOWED_METERED_REASON_FOREGROUND
+ | ALLOWED_REASON_NOT_IN_BACKGROUND;
+ } else if (procState < NetworkPolicyManager.BACKGROUND_THRESHOLD_STATE) {
+ return ALLOWED_REASON_NOT_IN_BACKGROUND;
}
+ return ALLOWED_REASON_NONE;
}
@Override
@@ -6471,6 +6752,7 @@
BLOCKED_REASON_APP_STANDBY,
BLOCKED_REASON_RESTRICTED_MODE,
BLOCKED_REASON_LOW_POWER_STANDBY,
+ BLOCKED_REASON_APP_BACKGROUND,
BLOCKED_METERED_REASON_DATA_SAVER,
BLOCKED_METERED_REASON_USER_RESTRICTED,
BLOCKED_METERED_REASON_ADMIN_DISABLED,
@@ -6484,6 +6766,7 @@
ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST,
ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS,
ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST,
+ ALLOWED_REASON_NOT_IN_BACKGROUND,
ALLOWED_METERED_REASON_USER_EXEMPTED,
ALLOWED_METERED_REASON_SYSTEM,
ALLOWED_METERED_REASON_FOREGROUND,
@@ -6503,6 +6786,8 @@
return "RESTRICTED_MODE";
case BLOCKED_REASON_LOW_POWER_STANDBY:
return "LOW_POWER_STANDBY";
+ case BLOCKED_REASON_APP_BACKGROUND:
+ return "APP_BACKGROUND";
case BLOCKED_METERED_REASON_DATA_SAVER:
return "DATA_SAVER";
case BLOCKED_METERED_REASON_USER_RESTRICTED:
@@ -6533,6 +6818,8 @@
return "RESTRICTED_MODE_PERMISSIONS";
case ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST:
return "LOW_POWER_STANDBY_ALLOWLIST";
+ case ALLOWED_REASON_NOT_IN_BACKGROUND:
+ return "NOT_IN_BACKGROUND";
case ALLOWED_METERED_REASON_USER_EXEMPTED:
return "METERED_USER_EXEMPTED";
case ALLOWED_METERED_REASON_SYSTEM:
@@ -6600,7 +6887,8 @@
int powerBlockedReasons = BLOCKED_REASON_APP_STANDBY
| BLOCKED_REASON_DOZE
| BLOCKED_REASON_BATTERY_SAVER
- | BLOCKED_REASON_LOW_POWER_STANDBY;
+ | BLOCKED_REASON_LOW_POWER_STANDBY
+ | BLOCKED_REASON_APP_BACKGROUND;
if ((effectiveBlockedReasons & powerBlockedReasons) != 0) {
uidRule |= RULE_REJECT_ALL;
} else if ((blockedReasons & powerBlockedReasons) != 0) {
diff --git a/services/core/java/com/android/server/net/flags.aconfig b/services/core/java/com/android/server/net/flags.aconfig
new file mode 100644
index 0000000..419665a
--- /dev/null
+++ b/services/core/java/com/android/server/net/flags.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.server.net"
+
+flag {
+ name: "network_blocked_for_top_sleeping_and_above"
+ namespace: "backstage_power"
+ description: "Block network access for apps in a low importance background state"
+ bug: "304347838"
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e633ba6..db04093 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -8237,19 +8237,26 @@
}
}
+ private PendingIntent getNotificationTimeoutPendingIntent(NotificationRecord record,
+ int flags) {
+ flags |= PendingIntent.FLAG_IMMUTABLE;
+ return PendingIntent.getBroadcast(getContext(),
+ REQUEST_CODE_TIMEOUT,
+ new Intent(ACTION_NOTIFICATION_TIMEOUT)
+ .setPackage(PackageManagerService.PLATFORM_PACKAGE_NAME)
+ .setData(new Uri.Builder().scheme(SCHEME_TIMEOUT)
+ .appendPath(record.getKey()).build())
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ .putExtra(EXTRA_KEY, record.getKey()),
+ flags);
+ }
+
@VisibleForTesting
@GuardedBy("mNotificationLock")
void scheduleTimeoutLocked(NotificationRecord record) {
if (record.getNotification().getTimeoutAfter() > 0) {
- final PendingIntent pi = PendingIntent.getBroadcast(getContext(),
- REQUEST_CODE_TIMEOUT,
- new Intent(ACTION_NOTIFICATION_TIMEOUT)
- .setPackage(PackageManagerService.PLATFORM_PACKAGE_NAME)
- .setData(new Uri.Builder().scheme(SCHEME_TIMEOUT)
- .appendPath(record.getKey()).build())
- .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
- .putExtra(EXTRA_KEY, record.getKey()),
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+ final PendingIntent pi = getNotificationTimeoutPendingIntent(
+ record, PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + record.getNotification().getTimeoutAfter(), pi);
}
@@ -8257,6 +8264,16 @@
@VisibleForTesting
@GuardedBy("mNotificationLock")
+ void cancelScheduledTimeoutLocked(NotificationRecord record) {
+ final PendingIntent pi = getNotificationTimeoutPendingIntent(
+ record, PendingIntent.FLAG_CANCEL_CURRENT);
+ if (pi != null) {
+ mAlarmManager.cancel(pi);
+ }
+ }
+
+ @VisibleForTesting
+ @GuardedBy("mNotificationLock")
/**
* Determine whether this notification should attempt to make noise, vibrate, or flash the LED
* @return buzzBeepBlink - bitfield (buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)
@@ -9249,21 +9266,7 @@
int rank, int count, boolean wasPosted, String listenerName,
@ElapsedRealtimeLong long cancellationElapsedTimeMs) {
final String canceledKey = r.getKey();
-
- // Get pending intent used to create alarm, use FLAG_NO_CREATE if PendingIntent
- // does not already exist, then null will be returned.
- final PendingIntent pi = PendingIntent.getBroadcast(getContext(),
- REQUEST_CODE_TIMEOUT,
- new Intent(ACTION_NOTIFICATION_TIMEOUT)
- .setData(new Uri.Builder().scheme(SCHEME_TIMEOUT)
- .appendPath(r.getKey()).build())
- .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
- PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE);
-
- // Cancel alarm corresponding to pi.
- if (pi != null) {
- mAlarmManager.cancel(pi);
- }
+ cancelScheduledTimeoutLocked(r);
// Record caller.
recordCallerLocked(r);
diff --git a/services/core/java/com/android/server/ondeviceintelligence/OWNERS b/services/core/java/com/android/server/ondeviceintelligence/OWNERS
new file mode 100644
index 0000000..09774f7
--- /dev/null
+++ b/services/core/java/com/android/server/ondeviceintelligence/OWNERS
@@ -0,0 +1 @@
+file:/core/java/android/app/ondeviceintelligence/OWNERS
diff --git a/services/core/java/com/android/server/os/Android.bp b/services/core/java/com/android/server/os/Android.bp
new file mode 100644
index 0000000..565dc3b
--- /dev/null
+++ b/services/core/java/com/android/server/os/Android.bp
@@ -0,0 +1,12 @@
+aconfig_declarations {
+ name: "core_os_flags",
+ package: "com.android.server.os",
+ srcs: [
+ "*.aconfig",
+ ],
+}
+
+java_aconfig_library {
+ name: "core_os_flags_lib",
+ aconfig_declarations: "core_os_flags",
+}
diff --git a/services/core/java/com/android/server/os/core_os_flags.aconfig b/services/core/java/com/android/server/os/core_os_flags.aconfig
new file mode 100644
index 0000000..cbc0d54
--- /dev/null
+++ b/services/core/java/com/android/server/os/core_os_flags.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.server.os"
+
+flag {
+ name: "proto_tombstone"
+ namespace: "proto_tombstone_ns"
+ description: "Use proto tombstones as source of truth for adding to dropbox"
+ bug: "323857385"
+}
diff --git a/services/core/java/com/android/server/pm/BACKGROUND_INSTALL_OWNERS b/services/core/java/com/android/server/pm/BACKGROUND_INSTALL_OWNERS
new file mode 100644
index 0000000..baa41a5
--- /dev/null
+++ b/services/core/java/com/android/server/pm/BACKGROUND_INSTALL_OWNERS
@@ -0,0 +1,2 @@
+georgechan@google.com
+wenhaowang@google.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 988a32f..8e31e76 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -4331,7 +4331,7 @@
+ "; old: " + pkgSetting.getPathString() + " @ "
+ pkgSetting.getVersionCode()
+ "; new: " + parsedPackage.getPath() + " @ "
- + parsedPackage.getPath());
+ + parsedPackage.getLongVersionCode());
}
}
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 84324f2..c8bc56c 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -51,3 +51,5 @@
per-file ShortcutService.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
per-file ShortcutUser.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
+# background install control service
+per-file BackgroundInstall* = file:BACKGROUND_INSTALL_OWNERS
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 178719f..57b89e3 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -42,6 +42,7 @@
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.pm.ApplicationInfo;
+import android.content.pm.Flags;
import android.content.pm.IPackageInstaller;
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.IPackageInstallerSession;
@@ -745,6 +746,40 @@
params.installFlags &= ~PackageManager.INSTALL_DISABLE_VERIFICATION;
}
+ if (Flags.rollbackLifetime()) {
+ if (params.rollbackLifetimeMillis > 0) {
+ if ((params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
+ throw new IllegalArgumentException(
+ "Can't set rollbackLifetimeMillis when rollback is not enabled");
+ }
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException(
+ "Setting rollback lifetime requires the MANAGE_ROLLBACKS permission");
+ }
+ } else if (params.rollbackLifetimeMillis < 0) {
+ throw new IllegalArgumentException("rollbackLifetimeMillis can't be negative.");
+ }
+ }
+
+ if (Flags.recoverabilityDetection()) {
+ if (params.rollbackImpactLevel == PackageManager.ROLLBACK_USER_IMPACT_HIGH
+ || params.rollbackImpactLevel
+ == PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL) {
+ if ((params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
+ throw new IllegalArgumentException(
+ "Can't set rollbackImpactLevel when rollback is not enabled");
+ }
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException(
+ "Setting rollbackImpactLevel requires the MANAGE_ROLLBACKS permission");
+ }
+ } else if (params.rollbackImpactLevel < 0) {
+ throw new IllegalArgumentException("rollbackImpactLevel can't be negative.");
+ }
+ }
+
boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0;
if (isApex) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGE_UPDATES)
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 2372fd3..fbd6526 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1206,6 +1206,8 @@
info.whitelistedRestrictedPermissions = params.whitelistedRestrictedPermissions;
info.autoRevokePermissionsMode = params.autoRevokePermissionsMode;
info.installFlags = params.installFlags;
+ info.rollbackLifetimeMillis = params.rollbackLifetimeMillis;
+ info.rollbackImpactLevel = params.rollbackImpactLevel;
info.isMultiPackage = params.isMultiPackage;
info.isStaged = params.isStaged;
info.rollbackDataPolicy = params.rollbackDataPolicy;
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index 8961923..d9d7087 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -193,7 +193,7 @@
}
try {
- sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, flags);
+ sm.prepareUserStorage(volumeUuid, user.id, flags);
synchronized (mPm.mInstallLock) {
appDataHelper.reconcileAppsDataLI(volumeUuid, user.id, flags,
true /* migrateAppData */);
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
index 8adb566..1d41401 100644
--- a/services/core/java/com/android/server/pm/UserDataPreparer.java
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -92,7 +92,7 @@
volumeUuid, userId, flags, isNewUser);
try {
// Prepare CE and/or DE storage.
- storage.prepareUserStorage(volumeUuid, userId, userSerial, flags);
+ storage.prepareUserStorage(volumeUuid, userId, flags);
// Ensure that the data directories of a removed user with the same ID are not being
// reused. New users must get fresh data directories, to avoid leaking data.
@@ -141,7 +141,7 @@
// If internal storage of the system user fails to prepare on first boot, then
// things are *really* broken, so we might as well reboot to recovery right away.
try {
- Log.wtf(TAG, "prepareUserData failed for user " + userId, e);
+ Log.e(TAG, "prepareUserData failed for user " + userId, e);
if (isNewUser && userId == UserHandle.USER_SYSTEM && volumeUuid == null) {
RecoverySystem.rebootPromptAndWipeUserData(mContext,
"failed to prepare internal storage for system user");
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 062d797..8fcc921 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -4920,7 +4920,7 @@
t.traceBegin("createUserStorageKeys");
final StorageManager storage = mContext.getSystemService(StorageManager.class);
- storage.createUserStorageKeys(userId, userInfo.serialNumber, userInfo.isEphemeral());
+ storage.createUserStorageKeys(userId, userInfo.isEphemeral());
t.traceEnd();
// Only prepare DE storage here. CE storage will be prepared later, when the user is
diff --git a/services/core/java/com/android/server/pm/dex/PackageDynamicCodeLoading.java b/services/core/java/com/android/server/pm/dex/PackageDynamicCodeLoading.java
index cc26c9b..9159851 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDynamicCodeLoading.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDynamicCodeLoading.java
@@ -538,9 +538,10 @@
} else {
if (fileInfo.mUserId != userId) {
// This should be impossible: private app files are always user-specific and
- // can't be accessed from different users.
- throw new IllegalArgumentException("Cannot change userId for '" + path
- + "' from " + fileInfo.mUserId + " to " + userId);
+ // can't be accessed from different users. But it does very occasionally happen
+ // (b/323665257). Ignore such cases - we shouldn't record data from a different
+ // user.
+ return false;
}
// Changing file type (i.e. loading the same file in different ways is possible if
// unlikely. We allow it but ignore it.
diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index c81d6d7..1440a1e 100644
--- a/services/core/java/com/android/server/pm/permission/Permission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -146,6 +146,10 @@
return mPermissionInfo.packageName;
}
+ public boolean isReconciled() {
+ return mReconciled;
+ }
+
public int getType() {
return mType;
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 2144654..b92ae23 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -3379,7 +3379,7 @@
final PermissionAllowlist permissionAllowlist =
SystemConfig.getInstance().getPermissionAllowlist();
final String packageName = packageState.getPackageName();
- if (packageState.isVendor()) {
+ if (packageState.isVendor() || packageState.isOdm()) {
return permissionAllowlist.getVendorPrivilegedAppAllowlistState(packageName,
permissionName);
} else if (packageState.isProduct()) {
@@ -3474,7 +3474,7 @@
// the permission's protectionLevel does not have the extra 'vendorPrivileged'
// flag.
if (allowed && isPrivilegedPermission && !bp.isVendorPrivileged()
- && pkgSetting.isVendor()) {
+ && (pkgSetting.isVendor() || pkgSetting.isOdm())) {
Slog.w(TAG, "Permission " + permissionName
+ " cannot be granted to privileged vendor apk " + pkg.getPackageName()
+ " because it isn't a 'vendorPrivileged' permission.");
@@ -4137,6 +4137,10 @@
// being uninstalled,
continue;
}
+ // Don't remove config permissions and lose their GIDs.
+ if (bp.getType() == Permission.TYPE_CONFIG && !bp.isReconciled()) {
+ continue;
+ }
// The target package is the source of the current permission
// Set to changed for either install or uninstall
changed = true;
diff --git a/services/core/java/com/android/server/pm/verify/domain/OWNERS b/services/core/java/com/android/server/pm/verify/domain/OWNERS
index c669112..b451fe4 100644
--- a/services/core/java/com/android/server/pm/verify/domain/OWNERS
+++ b/services/core/java/com/android/server/pm/verify/domain/OWNERS
@@ -1,5 +1,4 @@
# Bug component: 36137
+include /PACKAGE_MANAGER_OWNERS
-chiuwinson@google.com
-patb@google.com
-toddke@google.com
\ No newline at end of file
+wloh@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index 9d5173a..69b7034 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -524,6 +524,7 @@
if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
synchronized (sRequestLock) {
if (!setupOrClearBcb(true, command)) {
+ Slog.e(TAG, "rebootRecoveryWithCommand failed to setup BCB");
return;
}
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java
index 141d4dc..9ee9b14 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java
@@ -48,6 +48,8 @@
return isLskfCaptured();
case "reboot-and-apply":
return rebootAndApply();
+ case "wipe":
+ return wipe();
default:
return handleDefaultCommands(cmd);
}
@@ -58,6 +60,18 @@
}
}
+ private int wipe() throws RemoteException {
+ PrintWriter pw = getOutPrintWriter();
+ String newFsType = getNextArg();
+ String command = "--wipe_data";
+ if (newFsType != null && !newFsType.isEmpty()) {
+ command += "\n--reformat_data=" + newFsType;
+ }
+ pw.println("Rebooting into recovery with " + command.replaceAll("\n", " "));
+ mService.rebootRecoveryWithCommand(command);
+ return 0;
+ }
+
private int requestLskf() throws RemoteException {
String packageName = getNextArgRequired();
boolean success = mService.requestLskf(packageName, null);
@@ -104,5 +118,6 @@
pw.println(" clear-lskf");
pw.println(" is-lskf-captured <package_name>");
pw.println(" reboot-and-apply <package_name> <reason>");
+ pw.println(" wipe <new filesystem type ext4/f2fs>");
}
}
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 85d93f4..a580bb7 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -174,6 +174,11 @@
@Nullable private final String mInstallerPackageName;
/**
+ * Time after which rollback expires.
+ */
+ private long mRollbackLifetimeMillis = 0;
+
+ /**
* Session ids for all packages in the install. For multi-package sessions, this is the list
* of child session ids. For normal sessions, this list is a single element with the normal
* session id.
@@ -210,7 +215,8 @@
/* packages */ new ArrayList<>(),
/* isStaged */ isStaged,
/* causePackages */ new ArrayList<>(),
- /* committedSessionId */ -1);
+ /* committedSessionId */ -1,
+ /* rollbackImpactLevel */ PackageManager.ROLLBACK_USER_IMPACT_LOW);
mUserId = userId;
mInstallerPackageName = installerPackageName;
mBackupDir = backupDir;
@@ -286,6 +292,24 @@
}
/**
+ * Sets rollback lifetime in milliseconds, for purposes of expiring rollback data.
+ */
+ @WorkerThread
+ void setRollbackLifetimeMillis(long lifetimeMillis) {
+ assertInWorkerThread();
+ mRollbackLifetimeMillis = lifetimeMillis;
+ }
+
+ /**
+ * Returns rollback lifetime in milliseconds, for purposes of expiring rollback data.
+ */
+ @WorkerThread
+ long getRollbackLifetimeMillis() {
+ assertInWorkerThread();
+ return mRollbackLifetimeMillis;
+ }
+
+ /**
* Returns the session ID associated with this rollback, or {@code -1} if unknown.
*/
@AnyThread
@@ -371,7 +395,8 @@
*/
@WorkerThread
boolean enableForPackage(String packageName, long newVersion, long installedVersion,
- boolean isApex, String sourceDir, String[] splitSourceDirs, int rollbackDataPolicy) {
+ boolean isApex, String sourceDir, String[] splitSourceDirs, int rollbackDataPolicy,
+ @PackageManager.RollbackImpactLevel int rollbackImpactLevel) {
assertInWorkerThread();
try {
RollbackStore.backupPackageCodePath(this, packageName, sourceDir);
@@ -392,6 +417,10 @@
isApex, false /* isApkInApex */, new ArrayList<>(), rollbackDataPolicy);
info.getPackages().add(packageRollbackInfo);
+
+ if (info.getRollbackImpactLevel() < rollbackImpactLevel) {
+ info.setRollbackImpactLevel(rollbackImpactLevel);
+ }
return true;
}
@@ -930,6 +959,7 @@
ipw.println("-state: " + getStateAsString());
ipw.println("-stateDescription: " + mStateDescription);
ipw.println("-timestamp: " + getTimestamp());
+ ipw.println("-rollbackLifetimeMillis: " + getRollbackLifetimeMillis());
ipw.println("-isStaged: " + isStaged());
ipw.println("-originalSessionId: " + getOriginalSessionId());
ipw.println("-packages:");
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 720c773..e5cdf45 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -28,6 +28,7 @@
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
+import android.content.pm.Flags;
import android.content.pm.ModuleInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
@@ -702,6 +703,15 @@
// Schedules future expiration as appropriate.
@WorkerThread
private void runExpiration() {
+ if (Flags.rollbackLifetime()) {
+ runExpirationCustomRollbackLifetime();
+ } else {
+ runExpirationDefaultRollbackLifetime();
+ }
+ }
+
+ @WorkerThread
+ private void runExpirationDefaultRollbackLifetime() {
getHandler().removeCallbacks(mRunExpiration);
assertInWorkerThread();
Instant now = Instant.now();
@@ -729,6 +739,44 @@
}
}
+ @WorkerThread
+ private void runExpirationCustomRollbackLifetime() {
+ getHandler().removeCallbacks(mRunExpiration);
+ assertInWorkerThread();
+ Instant now = Instant.now();
+ long minDelay = 0;
+ Iterator<Rollback> iter = mRollbacks.iterator();
+ while (iter.hasNext()) {
+ Rollback rollback = iter.next();
+ if (!rollback.isAvailable() && !rollback.isCommitted()) {
+ continue;
+ }
+ long rollbackLifetimeMillis = rollback.getRollbackLifetimeMillis();
+ if (rollbackLifetimeMillis <= 0) {
+ rollbackLifetimeMillis = mRollbackLifetimeDurationInMillis;
+ }
+
+ Instant rollbackExpiryTimestamp = rollback.getTimestamp()
+ .plusMillis(rollbackLifetimeMillis);
+ if (!now.isBefore(rollbackExpiryTimestamp)) {
+ Slog.i(TAG, "runExpiration id=" + rollback.info.getRollbackId());
+ iter.remove();
+ deleteRollback(rollback, "Expired by timeout");
+ continue;
+ }
+
+ long delay = now.until(
+ rollbackExpiryTimestamp, ChronoUnit.MILLIS);
+ if (minDelay == 0 || delay < minDelay) {
+ minDelay = delay;
+ }
+ }
+
+ if (minDelay != 0) {
+ getHandler().postDelayed(mRunExpiration, minDelay);
+ }
+ }
+
@AnyThread
private Handler getHandler() {
return mHandler;
@@ -906,7 +954,7 @@
ApplicationInfo appInfo = pkgInfo.applicationInfo;
return rollback.enableForPackage(packageName, newPackage.getVersionCode(),
pkgInfo.getLongVersionCode(), isApex, appInfo.sourceDir,
- appInfo.splitSourceDirs, rollbackDataPolicy);
+ appInfo.splitSourceDirs, rollbackDataPolicy, session.rollbackImpactLevel);
}
@ExtThread
@@ -1164,13 +1212,20 @@
rollback.makeAvailable();
mPackageHealthObserver.notifyRollbackAvailable(rollback.info);
- // TODO(zezeozue): Provide API to explicitly start observing instead
- // of doing this for all rollbacks. If we do this for all rollbacks,
- // should document in PackageInstaller.SessionParams#setEnableRollback
- // After enabling and committing any rollback, observe packages and
- // prepare to rollback if packages crashes too frequently.
- mPackageHealthObserver.startObservingHealth(rollback.getPackageNames(),
- mRollbackLifetimeDurationInMillis);
+ if (Flags.recoverabilityDetection()) {
+ if (rollback.info.getRollbackImpactLevel() == PackageManager.ROLLBACK_USER_IMPACT_LOW) {
+ // TODO(zezeozue): Provide API to explicitly start observing instead
+ // of doing this for all rollbacks. If we do this for all rollbacks,
+ // should document in PackageInstaller.SessionParams#setEnableRollback
+ // After enabling and committing any rollback, observe packages and
+ // prepare to rollback if packages crashes too frequently.
+ mPackageHealthObserver.startObservingHealth(rollback.getPackageNames(),
+ mRollbackLifetimeDurationInMillis);
+ }
+ } else {
+ mPackageHealthObserver.startObservingHealth(rollback.getPackageNames(),
+ mRollbackLifetimeDurationInMillis);
+ }
runExpiration();
}
@@ -1231,8 +1286,8 @@
ipw.println();
}
- PackageWatchdog.getInstance(mContext).dump(ipw);
});
+ PackageWatchdog.getInstance(mContext).dump(ipw);
}
@AnyThread
@@ -1277,6 +1332,7 @@
}
final Rollback rollback;
+
if (parentSession.isStaged()) {
rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId, userId,
installerPackageName, packageSessionIds, getExtensionVersions());
@@ -1285,6 +1341,10 @@
installerPackageName, packageSessionIds, getExtensionVersions());
}
+ if (Flags.rollbackLifetime()) {
+ rollback.setRollbackLifetimeMillis(parentSession.rollbackLifetimeMillis);
+ }
+
mRollbacks.add(rollback);
return rollback;
}
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 8068c6f..14539d5 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -19,6 +19,7 @@
import static com.android.server.rollback.Rollback.rollbackStateFromString;
import android.annotation.NonNull;
+import android.content.pm.Flags;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
@@ -192,16 +193,27 @@
json.put("isStaged", rollback.isStaged());
json.put("causePackages", versionedPackagesToJson(rollback.getCausePackages()));
json.put("committedSessionId", rollback.getCommittedSessionId());
+ if (Flags.recoverabilityDetection()) {
+ json.put("rollbackImpactLevel", rollback.getRollbackImpactLevel());
+ }
return json;
}
private static RollbackInfo rollbackInfoFromJson(JSONObject json) throws JSONException {
- return new RollbackInfo(
+ RollbackInfo rollbackInfo = new RollbackInfo(
json.getInt("rollbackId"),
packageRollbackInfosFromJson(json.getJSONArray("packages")),
json.getBoolean("isStaged"),
versionedPackagesFromJson(json.getJSONArray("causePackages")),
json.getInt("committedSessionId"));
+
+ if (Flags.recoverabilityDetection()) {
+ // to make it backward compatible.
+ rollbackInfo.setRollbackImpactLevel(json.optInt("rollbackImpactLevel",
+ PackageManager.ROLLBACK_USER_IMPACT_LOW));
+ }
+
+ return rollbackInfo;
}
/**
@@ -312,6 +324,9 @@
JSONObject dataJson = new JSONObject();
dataJson.put("info", rollbackInfoToJson(rollback.info));
dataJson.put("timestamp", rollback.getTimestamp().toString());
+ if (Flags.rollbackLifetime()) {
+ dataJson.put("rollbackLifetimeMillis", rollback.getRollbackLifetimeMillis());
+ }
dataJson.put("originalSessionId", rollback.getOriginalSessionId());
dataJson.put("state", rollback.getStateAsString());
dataJson.put("stateDescription", rollback.getStateDescription());
@@ -375,7 +390,7 @@
@VisibleForTesting
static Rollback rollbackFromJson(JSONObject dataJson, File backupDir)
throws JSONException, ParseException {
- return new Rollback(
+ Rollback rollback = new Rollback(
rollbackInfoFromJson(dataJson.getJSONObject("info")),
backupDir,
Instant.parse(dataJson.getString("timestamp")),
@@ -388,6 +403,10 @@
dataJson.optInt("userId", UserHandle.SYSTEM.getIdentifier()),
dataJson.optString("installerPackageName", ""),
extensionVersionsFromJson(dataJson.optJSONArray("extensionVersions")));
+ if (Flags.rollbackLifetime()) {
+ rollback.setRollbackLifetimeMillis(dataJson.optLong("rollbackLifetimeMillis"));
+ }
+ return rollback;
}
private static JSONObject toJson(VersionedPackage pkg) throws JSONException {
diff --git a/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java b/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java
index d5bc912..b69ccb3 100644
--- a/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java
+++ b/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-
package com.android.server.security;
import android.content.Context;
@@ -23,6 +22,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Binder;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.security.keystore.IKeyAttestationApplicationIdProvider;
import android.security.keystore.KeyAttestationApplicationId;
@@ -57,7 +57,10 @@
try {
String[] packageNames = mPackageManager.getPackagesForUid(uid);
if (packageNames == null) {
- throw new RemoteException("No packages for uid");
+ throw new ServiceSpecificException(
+ IKeyAttestationApplicationIdProvider
+ .ERROR_GET_ATTESTATION_APPLICATION_ID_FAILED,
+ "No package for uid: " + uid);
}
int userId = UserHandle.getUserId(uid);
keyAttestationPackageInfos = new KeyAttestationPackageInfo[packageNames.length];
diff --git a/services/core/java/com/android/server/selinux/OWNERS b/services/core/java/com/android/server/selinux/OWNERS
new file mode 100644
index 0000000..6ca4da2
--- /dev/null
+++ b/services/core/java/com/android/server/selinux/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 1117393
+
+sandrom@google.com
diff --git a/services/core/java/com/android/server/trust/TEST_MAPPING b/services/core/java/com/android/server/trust/TEST_MAPPING
index fa46acd..0de7c28 100644
--- a/services/core/java/com/android/server/trust/TEST_MAPPING
+++ b/services/core/java/com/android/server/trust/TEST_MAPPING
@@ -12,6 +12,19 @@
]
}
],
+ "postsubmit": [
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.trust"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
"trust-tablet": [
{
"name": "TrustTests",
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 1ebad9b..ba8a76c 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -44,6 +44,9 @@
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
+import android.hardware.biometrics.SensorProperties;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -75,6 +78,7 @@
import android.view.WindowManagerGlobal;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.DumpUtils;
@@ -156,6 +160,8 @@
private final LockPatternUtils mLockPatternUtils;
private final UserManager mUserManager;
private final ActivityManager mActivityManager;
+ private FingerprintManager mFingerprintManager;
+ private FaceManager mFaceManager;
private VirtualDeviceManagerInternal mVirtualDeviceManager;
private enum TrustState {
@@ -293,6 +299,8 @@
mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
mReceiver.register(mContext);
mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
+ mFingerprintManager = mContext.getSystemService(FingerprintManager.class);
+ mFaceManager = mContext.getSystemService(FaceManager.class);
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
mTrustAgentsCanRun = true;
refreshAgentList(UserHandle.USER_ALL);
@@ -894,7 +902,19 @@
private void notifyKeystoreOfDeviceLockState(int userId, boolean isLocked) {
if (isLocked) {
- Authorization.onDeviceLocked(userId, getBiometricSids(userId));
+ if (android.security.Flags.fixUnlockedDeviceRequiredKeysV2()) {
+ // A profile with unified challenge is unlockable not by its own biometrics and
+ // trust agents, but rather by those of the parent user. Therefore, when protecting
+ // the profile's UnlockedDeviceRequired keys, we must use the parent's list of
+ // biometric SIDs and weak unlock methods, not the profile's.
+ int authUserId = mLockPatternUtils.isProfileWithUnifiedChallenge(userId)
+ ? resolveProfileParent(userId) : userId;
+
+ Authorization.onDeviceLocked(userId, getBiometricSids(authUserId),
+ isWeakUnlockMethodEnabled(authUserId));
+ } else {
+ Authorization.onDeviceLocked(userId, getBiometricSids(userId), false);
+ }
} else {
// Notify Keystore that the device is now unlocked for the user. Note that for unlocks
// with LSKF, this is redundant with the call from LockSettingsService which provides
@@ -1444,6 +1464,56 @@
return biometricManager.getAuthenticatorIds(userId);
}
+ // Returns whether the device can become unlocked for the specified user via one of that user's
+ // non-strong biometrics or trust agents. This assumes that the device is currently locked, or
+ // is becoming locked, for the user.
+ private boolean isWeakUnlockMethodEnabled(int userId) {
+
+ // Check whether the system currently allows the use of non-strong biometrics for the user,
+ // *and* the user actually has a non-strong biometric enrolled.
+ //
+ // The biometrics framework ostensibly supports multiple sensors per modality. However,
+ // that feature is unused and untested. So, we simply consider one sensor per modality.
+ //
+ // Also, currently we just consider fingerprint and face, matching Keyguard. If Keyguard
+ // starts supporting other biometric modalities, this will need to be updated.
+ if (mStrongAuthTracker.isBiometricAllowedForUser(/* isStrongBiometric= */ false, userId)) {
+ DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
+ int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userId);
+
+ if (mFingerprintManager != null
+ && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) == 0
+ && mFingerprintManager.hasEnrolledTemplates(userId)
+ && isWeakOrConvenienceSensor(
+ mFingerprintManager.getSensorProperties().get(0))) {
+ Slog.i(TAG, "User is unlockable by non-strong fingerprint auth");
+ return true;
+ }
+
+ if (mFaceManager != null
+ && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FACE) == 0
+ && mFaceManager.hasEnrolledTemplates(userId)
+ && isWeakOrConvenienceSensor(mFaceManager.getSensorProperties().get(0))) {
+ Slog.i(TAG, "User is unlockable by non-strong face auth");
+ return true;
+ }
+ }
+
+ // Check whether it's possible for the device to be actively unlocked by a trust agent.
+ if (getUserTrustStateInner(userId) == TrustState.TRUSTABLE
+ || (isAutomotive() && isTrustUsuallyManagedInternal(userId))) {
+ Slog.i(TAG, "User is unlockable by trust agent");
+ return true;
+ }
+
+ return false;
+ }
+
+ private static boolean isWeakOrConvenienceSensor(SensorProperties sensor) {
+ return sensor.getSensorStrength() == SensorProperties.STRENGTH_WEAK
+ || sensor.getSensorStrength() == SensorProperties.STRENGTH_CONVENIENCE;
+ }
+
// User lifecycle
@Override
@@ -1807,6 +1877,11 @@
}
};
+ @VisibleForTesting
+ void waitForIdle() {
+ mHandler.runWithScissors(() -> {}, 0);
+ }
+
private boolean isTrustUsuallyManagedInternal(int userId) {
synchronized (mTrustUsuallyManagedForUser) {
int i = mTrustUsuallyManagedForUser.indexOfKey(userId);
@@ -1927,7 +2002,8 @@
};
}
- private final PackageMonitor mPackageMonitor = new PackageMonitor() {
+ @VisibleForTesting
+ final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override
public void onSomePackagesChanged() {
refreshAgentList(UserHandle.USER_ALL);
diff --git a/services/core/java/com/android/server/vcn/VcnContext.java b/services/core/java/com/android/server/vcn/VcnContext.java
index 9213d96..1383708 100644
--- a/services/core/java/com/android/server/vcn/VcnContext.java
+++ b/services/core/java/com/android/server/vcn/VcnContext.java
@@ -34,6 +34,7 @@
@NonNull private final Looper mLooper;
@NonNull private final VcnNetworkProvider mVcnNetworkProvider;
@NonNull private final FeatureFlags mFeatureFlags;
+ @NonNull private final android.net.platform.flags.FeatureFlags mCoreNetFeatureFlags;
private final boolean mIsInTestMode;
public VcnContext(
@@ -48,6 +49,7 @@
// Auto-generated class
mFeatureFlags = new FeatureFlagsImpl();
+ mCoreNetFeatureFlags = new android.net.platform.flags.FeatureFlagsImpl();
}
@NonNull
@@ -69,11 +71,23 @@
return mIsInTestMode;
}
+ public boolean isFlagNetworkMetricMonitorEnabled() {
+ return mFeatureFlags.networkMetricMonitor();
+ }
+
+ public boolean isFlagIpSecTransformStateEnabled() {
+ return mCoreNetFeatureFlags.ipsecTransformState();
+ }
+
@NonNull
public FeatureFlags getFeatureFlags() {
return mFeatureFlags;
}
+ public boolean isFlagSafeModeTimeoutConfigEnabled() {
+ return mFeatureFlags.safeModeTimeoutConfig();
+ }
+
/**
* Verifies that the caller is running on the VcnContext Thread.
*
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 54c97dd..3094b18 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -915,9 +915,11 @@
// TODO(b/180132994): explore safely removing this Thread check
mVcnContext.ensureRunningOnLooperThread();
- logInfo(
- "Selected underlying network changed: "
- + (underlying == null ? null : underlying.network));
+ if (!UnderlyingNetworkRecord.isSameNetwork(mUnderlying, underlying)) {
+ logInfo(
+ "Selected underlying network changed: "
+ + (underlying == null ? null : underlying.network));
+ }
// TODO(b/179091925): Move the delayed-message handling to BaseState
@@ -1242,9 +1244,28 @@
createScheduledAlarm(
SAFEMODE_TIMEOUT_ALARM,
delayedMessage,
- mVcnContext.isInTestMode()
- ? TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS_TEST_MODE)
- : TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
+ getSafeModeTimeoutMs(mVcnContext, mLastSnapshot, mSubscriptionGroup));
+ }
+
+ /** Gets the safe mode timeout */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static long getSafeModeTimeoutMs(
+ VcnContext vcnContext, TelephonySubscriptionSnapshot snapshot, ParcelUuid subGrp) {
+ final int defaultSeconds =
+ vcnContext.isInTestMode()
+ ? SAFEMODE_TIMEOUT_SECONDS_TEST_MODE
+ : SAFEMODE_TIMEOUT_SECONDS;
+
+ final PersistableBundleWrapper carrierConfig = snapshot.getCarrierConfigForSubGrp(subGrp);
+ int resultSeconds = defaultSeconds;
+
+ if (vcnContext.isFlagSafeModeTimeoutConfigEnabled() && carrierConfig != null) {
+ resultSeconds =
+ carrierConfig.getInt(
+ VcnManager.VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY, defaultSeconds);
+ }
+
+ return TimeUnit.SECONDS.toMillis(resultSeconds);
}
private void cancelSafeModeAlarm() {
@@ -1889,6 +1910,12 @@
// Transforms do not need to be persisted; the IkeSession will keep them alive
mIpSecManager.applyTunnelModeTransform(tunnelIface, direction, transform);
+ if (direction == IpSecManager.DIRECTION_IN
+ && mVcnContext.isFlagNetworkMetricMonitorEnabled()
+ && mVcnContext.isFlagIpSecTransformStateEnabled()) {
+ mUnderlyingNetworkController.updateInboundTransform(mUnderlying, transform);
+ }
+
// For inbound transforms, additionally allow forwarded traffic to bridge to DUN (as
// needed)
final Set<Integer> exposedCaps = mConnectionConfig.getAllExposedCapabilities();
diff --git a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
new file mode 100644
index 0000000..a25d67a
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
@@ -0,0 +1,388 @@
+/*
+ * 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.vcn.routeselection;
+
+import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.IpSecTransformState;
+import android.net.Network;
+import android.net.vcn.VcnManager;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.OutcomeReceiver;
+import android.os.PowerManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.server.vcn.VcnContext;
+
+import java.util.BitSet;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * IpSecPacketLossDetector is responsible for continuously monitoring IPsec packet loss
+ *
+ * <p>When the packet loss rate surpass the threshold, IpSecPacketLossDetector will report it to the
+ * caller
+ *
+ * <p>IpSecPacketLossDetector will start monitoring when the network being monitored is selected AND
+ * an inbound IpSecTransform has been applied to this network.
+ *
+ * <p>This class is flag gated by "network_metric_monitor" and "ipsec_tramsform_state"
+ */
+public class IpSecPacketLossDetector extends NetworkMetricMonitor {
+ private static final String TAG = IpSecPacketLossDetector.class.getSimpleName();
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PACKET_LOSS_UNAVALAIBLE = -1;
+
+ // For VoIP, losses between 5% and 10% of the total packet stream will affect the quality
+ // significantly (as per "Computer Networking for LANS to WANS: Hardware, Software and
+ // Security"). For audio and video streaming, above 10-12% packet loss is unacceptable (as per
+ // "ICTP-SDU: About PingER"). Thus choose 12% as a conservative default threshold to declare a
+ // validation failure.
+ private static final int IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DEFAULT = 12;
+
+ private static final int POLL_IPSEC_STATE_INTERVAL_SECONDS_DEFAULT = 20;
+
+ private long mPollIpSecStateIntervalMs;
+ private final int mPacketLossRatePercentThreshold;
+
+ @NonNull private final Handler mHandler;
+ @NonNull private final PowerManager mPowerManager;
+ @NonNull private final Object mCancellationToken = new Object();
+ @NonNull private final PacketLossCalculator mPacketLossCalculator;
+
+ @Nullable private IpSecTransformWrapper mInboundTransform;
+ @Nullable private IpSecTransformState mLastIpSecTransformState;
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public IpSecPacketLossDetector(
+ @NonNull VcnContext vcnContext,
+ @NonNull Network network,
+ @Nullable PersistableBundleWrapper carrierConfig,
+ @NonNull NetworkMetricMonitorCallback callback,
+ @NonNull Dependencies deps)
+ throws IllegalAccessException {
+ super(vcnContext, network, carrierConfig, callback);
+
+ Objects.requireNonNull(deps, "Missing deps");
+
+ if (!vcnContext.isFlagIpSecTransformStateEnabled()) {
+ // Caller error
+ logWtf("ipsecTransformState flag disabled");
+ throw new IllegalAccessException("ipsecTransformState flag disabled");
+ }
+
+ mHandler = new Handler(getVcnContext().getLooper());
+
+ mPowerManager = getVcnContext().getContext().getSystemService(PowerManager.class);
+
+ mPacketLossCalculator = deps.getPacketLossCalculator();
+
+ mPollIpSecStateIntervalMs = getPollIpSecStateIntervalMs(carrierConfig);
+ mPacketLossRatePercentThreshold = getPacketLossRatePercentThreshold(carrierConfig);
+
+ // Register for system broadcasts to monitor idle mode change
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ getVcnContext()
+ .getContext()
+ .registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(
+ intent.getAction())
+ && mPowerManager.isDeviceIdleMode()) {
+ mLastIpSecTransformState = null;
+ }
+ }
+ },
+ intentFilter,
+ null /* broadcastPermission not required */,
+ mHandler);
+ }
+
+ public IpSecPacketLossDetector(
+ @NonNull VcnContext vcnContext,
+ @NonNull Network network,
+ @Nullable PersistableBundleWrapper carrierConfig,
+ @NonNull NetworkMetricMonitorCallback callback)
+ throws IllegalAccessException {
+ this(vcnContext, network, carrierConfig, callback, new Dependencies());
+ }
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static class Dependencies {
+ public PacketLossCalculator getPacketLossCalculator() {
+ return new PacketLossCalculator();
+ }
+ }
+
+ private static long getPollIpSecStateIntervalMs(
+ @Nullable PersistableBundleWrapper carrierConfig) {
+ final int seconds;
+
+ if (carrierConfig != null) {
+ seconds =
+ carrierConfig.getInt(
+ VcnManager.VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY,
+ POLL_IPSEC_STATE_INTERVAL_SECONDS_DEFAULT);
+ } else {
+ seconds = POLL_IPSEC_STATE_INTERVAL_SECONDS_DEFAULT;
+ }
+
+ return TimeUnit.SECONDS.toMillis(seconds);
+ }
+
+ private static int getPacketLossRatePercentThreshold(
+ @Nullable PersistableBundleWrapper carrierConfig) {
+ if (carrierConfig != null) {
+ return carrierConfig.getInt(
+ VcnManager.VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY,
+ IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DEFAULT);
+ }
+ return IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DEFAULT;
+ }
+
+ @Override
+ protected void onSelectedUnderlyingNetworkChanged() {
+ if (!isSelectedUnderlyingNetwork()) {
+ mInboundTransform = null;
+ stop();
+ }
+
+ // No action when the underlying network got selected. Wait for the inbound transform to
+ // start the monitor
+ }
+
+ @Override
+ public void setInboundTransformInternal(@NonNull IpSecTransformWrapper inboundTransform) {
+ Objects.requireNonNull(inboundTransform, "inboundTransform is null");
+
+ if (Objects.equals(inboundTransform, mInboundTransform)) {
+ return;
+ }
+
+ if (!isSelectedUnderlyingNetwork()) {
+ logWtf("setInboundTransform called but network not selected");
+ return;
+ }
+
+ // When multiple parallel inbound transforms are created, NetworkMetricMonitor will be
+ // enabled on the last one as a sample
+ mInboundTransform = inboundTransform;
+ start();
+ }
+
+ @Override
+ public void setCarrierConfig(@Nullable PersistableBundleWrapper carrierConfig) {
+ // The already scheduled event will not be affected. The followup events will be scheduled
+ // with the new interval
+ mPollIpSecStateIntervalMs = getPollIpSecStateIntervalMs(carrierConfig);
+ }
+
+ @Override
+ protected void start() {
+ super.start();
+ clearTransformStateAndPollingEvents();
+ mHandler.postDelayed(new PollIpSecStateRunnable(), mCancellationToken, 0L);
+ }
+
+ @Override
+ public void stop() {
+ super.stop();
+ clearTransformStateAndPollingEvents();
+ }
+
+ private void clearTransformStateAndPollingEvents() {
+ mHandler.removeCallbacksAndEqualMessages(mCancellationToken);
+ mLastIpSecTransformState = null;
+ }
+
+ @Override
+ public void close() {
+ super.close();
+
+ if (mInboundTransform != null) {
+ mInboundTransform.close();
+ }
+ }
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ @Nullable
+ public IpSecTransformState getLastTransformState() {
+ return mLastIpSecTransformState;
+ }
+
+ @VisibleForTesting(visibility = Visibility.PROTECTED)
+ @Nullable
+ public IpSecTransformWrapper getInboundTransformInternal() {
+ return mInboundTransform;
+ }
+
+ private class PollIpSecStateRunnable implements Runnable {
+ @Override
+ public void run() {
+ if (!isStarted()) {
+ logWtf("Monitor stopped but PollIpSecStateRunnable not removed from Handler");
+ return;
+ }
+
+ getInboundTransformInternal()
+ .requestIpSecTransformState(
+ new HandlerExecutor(mHandler), new IpSecTransformStateReceiver());
+
+ // Schedule for next poll
+ mHandler.postDelayed(
+ new PollIpSecStateRunnable(), mCancellationToken, mPollIpSecStateIntervalMs);
+ }
+ }
+
+ private class IpSecTransformStateReceiver
+ implements OutcomeReceiver<IpSecTransformState, RuntimeException> {
+ @Override
+ public void onResult(@NonNull IpSecTransformState state) {
+ getVcnContext().ensureRunningOnLooperThread();
+
+ if (!isStarted()) {
+ return;
+ }
+
+ onIpSecTransformStateReceived(state);
+ }
+
+ @Override
+ public void onError(@NonNull RuntimeException error) {
+ getVcnContext().ensureRunningOnLooperThread();
+
+ // Nothing we can do here
+ logW("TransformStateReceiver#onError " + error.toString());
+ }
+ }
+
+ private void onIpSecTransformStateReceived(@NonNull IpSecTransformState state) {
+ if (mLastIpSecTransformState == null) {
+ // This is first time to poll the state
+ mLastIpSecTransformState = state;
+ return;
+ }
+
+ final int packetLossRate =
+ mPacketLossCalculator.getPacketLossRatePercentage(
+ mLastIpSecTransformState, state, getLogPrefix());
+
+ if (packetLossRate == PACKET_LOSS_UNAVALAIBLE) {
+ return;
+ }
+
+ final String logMsg =
+ "packetLossRate: "
+ + packetLossRate
+ + "% in the past "
+ + (state.getTimestampMillis()
+ - mLastIpSecTransformState.getTimestampMillis())
+ + "ms";
+
+ mLastIpSecTransformState = state;
+ if (packetLossRate < mPacketLossRatePercentThreshold) {
+ logV(logMsg);
+ onValidationResultReceivedInternal(false /* isFailed */);
+ } else {
+ logInfo(logMsg);
+ onValidationResultReceivedInternal(true /* isFailed */);
+ }
+ }
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static class PacketLossCalculator {
+ /** Calculate the packet loss rate between two timestamps */
+ public int getPacketLossRatePercentage(
+ @NonNull IpSecTransformState oldState,
+ @NonNull IpSecTransformState newState,
+ String logPrefix) {
+ logVIpSecTransform("oldState", oldState, logPrefix);
+ logVIpSecTransform("newState", newState, logPrefix);
+
+ final int replayWindowSize = oldState.getReplayBitmap().length * 8;
+ final long oldSeqHi = oldState.getRxHighestSequenceNumber();
+ final long oldSeqLow = Math.max(0L, oldSeqHi - replayWindowSize + 1);
+ final long newSeqHi = newState.getRxHighestSequenceNumber();
+ final long newSeqLow = Math.max(0L, newSeqHi - replayWindowSize + 1);
+
+ if (oldSeqHi == newSeqHi || newSeqHi < replayWindowSize) {
+ // The replay window did not proceed and all packets might have been delivered out
+ // of order
+ return PACKET_LOSS_UNAVALAIBLE;
+ }
+
+ // Get the expected packet count by assuming there is no packet loss. In this case, SA
+ // should receive all packets whose sequence numbers are smaller than the lower bound of
+ // the replay window AND the packets received within the window.
+ // When the lower bound is 0, it's not possible to tell whether packet with seqNo 0 is
+ // received or not. For simplicity just assume that packet is received.
+ final long newExpectedPktCnt = newSeqLow + getPacketCntInReplayWindow(newState);
+ final long oldExpectedPktCnt = oldSeqLow + getPacketCntInReplayWindow(oldState);
+
+ final long expectedPktCntDiff = newExpectedPktCnt - oldExpectedPktCnt;
+ final long actualPktCntDiff = newState.getPacketCount() - oldState.getPacketCount();
+
+ logV(
+ TAG,
+ logPrefix
+ + " expectedPktCntDiff: "
+ + expectedPktCntDiff
+ + " actualPktCntDiff: "
+ + actualPktCntDiff);
+
+ if (expectedPktCntDiff < 0
+ || expectedPktCntDiff == 0
+ || actualPktCntDiff < 0
+ || actualPktCntDiff > expectedPktCntDiff) {
+ logWtf(TAG, "Impossible values for expectedPktCntDiff or" + " actualPktCntDiff");
+ return PACKET_LOSS_UNAVALAIBLE;
+ }
+
+ return 100 - (int) (actualPktCntDiff * 100 / expectedPktCntDiff);
+ }
+ }
+
+ private static void logVIpSecTransform(
+ String transformTag, IpSecTransformState state, String logPrefix) {
+ final String stateString =
+ " seqNo: "
+ + state.getRxHighestSequenceNumber()
+ + " | pktCnt: "
+ + state.getPacketCount()
+ + " | pktCntInWindow: "
+ + getPacketCntInReplayWindow(state);
+ logV(TAG, logPrefix + " " + transformTag + stateString);
+ }
+
+ /** Get the number of received packets within the replay window */
+ private static long getPacketCntInReplayWindow(@NonNull IpSecTransformState state) {
+ return BitSet.valueOf(state.getReplayBitmap()).cardinality();
+ }
+}
diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java b/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
new file mode 100644
index 0000000..1704aa1
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
@@ -0,0 +1,269 @@
+/*
+ * 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.vcn.routeselection;
+
+import static com.android.server.VcnManagementService.LOCAL_LOG;
+import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.IpSecTransform;
+import android.net.IpSecTransformState;
+import android.net.Network;
+import android.os.OutcomeReceiver;
+import android.util.CloseGuard;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.server.vcn.VcnContext;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/**
+ * NetworkMetricMonitor is responsible for managing metric monitoring and tracking validation
+ * results.
+ *
+ * <p>This class is flag gated by "network_metric_monitor"
+ */
+public abstract class NetworkMetricMonitor implements AutoCloseable {
+ private static final String TAG = NetworkMetricMonitor.class.getSimpleName();
+
+ private static final boolean VDBG = false; // STOPSHIP: if true
+
+ @NonNull private final CloseGuard mCloseGuard = new CloseGuard();
+
+ @NonNull private final VcnContext mVcnContext;
+ @NonNull private final Network mNetwork;
+ @NonNull private final NetworkMetricMonitorCallback mCallback;
+
+ private boolean mIsSelectedUnderlyingNetwork;
+ private boolean mIsStarted;
+ private boolean mIsValidationFailed;
+
+ protected NetworkMetricMonitor(
+ @NonNull VcnContext vcnContext,
+ @NonNull Network network,
+ @Nullable PersistableBundleWrapper carrierConfig,
+ @NonNull NetworkMetricMonitorCallback callback)
+ throws IllegalAccessException {
+ if (!vcnContext.isFlagNetworkMetricMonitorEnabled()) {
+ // Caller error
+ logWtf("networkMetricMonitor flag disabled");
+ throw new IllegalAccessException("networkMetricMonitor flag disabled");
+ }
+
+ mVcnContext = Objects.requireNonNull(vcnContext, "Missing vcnContext");
+ mNetwork = Objects.requireNonNull(network, "Missing network");
+ mCallback = Objects.requireNonNull(callback, "Missing callback");
+
+ mIsSelectedUnderlyingNetwork = false;
+ mIsStarted = false;
+ mIsValidationFailed = false;
+ }
+
+ /** Callback to notify caller of the validation result */
+ public interface NetworkMetricMonitorCallback {
+ /** Called when there is a validation result is ready */
+ void onValidationResultReceived();
+ }
+
+ /**
+ * Start monitoring
+ *
+ * <p>This method might be called on a an already started monitor for updating monitor
+ * properties (e.g. IpSecTransform, carrier config)
+ *
+ * <p>Subclasses MUST call super.start() when overriding this method
+ */
+ protected void start() {
+ mIsStarted = true;
+ }
+
+ /**
+ * Stop monitoring
+ *
+ * <p>Subclasses MUST call super.stop() when overriding this method
+ */
+ public void stop() {
+ mIsValidationFailed = false;
+ mIsStarted = false;
+ }
+
+ /** Called by the subclasses when the validation result is ready */
+ protected void onValidationResultReceivedInternal(boolean isFailed) {
+ mIsValidationFailed = isFailed;
+ mCallback.onValidationResultReceived();
+ }
+
+ /** Called when the underlying network changes to selected or unselected */
+ protected abstract void onSelectedUnderlyingNetworkChanged();
+
+ /**
+ * Mark the network being monitored selected or unselected
+ *
+ * <p>Subclasses MUST call super when overriding this method
+ */
+ public void setIsSelectedUnderlyingNetwork(boolean isSelectedUnderlyingNetwork) {
+ if (mIsSelectedUnderlyingNetwork == isSelectedUnderlyingNetwork) {
+ return;
+ }
+
+ mIsSelectedUnderlyingNetwork = isSelectedUnderlyingNetwork;
+ onSelectedUnderlyingNetworkChanged();
+ }
+
+ /** Wrapper that allows injection for testing purposes */
+ @VisibleForTesting(visibility = Visibility.PROTECTED)
+ public static class IpSecTransformWrapper {
+ @NonNull public final IpSecTransform ipSecTransform;
+
+ public IpSecTransformWrapper(@NonNull IpSecTransform ipSecTransform) {
+ this.ipSecTransform = ipSecTransform;
+ }
+
+ /** Poll an IpSecTransformState */
+ public void requestIpSecTransformState(
+ @NonNull Executor executor,
+ @NonNull OutcomeReceiver<IpSecTransformState, RuntimeException> callback) {
+ ipSecTransform.requestIpSecTransformState(executor, callback);
+ }
+
+ /** Close this instance and release the underlying resources */
+ public void close() {
+ ipSecTransform.close();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ipSecTransform);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof IpSecTransformWrapper)) {
+ return false;
+ }
+
+ final IpSecTransformWrapper other = (IpSecTransformWrapper) o;
+
+ return Objects.equals(ipSecTransform, other.ipSecTransform);
+ }
+ }
+
+ /** Set the IpSecTransform that applied to the Network being monitored */
+ public void setInboundTransform(@NonNull IpSecTransform inTransform) {
+ setInboundTransformInternal(new IpSecTransformWrapper(inTransform));
+ }
+
+ /**
+ * Set the IpSecTransform that applied to the Network being monitored *
+ *
+ * <p>Subclasses MUST call super when overriding this method
+ */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public void setInboundTransformInternal(@NonNull IpSecTransformWrapper inTransform) {
+ // Subclasses MUST override it if they care
+ }
+
+ /** Update the carrierconfig */
+ public void setCarrierConfig(@Nullable PersistableBundleWrapper carrierConfig) {
+ // Subclasses MUST override it if they care
+ }
+
+ public boolean isValidationFailed() {
+ return mIsValidationFailed;
+ }
+
+ public boolean isSelectedUnderlyingNetwork() {
+ return mIsSelectedUnderlyingNetwork;
+ }
+
+ public boolean isStarted() {
+ return mIsStarted;
+ }
+
+ @NonNull
+ public VcnContext getVcnContext() {
+ return mVcnContext;
+ }
+
+ // Override methods for AutoCloseable. Subclasses MUST call super when overriding this method
+ @Override
+ public void close() {
+ mCloseGuard.close();
+
+ stop();
+ }
+
+ // Override #finalize() to use closeGuard for flagging that #close() was not called
+ @SuppressWarnings("Finalize")
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ if (mCloseGuard != null) {
+ mCloseGuard.warnIfOpen();
+ }
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private String getClassName() {
+ return this.getClass().getSimpleName();
+ }
+
+ protected String getLogPrefix() {
+ return " [Network " + mNetwork + "] ";
+ }
+
+ protected void logV(String msg) {
+ if (VDBG) {
+ Slog.v(getClassName(), getLogPrefix() + msg);
+ LOCAL_LOG.log("[VERBOSE ] " + getClassName() + getLogPrefix() + msg);
+ }
+ }
+
+ protected void logInfo(String msg) {
+ Slog.i(getClassName(), getLogPrefix() + msg);
+ LOCAL_LOG.log("[INFO ] " + getClassName() + getLogPrefix() + msg);
+ }
+
+ protected void logW(String msg) {
+ Slog.w(getClassName(), getLogPrefix() + msg);
+ LOCAL_LOG.log("[WARN ] " + getClassName() + getLogPrefix() + msg);
+ }
+
+ protected void logWtf(String msg) {
+ Slog.wtf(getClassName(), getLogPrefix() + msg);
+ LOCAL_LOG.log("[WTF ] " + getClassName() + getLogPrefix() + msg);
+ }
+
+ protected static void logV(String className, String msgWithPrefix) {
+ if (VDBG) {
+ Slog.wtf(className, msgWithPrefix);
+ LOCAL_LOG.log("[VERBOSE ] " + className + msgWithPrefix);
+ }
+ }
+
+ protected static void logWtf(String className, String msgWithPrefix) {
+ Slog.wtf(className, msgWithPrefix);
+ LOCAL_LOG.log("[WTF ] " + className + msgWithPrefix);
+ }
+}
diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
index 7f129ea..d32e5cc 100644
--- a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
+++ b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
@@ -47,7 +47,6 @@
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Set;
/** @hide */
@@ -86,7 +85,6 @@
* <p>VCN MUST never select a non-INTERNET network that are unvalidated or fail to match any
* template as the underlying network.
*/
- @VisibleForTesting(visibility = Visibility.PRIVATE)
static final int PRIORITY_INVALID = -1;
/** Gives networks a priority class, based on configured VcnGatewayConnectionConfig */
@@ -96,7 +94,7 @@
List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
ParcelUuid subscriptionGroup,
TelephonySubscriptionSnapshot snapshot,
- UnderlyingNetworkRecord currentlySelected,
+ boolean isSelected,
PersistableBundleWrapper carrierConfig) {
// mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED
@@ -118,7 +116,7 @@
networkRecord,
subscriptionGroup,
snapshot,
- currentlySelected,
+ isSelected,
carrierConfig)) {
return priorityIndex;
}
@@ -140,12 +138,9 @@
UnderlyingNetworkRecord networkRecord,
ParcelUuid subscriptionGroup,
TelephonySubscriptionSnapshot snapshot,
- UnderlyingNetworkRecord currentlySelected,
+ boolean isSelected,
PersistableBundleWrapper carrierConfig) {
final NetworkCapabilities caps = networkRecord.networkCapabilities;
- final boolean isSelectedUnderlyingNetwork =
- currentlySelected != null
- && Objects.equals(currentlySelected.network, networkRecord.network);
final int meteredMatch = networkPriority.getMetered();
final boolean isMetered = !caps.hasCapability(NET_CAPABILITY_NOT_METERED);
@@ -159,7 +154,7 @@
if (caps.getLinkUpstreamBandwidthKbps() < networkPriority.getMinExitUpstreamBandwidthKbps()
|| (caps.getLinkUpstreamBandwidthKbps()
< networkPriority.getMinEntryUpstreamBandwidthKbps()
- && !isSelectedUnderlyingNetwork)) {
+ && !isSelected)) {
return false;
}
@@ -167,7 +162,7 @@
< networkPriority.getMinExitDownstreamBandwidthKbps()
|| (caps.getLinkDownstreamBandwidthKbps()
< networkPriority.getMinEntryDownstreamBandwidthKbps()
- && !isSelectedUnderlyingNetwork)) {
+ && !isSelected)) {
return false;
}
@@ -191,7 +186,7 @@
return checkMatchesWifiPriorityRule(
(VcnWifiUnderlyingNetworkTemplate) networkPriority,
networkRecord,
- currentlySelected,
+ isSelected,
carrierConfig);
}
@@ -214,7 +209,7 @@
public static boolean checkMatchesWifiPriorityRule(
VcnWifiUnderlyingNetworkTemplate networkPriority,
UnderlyingNetworkRecord networkRecord,
- UnderlyingNetworkRecord currentlySelected,
+ boolean isSelected,
PersistableBundleWrapper carrierConfig) {
final NetworkCapabilities caps = networkRecord.networkCapabilities;
@@ -223,7 +218,7 @@
}
// TODO: Move the Network Quality check to the network metric monitor framework.
- if (!isWifiRssiAcceptable(networkRecord, currentlySelected, carrierConfig)) {
+ if (!isWifiRssiAcceptable(networkRecord, isSelected, carrierConfig)) {
return false;
}
@@ -237,15 +232,11 @@
private static boolean isWifiRssiAcceptable(
UnderlyingNetworkRecord networkRecord,
- UnderlyingNetworkRecord currentlySelected,
+ boolean isSelected,
PersistableBundleWrapper carrierConfig) {
final NetworkCapabilities caps = networkRecord.networkCapabilities;
- final boolean isSelectedNetwork =
- currentlySelected != null
- && networkRecord.network.equals(currentlySelected.network);
- if (isSelectedNetwork
- && caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)) {
+ if (isSelected && caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)) {
return true;
}
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
index 6afa795..3f8d39e 100644
--- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
@@ -30,6 +30,7 @@
import android.annotation.Nullable;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.IpSecTransform;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -48,9 +49,11 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.VcnContext;
+import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback;
import com.android.server.vcn.util.LogUtils;
import java.util.ArrayList;
@@ -83,6 +86,9 @@
@NonNull private final TelephonyCallback mActiveDataSubIdListener =
new VcnActiveDataSubscriptionIdListener();
+ private final Map<Network, UnderlyingNetworkEvaluator> mUnderlyingNetworkRecords =
+ new ArrayMap<>();
+
@NonNull private final List<NetworkCallback> mCellBringupCallbacks = new ArrayList<>();
@Nullable private NetworkCallback mWifiBringupCallback;
@Nullable private NetworkCallback mWifiEntryRssiThresholdCallback;
@@ -105,7 +111,8 @@
this(vcnContext, connectionConfig, subscriptionGroup, snapshot, cb, new Dependencies());
}
- private UnderlyingNetworkController(
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ UnderlyingNetworkController(
@NonNull VcnContext vcnContext,
@NonNull VcnGatewayConnectionConfig connectionConfig,
@NonNull ParcelUuid subscriptionGroup,
@@ -197,6 +204,15 @@
List<NetworkCallback> oldCellCallbacks = new ArrayList<>(mCellBringupCallbacks);
mCellBringupCallbacks.clear();
+ if (mVcnContext.isFlagNetworkMetricMonitorEnabled()
+ && mVcnContext.isFlagIpSecTransformStateEnabled()) {
+ for (UnderlyingNetworkEvaluator evaluator : mUnderlyingNetworkRecords.values()) {
+ evaluator.close();
+ }
+ }
+
+ mUnderlyingNetworkRecords.clear();
+
// Register new callbacks. Make-before-break; always register new callbacks before removal
// of old callbacks
if (!mIsQuitting) {
@@ -395,15 +411,58 @@
// Update carrier config
mCarrierConfig = mLastSnapshot.getCarrierConfigForSubGrp(mSubscriptionGroup);
+ // Make sure all evaluators use the same updated TelephonySubscriptionSnapshot and carrier
+ // config to calculate their cached priority classes. For simplicity, the
+ // UnderlyingNetworkController does not listen for changes in VCN-related carrier config
+ // keys, and changes are applied at restart of the VcnGatewayConnection
+ for (UnderlyingNetworkEvaluator evaluator : mUnderlyingNetworkRecords.values()) {
+ evaluator.reevaluate(
+ mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
+ mSubscriptionGroup,
+ mLastSnapshot,
+ mCarrierConfig);
+ }
+
// Only trigger re-registration if subIds in this group have changed
if (oldSnapshot
.getAllSubIdsInGroup(mSubscriptionGroup)
.equals(newSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))) {
+
+ if (mVcnContext.isFlagNetworkMetricMonitorEnabled()
+ && mVcnContext.isFlagIpSecTransformStateEnabled()) {
+ reevaluateNetworks();
+ }
return;
}
registerOrUpdateNetworkRequests();
}
+ /**
+ * Pass the IpSecTransform of the VCN to UnderlyingNetworkController for metric monitoring
+ *
+ * <p>Caller MUST call it when IpSecTransforms have been created for VCN creation or migration
+ */
+ public void updateInboundTransform(
+ @NonNull UnderlyingNetworkRecord currentNetwork, @NonNull IpSecTransform transform) {
+ if (!mVcnContext.isFlagNetworkMetricMonitorEnabled()
+ || !mVcnContext.isFlagIpSecTransformStateEnabled()) {
+ logWtf("#updateInboundTransform: unexpected call; flags missing");
+ return;
+ }
+
+ Objects.requireNonNull(currentNetwork, "currentNetwork is null");
+ Objects.requireNonNull(transform, "transform is null");
+
+ if (mCurrentRecord == null
+ || mRouteSelectionCallback == null
+ || !Objects.equals(currentNetwork.network, mCurrentRecord.network)) {
+ // The caller (VcnGatewayConnection) is out-of-dated. Ignore this call.
+ return;
+ }
+
+ mUnderlyingNetworkRecords.get(mCurrentRecord.network).setInboundTransform(transform);
+ }
+
/** Tears down this Tracker, and releases all underlying network requests. */
public void teardown() {
mVcnContext.ensureRunningOnLooperThread();
@@ -418,32 +477,62 @@
.unregisterTelephonyCallback(mActiveDataSubIdListener);
}
+ private TreeSet<UnderlyingNetworkEvaluator> getSortedUnderlyingNetworks() {
+ TreeSet<UnderlyingNetworkEvaluator> sorted =
+ new TreeSet<>(UnderlyingNetworkEvaluator.getComparator(mVcnContext));
+
+ for (UnderlyingNetworkEvaluator evaluator : mUnderlyingNetworkRecords.values()) {
+ if (evaluator.getPriorityClass() != NetworkPriorityClassifier.PRIORITY_INVALID) {
+ sorted.add(evaluator);
+ }
+ }
+
+ return sorted;
+ }
+
private void reevaluateNetworks() {
if (mIsQuitting || mRouteSelectionCallback == null) {
return; // UnderlyingNetworkController has quit.
}
- TreeSet<UnderlyingNetworkRecord> sorted =
- mRouteSelectionCallback.getSortedUnderlyingNetworks();
- UnderlyingNetworkRecord candidate = sorted.isEmpty() ? null : sorted.first();
+ TreeSet<UnderlyingNetworkEvaluator> sorted = getSortedUnderlyingNetworks();
+
+ UnderlyingNetworkEvaluator candidateEvaluator = sorted.isEmpty() ? null : sorted.first();
+ UnderlyingNetworkRecord candidate =
+ candidateEvaluator == null ? null : candidateEvaluator.getNetworkRecord();
if (Objects.equals(mCurrentRecord, candidate)) {
return;
}
String allNetworkPriorities = "";
- for (UnderlyingNetworkRecord record : sorted) {
+ for (UnderlyingNetworkEvaluator recordEvaluator : sorted) {
if (!allNetworkPriorities.isEmpty()) {
allNetworkPriorities += ", ";
}
- allNetworkPriorities += record.network + ": " + record.priorityClass;
+ allNetworkPriorities +=
+ recordEvaluator.getNetwork() + ": " + recordEvaluator.getPriorityClass();
}
- logInfo(
- "Selected network changed to "
- + (candidate == null ? null : candidate.network)
- + ", selected from list: "
- + allNetworkPriorities);
+
+ if (!UnderlyingNetworkRecord.isSameNetwork(mCurrentRecord, candidate)) {
+ logInfo(
+ "Selected network changed to "
+ + (candidate == null ? null : candidate.network)
+ + ", selected from list: "
+ + allNetworkPriorities);
+ }
+
mCurrentRecord = candidate;
mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
+
+ // Need to update all evaluators to ensure the previously selected one is unselected
+ for (UnderlyingNetworkEvaluator evaluator : mUnderlyingNetworkRecords.values()) {
+ evaluator.setIsSelected(
+ candidateEvaluator == evaluator,
+ mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
+ mSubscriptionGroup,
+ mLastSnapshot,
+ mCarrierConfig);
+ }
}
/**
@@ -463,46 +552,32 @@
*/
@VisibleForTesting
class UnderlyingNetworkListener extends NetworkCallback {
- private final Map<Network, UnderlyingNetworkRecord.Builder>
- mUnderlyingNetworkRecordBuilders = new ArrayMap<>();
-
UnderlyingNetworkListener() {
super(NetworkCallback.FLAG_INCLUDE_LOCATION_INFO);
}
- private TreeSet<UnderlyingNetworkRecord> getSortedUnderlyingNetworks() {
- TreeSet<UnderlyingNetworkRecord> sorted =
- new TreeSet<>(UnderlyingNetworkRecord.getComparator());
-
- for (UnderlyingNetworkRecord.Builder builder :
- mUnderlyingNetworkRecordBuilders.values()) {
- if (builder.isValid()) {
- final UnderlyingNetworkRecord record =
- builder.build(
- mVcnContext,
- mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
- mSubscriptionGroup,
- mLastSnapshot,
- mCurrentRecord,
- mCarrierConfig);
- if (record.priorityClass != NetworkPriorityClassifier.PRIORITY_INVALID) {
- sorted.add(record);
- }
- }
- }
-
- return sorted;
- }
-
@Override
public void onAvailable(@NonNull Network network) {
- mUnderlyingNetworkRecordBuilders.put(
- network, new UnderlyingNetworkRecord.Builder(network));
+ mUnderlyingNetworkRecords.put(
+ network,
+ mDeps.newUnderlyingNetworkEvaluator(
+ mVcnContext,
+ network,
+ mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
+ mSubscriptionGroup,
+ mLastSnapshot,
+ mCarrierConfig,
+ new NetworkEvaluatorCallbackImpl()));
}
@Override
public void onLost(@NonNull Network network) {
- mUnderlyingNetworkRecordBuilders.remove(network);
+ if (mVcnContext.isFlagNetworkMetricMonitorEnabled()
+ && mVcnContext.isFlagIpSecTransformStateEnabled()) {
+ mUnderlyingNetworkRecords.get(network).close();
+ }
+
+ mUnderlyingNetworkRecords.remove(network);
reevaluateNetworks();
}
@@ -510,15 +585,20 @@
@Override
public void onCapabilitiesChanged(
@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
- final UnderlyingNetworkRecord.Builder builder =
- mUnderlyingNetworkRecordBuilders.get(network);
- if (builder == null) {
+ final UnderlyingNetworkEvaluator evaluator = mUnderlyingNetworkRecords.get(network);
+ if (evaluator == null) {
logWtf("Got capabilities change for unknown key: " + network);
return;
}
- builder.setNetworkCapabilities(networkCapabilities);
- if (builder.isValid()) {
+ evaluator.setNetworkCapabilities(
+ networkCapabilities,
+ mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
+ mSubscriptionGroup,
+ mLastSnapshot,
+ mCarrierConfig);
+
+ if (evaluator.isValid()) {
reevaluateNetworks();
}
}
@@ -526,35 +606,60 @@
@Override
public void onLinkPropertiesChanged(
@NonNull Network network, @NonNull LinkProperties linkProperties) {
- final UnderlyingNetworkRecord.Builder builder =
- mUnderlyingNetworkRecordBuilders.get(network);
- if (builder == null) {
+ final UnderlyingNetworkEvaluator evaluator = mUnderlyingNetworkRecords.get(network);
+ if (evaluator == null) {
logWtf("Got link properties change for unknown key: " + network);
return;
}
- builder.setLinkProperties(linkProperties);
- if (builder.isValid()) {
+ evaluator.setLinkProperties(
+ linkProperties,
+ mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
+ mSubscriptionGroup,
+ mLastSnapshot,
+ mCarrierConfig);
+
+ if (evaluator.isValid()) {
reevaluateNetworks();
}
}
@Override
public void onBlockedStatusChanged(@NonNull Network network, boolean isBlocked) {
- final UnderlyingNetworkRecord.Builder builder =
- mUnderlyingNetworkRecordBuilders.get(network);
- if (builder == null) {
+ final UnderlyingNetworkEvaluator evaluator = mUnderlyingNetworkRecords.get(network);
+ if (evaluator == null) {
logWtf("Got blocked status change for unknown key: " + network);
return;
}
- builder.setIsBlocked(isBlocked);
- if (builder.isValid()) {
+ evaluator.setIsBlocked(
+ isBlocked,
+ mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
+ mSubscriptionGroup,
+ mLastSnapshot,
+ mCarrierConfig);
+
+ if (evaluator.isValid()) {
reevaluateNetworks();
}
}
}
+ @VisibleForTesting
+ class NetworkEvaluatorCallbackImpl implements NetworkEvaluatorCallback {
+ @Override
+ public void onEvaluationResultChanged() {
+ if (!mVcnContext.isFlagNetworkMetricMonitorEnabled()
+ || !mVcnContext.isFlagIpSecTransformStateEnabled()) {
+ logWtf("#onEvaluationResultChanged: unexpected call; flags missing");
+ return;
+ }
+
+ mVcnContext.ensureRunningOnLooperThread();
+ reevaluateNetworks();
+ }
+ }
+
private String getLogPrefix() {
return "("
+ LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup)
@@ -614,16 +719,8 @@
pw.println("Underlying networks:");
pw.increaseIndent();
if (mRouteSelectionCallback != null) {
- for (UnderlyingNetworkRecord record :
- mRouteSelectionCallback.getSortedUnderlyingNetworks()) {
- record.dump(
- mVcnContext,
- pw,
- mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
- mSubscriptionGroup,
- mLastSnapshot,
- mCurrentRecord,
- mCarrierConfig);
+ for (UnderlyingNetworkEvaluator recordEvaluator : getSortedUnderlyingNetworks()) {
+ recordEvaluator.dump(pw);
}
}
pw.decreaseIndent();
@@ -653,5 +750,24 @@
@Nullable UnderlyingNetworkRecord underlyingNetworkRecord);
}
- private static class Dependencies {}
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static class Dependencies {
+ public UnderlyingNetworkEvaluator newUnderlyingNetworkEvaluator(
+ @NonNull VcnContext vcnContext,
+ @NonNull Network network,
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull TelephonySubscriptionSnapshot lastSnapshot,
+ @Nullable PersistableBundleWrapper carrierConfig,
+ @NonNull NetworkEvaluatorCallback evaluatorCallback) {
+ return new UnderlyingNetworkEvaluator(
+ vcnContext,
+ network,
+ underlyingNetworkTemplates,
+ subscriptionGroup,
+ lastSnapshot,
+ carrierConfig,
+ evaluatorCallback);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
new file mode 100644
index 0000000..2f4cf5e
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
@@ -0,0 +1,442 @@
+/*
+ * 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.vcn.routeselection;
+
+import static com.android.server.VcnManagementService.LOCAL_LOG;
+import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.IpSecTransform;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.vcn.VcnManager;
+import android.net.vcn.VcnUnderlyingNetworkTemplate;
+import android.os.Handler;
+import android.os.ParcelUuid;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
+import com.android.server.vcn.VcnContext;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * UnderlyingNetworkEvaluator evaluates the quality and priority class of a network candidate for
+ * route selection.
+ *
+ * @hide
+ */
+public class UnderlyingNetworkEvaluator {
+ private static final String TAG = UnderlyingNetworkEvaluator.class.getSimpleName();
+
+ private static final int[] PENALTY_TIMEOUT_MINUTES_DEFAULT = new int[] {5};
+
+ @NonNull private final VcnContext mVcnContext;
+ @NonNull private final Handler mHandler;
+ @NonNull private final Object mCancellationToken = new Object();
+
+ @NonNull private final UnderlyingNetworkRecord.Builder mNetworkRecordBuilder;
+
+ @NonNull private final NetworkEvaluatorCallback mEvaluatorCallback;
+ @NonNull private final List<NetworkMetricMonitor> mMetricMonitors = new ArrayList<>();
+
+ @NonNull private final Dependencies mDependencies;
+
+ // TODO: Support back-off timeouts
+ private long mPenalizedTimeoutMs;
+
+ private boolean mIsSelected;
+ private boolean mIsPenalized;
+ private int mPriorityClass = NetworkPriorityClassifier.PRIORITY_INVALID;
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public UnderlyingNetworkEvaluator(
+ @NonNull VcnContext vcnContext,
+ @NonNull Network network,
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull TelephonySubscriptionSnapshot lastSnapshot,
+ @Nullable PersistableBundleWrapper carrierConfig,
+ @NonNull NetworkEvaluatorCallback evaluatorCallback,
+ @NonNull Dependencies dependencies) {
+ mVcnContext = Objects.requireNonNull(vcnContext, "Missing vcnContext");
+ mHandler = new Handler(mVcnContext.getLooper());
+
+ mDependencies = Objects.requireNonNull(dependencies, "Missing dependencies");
+ mEvaluatorCallback = Objects.requireNonNull(evaluatorCallback, "Missing deps");
+
+ Objects.requireNonNull(underlyingNetworkTemplates, "Missing underlyingNetworkTemplates");
+ Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
+ Objects.requireNonNull(lastSnapshot, "Missing lastSnapshot");
+
+ mNetworkRecordBuilder =
+ new UnderlyingNetworkRecord.Builder(
+ Objects.requireNonNull(network, "Missing network"));
+ mIsSelected = false;
+ mIsPenalized = false;
+ mPenalizedTimeoutMs = getPenaltyTimeoutMs(carrierConfig);
+
+ updatePriorityClass(
+ underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig);
+
+ if (isIpSecPacketLossDetectorEnabled()) {
+ try {
+ mMetricMonitors.add(
+ mDependencies.newIpSecPacketLossDetector(
+ mVcnContext,
+ mNetworkRecordBuilder.getNetwork(),
+ carrierConfig,
+ new MetricMonitorCallbackImpl()));
+ } catch (IllegalAccessException e) {
+ // No action. Do not add anything to mMetricMonitors
+ }
+ }
+ }
+
+ public UnderlyingNetworkEvaluator(
+ @NonNull VcnContext vcnContext,
+ @NonNull Network network,
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull TelephonySubscriptionSnapshot lastSnapshot,
+ @Nullable PersistableBundleWrapper carrierConfig,
+ @NonNull NetworkEvaluatorCallback evaluatorCallback) {
+ this(
+ vcnContext,
+ network,
+ underlyingNetworkTemplates,
+ subscriptionGroup,
+ lastSnapshot,
+ carrierConfig,
+ evaluatorCallback,
+ new Dependencies());
+ }
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static class Dependencies {
+ /** Get an IpSecPacketLossDetector instance */
+ public IpSecPacketLossDetector newIpSecPacketLossDetector(
+ @NonNull VcnContext vcnContext,
+ @NonNull Network network,
+ @Nullable PersistableBundleWrapper carrierConfig,
+ @NonNull NetworkMetricMonitor.NetworkMetricMonitorCallback callback)
+ throws IllegalAccessException {
+ return new IpSecPacketLossDetector(vcnContext, network, carrierConfig, callback);
+ }
+ }
+
+ /** Callback to notify caller to reevaluate network selection */
+ public interface NetworkEvaluatorCallback {
+ /**
+ * Called when mIsPenalized changed
+ *
+ * <p>When receiving this call, UnderlyingNetworkController should reevaluate all network
+ * candidates for VCN underlying network selection
+ */
+ void onEvaluationResultChanged();
+ }
+
+ private class MetricMonitorCallbackImpl
+ implements NetworkMetricMonitor.NetworkMetricMonitorCallback {
+ public void onValidationResultReceived() {
+ mVcnContext.ensureRunningOnLooperThread();
+
+ handleValidationResult();
+ }
+ }
+
+ private void updatePriorityClass(
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull TelephonySubscriptionSnapshot lastSnapshot,
+ @Nullable PersistableBundleWrapper carrierConfig) {
+ if (mNetworkRecordBuilder.isValid()) {
+ mPriorityClass =
+ NetworkPriorityClassifier.calculatePriorityClass(
+ mVcnContext,
+ mNetworkRecordBuilder.build(),
+ underlyingNetworkTemplates,
+ subscriptionGroup,
+ lastSnapshot,
+ mIsSelected,
+ carrierConfig);
+ } else {
+ mPriorityClass = NetworkPriorityClassifier.PRIORITY_INVALID;
+ }
+ }
+
+ private boolean isIpSecPacketLossDetectorEnabled() {
+ return isIpSecPacketLossDetectorEnabled(mVcnContext);
+ }
+
+ private static boolean isIpSecPacketLossDetectorEnabled(VcnContext vcnContext) {
+ return vcnContext.isFlagIpSecTransformStateEnabled()
+ && vcnContext.isFlagNetworkMetricMonitorEnabled();
+ }
+
+ /** Get the comparator for UnderlyingNetworkEvaluator */
+ public static Comparator<UnderlyingNetworkEvaluator> getComparator(VcnContext vcnContext) {
+ return (left, right) -> {
+ if (isIpSecPacketLossDetectorEnabled(vcnContext)) {
+ if (left.mIsPenalized != right.mIsPenalized) {
+ // A penalized network should have lower priority which means a larger index
+ return left.mIsPenalized ? 1 : -1;
+ }
+ }
+
+ final int leftIndex = left.mPriorityClass;
+ final int rightIndex = right.mPriorityClass;
+
+ // In the case of networks in the same priority class, prioritize based on other
+ // criteria (eg. actively selected network, link metrics, etc)
+ if (leftIndex == rightIndex) {
+ // TODO: Improve the strategy of network selection when both UnderlyingNetworkRecord
+ // fall into the same priority class.
+ if (left.mIsSelected) {
+ return -1;
+ }
+ if (right.mIsSelected) {
+ return 1;
+ }
+ }
+ return Integer.compare(leftIndex, rightIndex);
+ };
+ }
+
+ private static long getPenaltyTimeoutMs(@Nullable PersistableBundleWrapper carrierConfig) {
+ final int[] timeoutMinuteList;
+
+ if (carrierConfig != null) {
+ timeoutMinuteList =
+ carrierConfig.getIntArray(
+ VcnManager.VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY,
+ PENALTY_TIMEOUT_MINUTES_DEFAULT);
+ } else {
+ timeoutMinuteList = PENALTY_TIMEOUT_MINUTES_DEFAULT;
+ }
+
+ // TODO: Add the support of back-off timeouts and return the full list
+ return TimeUnit.MINUTES.toMillis(timeoutMinuteList[0]);
+ }
+
+ private void handleValidationResult() {
+ final boolean wasPenalized = mIsPenalized;
+ mIsPenalized = false;
+ for (NetworkMetricMonitor monitor : mMetricMonitors) {
+ mIsPenalized |= monitor.isValidationFailed();
+ }
+
+ if (wasPenalized == mIsPenalized) {
+ return;
+ }
+
+ logInfo(
+ "#handleValidationResult: wasPenalized "
+ + wasPenalized
+ + " mIsPenalized "
+ + mIsPenalized);
+
+ if (mIsPenalized) {
+ mHandler.postDelayed(
+ new ExitPenaltyBoxRunnable(), mCancellationToken, mPenalizedTimeoutMs);
+ } else {
+ // Exit the penalty box
+ mHandler.removeCallbacksAndEqualMessages(mCancellationToken);
+ }
+ mEvaluatorCallback.onEvaluationResultChanged();
+ }
+
+ public class ExitPenaltyBoxRunnable implements Runnable {
+ @Override
+ public void run() {
+ if (!mIsPenalized) {
+ logWtf("Evaluator not being penalized but ExitPenaltyBoxRunnable was scheduled");
+ return;
+ }
+
+ // TODO: There might be a future metric monitor (e.g. ping) that will require the
+ // validation to pass before exiting the penalty box.
+ mIsPenalized = false;
+ mEvaluatorCallback.onEvaluationResultChanged();
+ }
+ }
+
+ /** Set the NetworkCapabilities */
+ public void setNetworkCapabilities(
+ @NonNull NetworkCapabilities nc,
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull TelephonySubscriptionSnapshot lastSnapshot,
+ @Nullable PersistableBundleWrapper carrierConfig) {
+ mNetworkRecordBuilder.setNetworkCapabilities(nc);
+
+ updatePriorityClass(
+ underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig);
+ }
+
+ /** Set the LinkProperties */
+ public void setLinkProperties(
+ @NonNull LinkProperties lp,
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull TelephonySubscriptionSnapshot lastSnapshot,
+ @Nullable PersistableBundleWrapper carrierConfig) {
+ mNetworkRecordBuilder.setLinkProperties(lp);
+
+ updatePriorityClass(
+ underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig);
+ }
+
+ /** Set whether the network is blocked */
+ public void setIsBlocked(
+ boolean isBlocked,
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull TelephonySubscriptionSnapshot lastSnapshot,
+ @Nullable PersistableBundleWrapper carrierConfig) {
+ mNetworkRecordBuilder.setIsBlocked(isBlocked);
+
+ updatePriorityClass(
+ underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig);
+ }
+
+ /** Set whether the network is selected as VCN's underlying network */
+ public void setIsSelected(
+ boolean isSelected,
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull TelephonySubscriptionSnapshot lastSnapshot,
+ @Nullable PersistableBundleWrapper carrierConfig) {
+ mIsSelected = isSelected;
+
+ updatePriorityClass(
+ underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig);
+
+ for (NetworkMetricMonitor monitor : mMetricMonitors) {
+ monitor.setIsSelectedUnderlyingNetwork(isSelected);
+ }
+ }
+
+ /**
+ * Update the last TelephonySubscriptionSnapshot and carrier config to reevaluate the network
+ */
+ public void reevaluate(
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
+ @NonNull ParcelUuid subscriptionGroup,
+ @NonNull TelephonySubscriptionSnapshot lastSnapshot,
+ @Nullable PersistableBundleWrapper carrierConfig) {
+ updatePriorityClass(
+ underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig);
+
+ // The already scheduled event will not be affected. The followup events will be scheduled
+ // with the new timeout
+ mPenalizedTimeoutMs = getPenaltyTimeoutMs(carrierConfig);
+
+ for (NetworkMetricMonitor monitor : mMetricMonitors) {
+ monitor.setCarrierConfig(carrierConfig);
+ }
+ }
+
+ /** Update the inbound IpSecTransform applied to the network */
+ public void setInboundTransform(@NonNull IpSecTransform transform) {
+ if (!mIsSelected) {
+ logWtf("setInboundTransform on an unselected evaluator");
+ return;
+ }
+
+ for (NetworkMetricMonitor monitor : mMetricMonitors) {
+ monitor.setInboundTransform(transform);
+ }
+ }
+
+ /** Close the evaluator and stop all the underlying network metric monitors */
+ public void close() {
+ mHandler.removeCallbacksAndEqualMessages(mCancellationToken);
+
+ for (NetworkMetricMonitor monitor : mMetricMonitors) {
+ monitor.close();
+ }
+ }
+
+ /** Return whether this network evaluator is valid */
+ public boolean isValid() {
+ return mNetworkRecordBuilder.isValid();
+ }
+
+ /** Return the network */
+ public Network getNetwork() {
+ return mNetworkRecordBuilder.getNetwork();
+ }
+
+ /** Return the network record */
+ public UnderlyingNetworkRecord getNetworkRecord() {
+ return mNetworkRecordBuilder.build();
+ }
+
+ /** Return the priority class for network selection */
+ public int getPriorityClass() {
+ return mPriorityClass;
+ }
+
+ /** Return whether the network is being penalized */
+ public boolean isPenalized() {
+ return mIsPenalized;
+ }
+
+ /** Dump the information of this instance */
+ public void dump(IndentingPrintWriter pw) {
+ pw.println("UnderlyingNetworkEvaluator:");
+ pw.increaseIndent();
+
+ if (mNetworkRecordBuilder.isValid()) {
+ getNetworkRecord().dump(pw);
+ } else {
+ pw.println(
+ "UnderlyingNetworkRecord incomplete: mNetwork: "
+ + mNetworkRecordBuilder.getNetwork());
+ }
+
+ pw.println("mIsSelected: " + mIsSelected);
+ pw.println("mPriorityClass: " + mPriorityClass);
+ pw.println("mIsPenalized: " + mIsPenalized);
+
+ pw.decreaseIndent();
+ }
+
+ private String getLogPrefix() {
+ return "[Network " + mNetworkRecordBuilder.getNetwork() + "] ";
+ }
+
+ private void logInfo(String msg) {
+ Slog.i(TAG, getLogPrefix() + msg);
+ LOCAL_LOG.log("[INFO ] " + TAG + getLogPrefix() + msg);
+ }
+
+ private void logWtf(String msg) {
+ Slog.wtf(TAG, getLogPrefix() + msg);
+ LOCAL_LOG.log("[WTF ] " + TAG + getLogPrefix() + msg);
+ }
+}
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
index aea9f4d..7ab8e55 100644
--- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
@@ -16,24 +16,17 @@
package com.android.server.vcn.routeselection;
-import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.vcn.VcnUnderlyingNetworkTemplate;
-import android.os.ParcelUuid;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
-import com.android.server.vcn.VcnContext;
-import java.util.Comparator;
-import java.util.List;
import java.util.Objects;
/**
@@ -46,54 +39,17 @@
@NonNull public final NetworkCapabilities networkCapabilities;
@NonNull public final LinkProperties linkProperties;
public final boolean isBlocked;
- public final boolean isSelected;
- public final int priorityClass;
@VisibleForTesting(visibility = Visibility.PRIVATE)
public UnderlyingNetworkRecord(
@NonNull Network network,
@NonNull NetworkCapabilities networkCapabilities,
@NonNull LinkProperties linkProperties,
- boolean isBlocked,
- VcnContext vcnContext,
- List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
- ParcelUuid subscriptionGroup,
- TelephonySubscriptionSnapshot snapshot,
- UnderlyingNetworkRecord currentlySelected,
- PersistableBundleWrapper carrierConfig) {
+ boolean isBlocked) {
this.network = network;
this.networkCapabilities = networkCapabilities;
this.linkProperties = linkProperties;
this.isBlocked = isBlocked;
-
- this.isSelected = isSelected(this.network, currentlySelected);
-
- priorityClass =
- NetworkPriorityClassifier.calculatePriorityClass(
- vcnContext,
- this,
- underlyingNetworkTemplates,
- subscriptionGroup,
- snapshot,
- currentlySelected,
- carrierConfig);
- }
-
- @VisibleForTesting(visibility = Visibility.PRIVATE)
- public UnderlyingNetworkRecord(
- @NonNull Network network,
- @NonNull NetworkCapabilities networkCapabilities,
- @NonNull LinkProperties linkProperties,
- boolean isBlocked,
- boolean isSelected,
- int priorityClass) {
- this.network = network;
- this.networkCapabilities = networkCapabilities;
- this.linkProperties = linkProperties;
- this.isBlocked = isBlocked;
- this.isSelected = isSelected;
-
- this.priorityClass = priorityClass;
}
@Override
@@ -113,64 +69,20 @@
return Objects.hash(network, networkCapabilities, linkProperties, isBlocked);
}
- /** Returns if two records are equal including their priority classes. */
- public static boolean isEqualIncludingPriorities(
- UnderlyingNetworkRecord left, UnderlyingNetworkRecord right) {
- if (left != null && right != null) {
- return left.equals(right)
- && left.isSelected == right.isSelected
- && left.priorityClass == right.priorityClass;
- }
-
- return left == right;
- }
-
- static Comparator<UnderlyingNetworkRecord> getComparator() {
- return (left, right) -> {
- final int leftIndex = left.priorityClass;
- final int rightIndex = right.priorityClass;
-
- // In the case of networks in the same priority class, prioritize based on other
- // criteria (eg. actively selected network, link metrics, etc)
- if (leftIndex == rightIndex) {
- // TODO: Improve the strategy of network selection when both UnderlyingNetworkRecord
- // fall into the same priority class.
- if (left.isSelected) {
- return -1;
- }
- if (right.isSelected) {
- return 1;
- }
- }
- return Integer.compare(leftIndex, rightIndex);
- };
- }
-
- private static boolean isSelected(
- Network networkToCheck, UnderlyingNetworkRecord currentlySelected) {
- if (currentlySelected == null) {
- return false;
- }
- if (currentlySelected.network.equals(networkToCheck)) {
- return true;
- }
- return false;
+ /** Return whether two records represent the same network */
+ public static boolean isSameNetwork(
+ @Nullable UnderlyingNetworkRecord leftRecord,
+ @Nullable UnderlyingNetworkRecord rightRecord) {
+ final Network left = leftRecord == null ? null : leftRecord.network;
+ final Network right = rightRecord == null ? null : rightRecord.network;
+ return Objects.equals(left, right);
}
/** Dumps the state of this record for logging and debugging purposes. */
- void dump(
- VcnContext vcnContext,
- IndentingPrintWriter pw,
- List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
- ParcelUuid subscriptionGroup,
- TelephonySubscriptionSnapshot snapshot,
- UnderlyingNetworkRecord currentlySelected,
- PersistableBundleWrapper carrierConfig) {
+ void dump(IndentingPrintWriter pw) {
pw.println("UnderlyingNetworkRecord:");
pw.increaseIndent();
- pw.println("priorityClass: " + priorityClass);
- pw.println("isSelected: " + isSelected);
pw.println("mNetwork: " + network);
pw.println("mNetworkCapabilities: " + networkCapabilities);
pw.println("mLinkProperties: " + linkProperties);
@@ -218,29 +130,14 @@
return mNetworkCapabilities != null && mLinkProperties != null && mWasIsBlockedSet;
}
- UnderlyingNetworkRecord build(
- VcnContext vcnContext,
- List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
- ParcelUuid subscriptionGroup,
- TelephonySubscriptionSnapshot snapshot,
- UnderlyingNetworkRecord currentlySelected,
- PersistableBundleWrapper carrierConfig) {
+ UnderlyingNetworkRecord build() {
if (!isValid()) {
throw new IllegalArgumentException(
"Called build before UnderlyingNetworkRecord was valid");
}
return new UnderlyingNetworkRecord(
- mNetwork,
- mNetworkCapabilities,
- mLinkProperties,
- mIsBlocked,
- vcnContext,
- underlyingNetworkTemplates,
- subscriptionGroup,
- snapshot,
- currentlySelected,
- carrierConfig);
+ mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
}
}
}
diff --git a/services/core/java/com/android/server/wearable/OWNERS b/services/core/java/com/android/server/wearable/OWNERS
index 073e2d7..eca48b7 100644
--- a/services/core/java/com/android/server/wearable/OWNERS
+++ b/services/core/java/com/android/server/wearable/OWNERS
@@ -1,3 +1 @@
-charliewang@google.com
-oni@google.com
-volnov@google.com
\ No newline at end of file
+include /core/java/android/app/wearable/OWNERS
\ No newline at end of file
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index cd70447..e06f215 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -17,6 +17,7 @@
rgl@google.com
yunfanc@google.com
wilsonshih@google.com
+jiamingliu@google.com
# Files related to background activity launches
per-file Background*Start* = set noparent
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index e51afbe..0bc60cd 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4708,6 +4708,7 @@
}
if (top.isAttached()) {
top.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+ top.mWaitForEnteringPinnedMode = false;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowList.java b/services/core/java/com/android/server/wm/WindowList.java
index dfeba40..1e888f5 100644
--- a/services/core/java/com/android/server/wm/WindowList.java
+++ b/services/core/java/com/android/server/wm/WindowList.java
@@ -24,7 +24,7 @@
*/
class WindowList<E> extends ArrayList<E> {
- void addFirst(E e) {
+ public void addFirst(E e) {
add(0, e);
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 9375b29..ecdf09f 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -2016,6 +2016,11 @@
ownerTask.addChild(taskFragment, position);
taskFragment.setWindowingMode(creationParams.getWindowingMode());
if (!creationParams.getInitialRelativeBounds().isEmpty()) {
+ // The surface operations for the task fragment should sync with the transition.
+ // This avoid using pending transaction before collectExistenceChange is called.
+ if (transition != null) {
+ addToSyncSet(transition.getSyncId(), taskFragment);
+ }
// Set relative bounds instead of using setBounds. This will avoid unnecessary update in
// case the parent has resized since the last time parent info is sent to the organizer.
taskFragment.setRelativeEmbeddedBounds(creationParams.getInitialRelativeBounds());
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 8cd55c7..1f6f4f3 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -77,6 +77,7 @@
"onload.cpp",
":lib_cachedAppOptimizer_native",
":lib_gameManagerService_native",
+ ":lib_oomConnection_native",
],
include_dirs: [
@@ -118,6 +119,7 @@
"libhardware_legacy",
"libhidlbase",
"libmeminfo",
+ "libmemevents",
"libmemtrackproxy",
"libmtp",
"libnativehelper",
@@ -235,3 +237,8 @@
"com_android_server_app_GameManagerService.cpp",
],
}
+
+filegroup {
+ name: "lib_oomConnection_native",
+ srcs: ["com_android_server_am_OomConnection.cpp"],
+}
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index fd9d4a4..e37d9a1 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -30,5 +30,8 @@
per-file com_android_server_am_CachedAppOptimizer.cpp = timmurray@google.com, edgararriaga@google.com, dualli@google.com, carmenjackson@google.com, philipcuadra@google.com
per-file com_android_server_companion_virtual_InputController.cpp = file:/services/companion/java/com/android/server/companion/virtual/OWNERS
-# Bug component : 158088 = per-file com_android_server_utils_AnrTimer*.java
-per-file com_android_server_utils_AnrTimer*.java = file:/PERFORMANCE_OWNERS
+# Memory
+per-file com_android_server_am_OomConnection.cpp = file:/MEMORY_OWNERS
+
+# Bug component : 158088 = per-file *AnrTimer*
+per-file *AnrTimer* = file:/PERFORMANCE_OWNERS
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 98482b8..c5b379b 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -565,8 +565,8 @@
}
static jboolean com_android_server_am_CachedAppOptimizer_isFreezerProfileValid(JNIEnv* env) {
- int uid = getuid();
- int pid = getpid();
+ uid_t uid = getuid();
+ pid_t pid = getpid();
return isProfileValidForProcess("Frozen", uid, pid) &&
isProfileValidForProcess("Unfrozen", uid, pid);
diff --git a/services/core/jni/com_android_server_am_OomConnection.cpp b/services/core/jni/com_android_server_am_OomConnection.cpp
new file mode 100644
index 0000000..49a3ad3
--- /dev/null
+++ b/services/core/jni/com_android_server_am_OomConnection.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "OomConnection"
+
+#include <core_jni_helpers.h>
+#include <jni.h>
+#include <memevents/memevents.h>
+
+namespace android {
+
+using namespace ::android::bpf::memevents;
+
+// Used to cache the results of the JNI name lookup
+static struct {
+ jclass clazz;
+ jmethodID ctor;
+} sOomKillRecordInfo;
+
+static MemEventListener memevent_listener(MemEventClient::AMS);
+
+/**
+ * Initialize listening and waiting for new out-of-memory (OOM) events to occur.
+ * Once a OOM event is detected, we then fetch the list of OOM kills, and return
+ * a corresponding java array with the information gathered.
+ *
+ * In the case that we encounter an error, we make sure to close the epfd, and
+ * the OOM file descriptor, by calling `deregisterAllEvents()`.
+ *
+ * @return list of `android.os.OomKillRecord`
+ * @throws java.lang.RuntimeException
+ */
+static jobjectArray android_server_am_OomConnection_waitOom(JNIEnv* env, jobject) {
+ if (!memevent_listener.registerEvent(MEM_EVENT_OOM_KILL)) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "listener failed to register to OOM events");
+ return nullptr;
+ }
+
+ if (!memevent_listener.listen()) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "listener failed waiting for OOM event");
+ return nullptr;
+ }
+
+ std::vector<mem_event_t> oom_events;
+ if (!memevent_listener.getMemEvents(oom_events)) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "Failed to get OOM events");
+ return nullptr;
+ }
+
+ jobjectArray java_oom_array =
+ env->NewObjectArray(oom_events.size(), sOomKillRecordInfo.clazz, nullptr);
+ if (java_oom_array == NULL) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "Failed to create OomKillRecord array");
+ return nullptr;
+ }
+
+ for (int i = 0; i < oom_events.size(); i++) {
+ const mem_event_t mem_event = oom_events[i];
+ if (mem_event.type != MEM_EVENT_OOM_KILL) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "Received invalid memory event");
+ return java_oom_array;
+ }
+
+ const auto oom_kill = mem_event.event_data.oom_kill;
+
+ jstring process_name = env->NewStringUTF(oom_kill.process_name);
+ if (process_name == NULL) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "Failed creating java string for process name");
+ }
+ jobject java_oom_kill = env->NewObject(sOomKillRecordInfo.clazz, sOomKillRecordInfo.ctor,
+ oom_kill.timestamp_ms, oom_kill.pid, oom_kill.uid,
+ process_name, oom_kill.oom_score_adj);
+ if (java_oom_kill == NULL) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "Failed to create OomKillRecord object");
+ return java_oom_array;
+ }
+ env->SetObjectArrayElement(java_oom_array, i, java_oom_kill);
+ }
+ return java_oom_array;
+}
+
+static const JNINativeMethod sOomConnectionMethods[] = {
+ /* name, signature, funcPtr */
+ {"waitOom", "()[Landroid/os/OomKillRecord;",
+ (void*)android_server_am_OomConnection_waitOom},
+};
+
+int register_android_server_am_OomConnection(JNIEnv* env) {
+ sOomKillRecordInfo.clazz = FindClassOrDie(env, "android/os/OomKillRecord");
+ sOomKillRecordInfo.clazz = MakeGlobalRefOrDie(env, sOomKillRecordInfo.clazz);
+
+ sOomKillRecordInfo.ctor =
+ GetMethodIDOrDie(env, sOomKillRecordInfo.clazz, "<init>", "(JIILjava/lang/String;S)V");
+
+ return RegisterMethodsOrDie(env, "com/android/server/am/OomConnection", sOomConnectionMethods,
+ NELEM(sOomConnectionMethods));
+}
+} // namespace android
\ No newline at end of file
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 9d39165..0af8169 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -290,6 +290,7 @@
void setInputDispatchMode(bool enabled, bool frozen);
void setSystemUiLightsOut(bool lightsOut);
void setPointerDisplayId(int32_t displayId);
+ int32_t getMousePointerSpeed();
void setPointerSpeed(int32_t speed);
void setPointerAcceleration(float acceleration);
void setTouchpadPointerSpeed(int32_t speed);
@@ -1096,6 +1097,11 @@
InputReaderConfiguration::Change::DISPLAY_INFO);
}
+int32_t NativeInputManager::getMousePointerSpeed() {
+ std::scoped_lock _l(mLock);
+ return mLocked.pointerSpeed;
+}
+
void NativeInputManager::setPointerSpeed(int32_t speed) {
{ // acquire lock
std::scoped_lock _l(mLock);
@@ -2037,6 +2043,12 @@
}
}
+static jint nativeGetMousePointerSpeed(JNIEnv* env, jobject nativeImplObj) {
+ NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
+
+ return static_cast<jint>(im->getMousePointerSpeed());
+}
+
static void nativeSetPointerSpeed(JNIEnv* env, jobject nativeImplObj, jint speed) {
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
@@ -2633,6 +2645,7 @@
{"transferTouchFocus", "(Landroid/os/IBinder;Landroid/os/IBinder;Z)Z",
(void*)nativeTransferTouchFocus},
{"transferTouch", "(Landroid/os/IBinder;I)Z", (void*)nativeTransferTouch},
+ {"getMousePointerSpeed", "()I", (void*)nativeGetMousePointerSpeed},
{"setPointerSpeed", "(I)V", (void*)nativeSetPointerSpeed},
{"setPointerAcceleration", "(F)V", (void*)nativeSetPointerAcceleration},
{"setTouchpadPointerSpeed", "(I)V", (void*)nativeSetTouchpadPointerSpeed},
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index a87902f..cf0c55d 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -51,6 +51,7 @@
int register_android_server_HardwarePropertiesManagerService(JNIEnv* env);
int register_android_server_SyntheticPasswordManager(JNIEnv* env);
int register_android_hardware_display_DisplayViewport(JNIEnv* env);
+int register_android_server_am_OomConnection(JNIEnv* env);
int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
int register_android_server_am_LowMemDetector(JNIEnv* env);
int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(JNIEnv* env);
@@ -110,6 +111,7 @@
register_android_server_storage_AppFuse(env);
register_android_server_SyntheticPasswordManager(env);
register_android_hardware_display_DisplayViewport(env);
+ register_android_server_am_OomConnection(env);
register_android_server_am_CachedAppOptimizer(env);
register_android_server_am_LowMemDetector(env);
register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2c3f846..aab14ad 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -71,6 +71,7 @@
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_THREAD_NETWORK;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_TIME;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER;
@@ -13834,6 +13835,11 @@
UserManager.DISALLOW_SMS, new String[]{MANAGE_DEVICE_POLICY_SMS});
USER_RESTRICTION_PERMISSIONS.put(
UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS, new String[]{MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS});
+ if (com.android.net.thread.platform.flags.Flags.threadUserRestrictionEnabled()) {
+ USER_RESTRICTION_PERMISSIONS.put(
+ UserManager.DISALLOW_THREAD_NETWORK,
+ new String[]{MANAGE_DEVICE_POLICY_THREAD_NETWORK});
+ }
USER_RESTRICTION_PERMISSIONS.put(
UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO, new String[]{MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION});
USER_RESTRICTION_PERMISSIONS.put(
diff --git a/services/incremental/OWNERS b/services/incremental/OWNERS
index 7ebb962..c18a9e5 100644
--- a/services/incremental/OWNERS
+++ b/services/incremental/OWNERS
@@ -1,8 +1,4 @@
# Bug component: 554432
-include /services/core/java/com/android/server/pm/OWNERS
+include /PACKAGE_MANAGER_OWNERS
-alexbuy@google.com
-schfan@google.com
-toddke@google.com
-zyy@google.com
-patb@google.com
+zyy@google.com
\ No newline at end of file
diff --git a/services/java/com/android/server/SystemConfigService.java b/services/java/com/android/server/SystemConfigService.java
index 6e82907..fd21a32 100644
--- a/services/java/com/android/server/SystemConfigService.java
+++ b/services/java/com/android/server/SystemConfigService.java
@@ -21,6 +21,8 @@
import android.Manifest;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManagerInternal;
+import android.os.Binder;
import android.os.ISystemConfig;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -108,6 +110,15 @@
"Caller must hold " + Manifest.permission.QUERY_ALL_PACKAGES);
return new ArrayList<>(SystemConfig.getInstance().getDefaultVrComponents());
}
+
+ @Override
+ public List<String> getPreventUserDisablePackages() {
+ PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+ return SystemConfig.getInstance().getPreventUserDisablePackages().stream()
+ .filter(preventUserDisablePackage ->
+ pmi.canQueryPackage(Binder.getCallingUid(), preventUserDisablePackage))
+ .collect(toList());
+ }
};
public SystemConfigService(Context context) {
diff --git a/services/profcollect/Android.bp b/services/profcollect/Android.bp
index 2040bb6..fe431f5 100644
--- a/services/profcollect/Android.bp
+++ b/services/profcollect/Android.bp
@@ -22,24 +22,25 @@
}
filegroup {
- name: "services.profcollect-javasources",
- srcs: ["src/**/*.java"],
- path: "src",
- visibility: ["//frameworks/base/services"],
+ name: "services.profcollect-javasources",
+ srcs: ["src/**/*.java"],
+ path: "src",
+ visibility: ["//frameworks/base/services"],
}
filegroup {
- name: "services.profcollect-sources",
- srcs: [
- ":services.profcollect-javasources",
- ":profcollectd_aidl",
- ],
- visibility: ["//frameworks/base/services:__subpackages__"],
+ name: "services.profcollect-sources",
+ srcs: [
+ ":services.profcollect-javasources",
+ ":profcollectd_aidl",
+ ],
+ visibility: ["//frameworks/base/services:__subpackages__"],
}
java_library_static {
- name: "services.profcollect",
- defaults: ["platform_service_defaults"],
- srcs: [":services.profcollect-sources"],
- libs: ["services.core"],
+ name: "services.profcollect",
+ defaults: ["platform_service_defaults"],
+ srcs: [":services.profcollect-sources"],
+ static_libs: ["services.core"],
+ libs: ["service-art.stubs.system_server"],
}
diff --git a/services/profcollect/OWNERS b/services/profcollect/OWNERS
index b380e39..be9e61f 100644
--- a/services/profcollect/OWNERS
+++ b/services/profcollect/OWNERS
@@ -1,3 +1 @@
-srhines@google.com
-yabinc@google.com
-yikong@google.com
+include platform/prebuilts/clang/host/linux-x86:/OWNERS
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 4007672..68038fa 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -41,8 +41,10 @@
import com.android.internal.R;
import com.android.internal.os.BackgroundThread;
import com.android.server.IoThread;
+import com.android.server.LocalManagerRegistry;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.art.ArtManagerLocal;
import com.android.server.wm.ActivityMetricsLaunchObserver;
import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -59,7 +61,7 @@
private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
private static final String INTENT_UPLOAD_PROFILES =
"com.android.server.profcollect.UPLOAD_PROFILES";
- private static final long BG_PROCESS_PERIOD = TimeUnit.HOURS.toMillis(4); // every 4 hours.
+ private static final long BG_PROCESS_INTERVAL = TimeUnit.HOURS.toMillis(4); // every 4 hours.
private IProfCollectd mIProfcollect;
private static ProfcollectForwardingService sSelfService;
@@ -223,7 +225,7 @@
js.schedule(new JobInfo.Builder(JOB_IDLE_PROCESS, JOB_SERVICE_NAME)
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
- .setPeriodic(BG_PROCESS_PERIOD)
+ .setPeriodic(BG_PROCESS_INTERVAL)
.setPriority(JobInfo.PRIORITY_MIN)
.build());
}
@@ -261,6 +263,7 @@
BackgroundThread.get().getThreadHandler().post(
() -> {
registerAppLaunchObserver();
+ registerDex2oatObserver();
registerOTAObserver();
});
}
@@ -304,6 +307,44 @@
}
}
+ private void registerDex2oatObserver() {
+ ArtManagerLocal aml = LocalManagerRegistry.getManager(ArtManagerLocal.class);
+ if (aml == null) {
+ Log.w(LOG_TAG, "Couldn't get ArtManagerLocal");
+ return;
+ }
+ aml.setBatchDexoptStartCallback(Runnable::run,
+ (snapshot, reason, defaultPackages, builder, passedSignal) -> {
+ traceOnDex2oatStart();
+ });
+ }
+
+ private void traceOnDex2oatStart() {
+ if (mIProfcollect == null) {
+ return;
+ }
+ // Sample for a fraction of dex2oat runs.
+ final int traceFrequency =
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
+ "dex2oat_trace_freq", 25);
+ int randomNum = ThreadLocalRandom.current().nextInt(100);
+ if (randomNum < traceFrequency) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Tracing on dex2oat event");
+ }
+ BackgroundThread.get().getThreadHandler().post(() -> {
+ try {
+ // Dex2oat could take a while before it starts. Add a short delay before start
+ // tracing.
+ Thread.sleep(1000);
+ mIProfcollect.trace_once("dex2oat");
+ } catch (RemoteException | InterruptedException e) {
+ Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage());
+ }
+ });
+ }
+ }
+
private void registerOTAObserver() {
UpdateEngine updateEngine = new UpdateEngine();
updateEngine.bind(new UpdateEngineCallback() {
diff --git a/services/robotests/Android.bp b/services/robotests/Android.bp
index 52eae21..a70802a 100644
--- a/services/robotests/Android.bp
+++ b/services/robotests/Android.bp
@@ -57,9 +57,13 @@
],
static_libs: [
"androidx.test.ext.truth",
+ "Settings-robo-testutils",
+ "SettingsLib-robo-testutils",
],
instrumentation_for: "FrameworksServicesLib",
+
+ upstream: true,
}
filegroup {
diff --git a/services/robotests/backup/Android.bp b/services/robotests/backup/Android.bp
index 66ee696..fba2cad 100644
--- a/services/robotests/backup/Android.bp
+++ b/services/robotests/backup/Android.bp
@@ -56,6 +56,8 @@
// Include the testing libraries
libs: [
"mockito-robolectric-prebuilt",
+ "Settings-robo-testutils",
+ "SettingsLib-robo-testutils",
"platform-test-annotations",
"testng",
"truth",
@@ -63,4 +65,6 @@
instrumentation_for: "BackupFrameworksServicesLib",
+ upstream: true,
+
}
diff --git a/services/robotests/backup/config/robolectric.properties b/services/robotests/backup/config/robolectric.properties
index 850557a..1ebf6d4 100644
--- a/services/robotests/backup/config/robolectric.properties
+++ b/services/robotests/backup/config/robolectric.properties
@@ -1 +1,3 @@
-sdk=NEWEST_SDK
\ No newline at end of file
+sdk=NEWEST_SDK
+looperMode=LEGACY
+shadows=com.android.server.testing.shadows.FrameworkShadowLooper
diff --git a/services/robotests/backup/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java b/services/robotests/backup/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
index ee5a534..6839a06 100644
--- a/services/robotests/backup/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
@@ -57,6 +57,7 @@
ShadowBackupDataOutput.class,
ShadowEnvironment.class,
ShadowFullBackup.class,
+ ShadowSigningInfo.class,
})
public class AppMetadataBackupWriterTest {
private static final String TEST_PACKAGE = "com.test.package";
diff --git a/services/robotests/backup/src/com/android/server/backup/fullbackup/ShadowSigningInfo.java b/services/robotests/backup/src/com/android/server/backup/fullbackup/ShadowSigningInfo.java
new file mode 100644
index 0000000..53d807c
--- /dev/null
+++ b/services/robotests/backup/src/com/android/server/backup/fullbackup/ShadowSigningInfo.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.fullbackup;
+
+import static android.os.Build.VERSION_CODES.P;
+
+import android.content.pm.SigningInfo;
+
+import org.robolectric.annotation.Implements;
+
+@Implements(value = SigningInfo.class, minSdk = P)
+public class ShadowSigningInfo {
+}
diff --git a/services/robotests/src/com/android/server/location/gnss/NtpNetworkTimeHelperTest.java b/services/robotests/src/com/android/server/location/gnss/NtpNetworkTimeHelperTest.java
index 4949091..0092763 100644
--- a/services/robotests/src/com/android/server/location/gnss/NtpNetworkTimeHelperTest.java
+++ b/services/robotests/src/com/android/server/location/gnss/NtpNetworkTimeHelperTest.java
@@ -35,6 +35,7 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.LooperMode;
import org.robolectric.shadows.ShadowLooper;
import java.util.concurrent.CountDownLatch;
@@ -45,6 +46,7 @@
*/
@RunWith(RobolectricTestRunner.class)
@Presubmit
+@LooperMode(LooperMode.Mode.LEGACY)
public class NtpNetworkTimeHelperTest {
private static final long MOCK_NTP_TIME = 1519930775453L;
diff --git a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
index 16d16cd..3681bd4 100644
--- a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
+++ b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
@@ -21,12 +21,15 @@
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
+import org.robolectric.shadows.LooperShadowPicker;
+import org.robolectric.shadows.ShadowLegacyLooper;
import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.ShadowPausedLooper;
import java.util.Optional;
-@Implements(value = Looper.class)
-public class FrameworkShadowLooper extends ShadowLooper {
+@Implements(value = Looper.class, shadowPicker = FrameworkShadowLooper.Picker.class)
+public class FrameworkShadowLooper extends ShadowLegacyLooper {
@RealObject private Looper mLooper;
private Optional<Boolean> mIsCurrentThread = Optional.empty();
@@ -45,4 +48,10 @@
}
return Thread.currentThread() == mLooper.getThread();
}
+
+ public static class Picker extends LooperShadowPicker<ShadowLooper> {
+ public Picker() {
+ super(FrameworkShadowLooper.class, ShadowPausedLooper.class);
+ }
+ }
}
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
index 4a99486..1da6759 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
@@ -95,7 +95,6 @@
sPackageAppEnabledStates.put(packageName, Integer.valueOf(newState)); // flags unused here.
}
- @Override
protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
throws NameNotFoundException {
if (!sPackageInfos.containsKey(packageName)) {
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 528fda2..0af45ec 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_input_method_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/Android.bp b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/Android.bp
index e1fd2b3..8a12dcd 100644
--- a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_input_method_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/services/tests/PackageManagerComponentOverrideTests/Android.bp b/services/tests/PackageManagerComponentOverrideTests/Android.bp
index 81fd90d..1227b0c 100644
--- a/services/tests/PackageManagerComponentOverrideTests/Android.bp
+++ b/services/tests/PackageManagerComponentOverrideTests/Android.bp
@@ -18,6 +18,7 @@
// and this is more representative of a real caller. It also uses Mockito extended, and this
// prevents converting the entire services test module.
package {
+ default_team: "trendy_team_framework_android_packages",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
index ad7af44..f15e533 100644
--- a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
+++ b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_framework_android_packages",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/Android.bp b/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/Android.bp
index 9921106..6da503d 100644
--- a/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/Android.bp
+++ b/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_framework_android_packages",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index 47d2422..84ff891 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -3,6 +3,7 @@
//########################################################################
package {
+ default_team: "trendy_team_framework_android_packages",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java
index e5be4d9..9e11fa2 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java
@@ -50,7 +50,7 @@
import java.util.Arrays;
import java.util.Collections;
-// atest PackageManagerServiceTest:com.android.server.pm.UserDataPreparerTest
+// atest PackageManagerServiceServerTests:com.android.server.pm.UserDataPreparerTest
@RunWith(AndroidJUnit4.class)
@Presubmit
@SmallTest
@@ -99,7 +99,7 @@
systemDeDir.mkdirs();
mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_DE);
verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
- eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE));
+ eq(StorageManager.FLAG_STORAGE_DE));
verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID),
eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE));
int serialNumber = UserDataPreparer.getSerialNumber(userDeDir);
@@ -116,7 +116,7 @@
systemCeDir.mkdirs();
mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE);
verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
- eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE));
+ eq(StorageManager.FLAG_STORAGE_CE));
verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID),
eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE));
int serialNumber = UserDataPreparer.getSerialNumber(userCeDir);
@@ -129,7 +129,7 @@
public void testPrepareUserData_forNewUser_destroysOnFailure() throws Exception {
TEST_USER.lastLoggedInTime = 0;
doThrow(new IllegalStateException("expected exception for test")).when(mStorageManagerMock)
- .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), eq(TEST_USER_SERIAL),
+ .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
eq(StorageManager.FLAG_STORAGE_CE));
mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE);
verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID),
@@ -140,7 +140,7 @@
public void testPrepareUserData_forExistingUser_doesNotDestroyOnFailure() throws Exception {
TEST_USER.lastLoggedInTime = System.currentTimeMillis();
doThrow(new IllegalStateException("expected exception for test")).when(mStorageManagerMock)
- .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), eq(TEST_USER_SERIAL),
+ .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
eq(StorageManager.FLAG_STORAGE_CE));
mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE);
verify(mStorageManagerMock, never()).destroyUserStorage(isNull(String.class),
diff --git a/services/tests/PackageManagerServiceTests/unit/Android.bp b/services/tests/PackageManagerServiceTests/unit/Android.bp
index 85059838..c93f482 100644
--- a/services/tests/PackageManagerServiceTests/unit/Android.bp
+++ b/services/tests/PackageManagerServiceTests/unit/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_framework_android_packages",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index f56f290..cd18918 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -53,6 +53,7 @@
"mockito-target-extended-minus-junit4",
"platform-compat-test-rules",
"platform-test-annotations",
+ "PlatformProperties",
"service-blobstore",
"service-jobscheduler",
"service-permission.impl",
@@ -71,6 +72,7 @@
// TODO: remove once Android migrates to JUnit 4.12, which provides assertThrows
"testng",
"compatibility-device-util-axt",
+ "flag-junit",
],
libs: [
diff --git a/services/tests/mockingservicestests/jni/Android.bp b/services/tests/mockingservicestests/jni/Android.bp
index f1dc1fa..1eb9888 100644
--- a/services/tests/mockingservicestests/jni/Android.bp
+++ b/services/tests/mockingservicestests/jni/Android.bp
@@ -22,6 +22,7 @@
srcs: [
":lib_cachedAppOptimizer_native",
":lib_gameManagerService_native",
+ ":lib_oomConnection_native",
"onload.cpp",
],
@@ -42,6 +43,7 @@
"libgui",
"libhidlbase",
"liblog",
+ "libmemevents",
"libmeminfo",
"libnativehelper",
"libprocessgroup",
diff --git a/services/tests/mockingservicestests/jni/onload.cpp b/services/tests/mockingservicestests/jni/onload.cpp
index 23ccb22..fb91051 100644
--- a/services/tests/mockingservicestests/jni/onload.cpp
+++ b/services/tests/mockingservicestests/jni/onload.cpp
@@ -26,6 +26,7 @@
namespace android {
int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
int register_android_server_app_GameManagerService(JNIEnv* env);
+int register_android_server_am_OomConnection(JNIEnv* env);
};
using namespace android;
@@ -42,6 +43,7 @@
ALOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_am_CachedAppOptimizer(env);
register_android_server_app_GameManagerService(env);
+ register_android_server_am_OomConnection(env);
return JNI_VERSION_1_4;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/OWNERS b/services/tests/mockingservicestests/src/com/android/server/OWNERS
index c0f0ce04..f801560 100644
--- a/services/tests/mockingservicestests/src/com/android/server/OWNERS
+++ b/services/tests/mockingservicestests/src/com/android/server/OWNERS
@@ -1,3 +1,5 @@
per-file *Alarm* = file:/apex/jobscheduler/OWNERS
per-file *AppStateTracker* = file:/apex/jobscheduler/OWNERS
per-file *DeviceIdleController* = file:/apex/jobscheduler/OWNERS
+per-file SensitiveContentProtectionManagerServiceTest.java = file:/core/java/android/permission/OWNERS
+per-file RescuePartyTest.java = file:/packages/CrashRecovery/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 7b771af..211a83d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -33,6 +33,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import android.content.ContentResolver;
@@ -63,6 +64,7 @@
import org.mockito.quality.Strictness;
import org.mockito.stubbing.Answer;
+import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -95,12 +97,12 @@
"persist.device_config.configuration.disable_rescue_party";
private static final String PROP_DISABLE_FACTORY_RESET_FLAG =
"persist.device_config.configuration.disable_rescue_party_factory_reset";
- private static final String PROP_LAST_FACTORY_RESET_TIME_MS = "persist.sys.last_factory_reset";
private static final int THROTTLING_DURATION_MIN = 10;
private MockitoSession mSession;
private HashMap<String, String> mSystemSettingsMap;
+ private HashMap<String, String> mCrashRecoveryPropertiesMap;
//Records the namespaces wiped by setProperties().
private HashSet<String> mNamespacesWiped;
@@ -113,6 +115,9 @@
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PackageManager mPackageManager;
+ // Mock only sysprop apis
+ private PackageWatchdog.BootThreshold mSpyBootThreshold;
+
@Captor
private ArgumentCaptor<DeviceConfig.MonitorCallback> mMonitorCallbackCaptor;
@Captor
@@ -208,10 +213,11 @@
// Mock PackageWatchdog
doAnswer((Answer<PackageWatchdog>) invocationOnMock -> mMockPackageWatchdog)
.when(() -> PackageWatchdog.getInstance(mMockContext));
+ mockCrashRecoveryProperties(mMockPackageWatchdog);
doReturn(CURRENT_NETWORK_TIME_MILLIS).when(() -> RescueParty.getElapsedRealtime());
- SystemProperties.set(RescueParty.PROP_RESCUE_BOOT_COUNT, Integer.toString(0));
+ setCrashRecoveryPropRescueBootCount(0);
SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(true));
SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(false));
}
@@ -255,7 +261,7 @@
noteBoot(4);
assertTrue(RescueParty.isRebootPropertySet());
- SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
+ setCrashRecoveryPropAttemptingReboot(false);
noteBoot(5);
assertTrue(RescueParty.isFactoryResetPropertySet());
}
@@ -280,7 +286,7 @@
noteAppCrash(4, true);
assertTrue(RescueParty.isRebootPropertySet());
- SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
+ setCrashRecoveryPropAttemptingReboot(false);
noteAppCrash(5, true);
assertTrue(RescueParty.isFactoryResetPropertySet());
}
@@ -438,7 +444,7 @@
noteBoot(i + 1);
}
assertFalse(RescueParty.isFactoryResetPropertySet());
- SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
+ setCrashRecoveryPropAttemptingReboot(false);
noteBoot(LEVEL_FACTORY_RESET + 1);
assertTrue(RescueParty.isAttemptingFactoryReset());
assertTrue(RescueParty.isFactoryResetPropertySet());
@@ -456,7 +462,7 @@
noteBoot(mitigationCount++);
assertFalse(RescueParty.isFactoryResetPropertySet());
noteBoot(mitigationCount++);
- SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
+ setCrashRecoveryPropAttemptingReboot(false);
noteBoot(mitigationCount + 1);
assertTrue(RescueParty.isAttemptingFactoryReset());
assertTrue(RescueParty.isFactoryResetPropertySet());
@@ -464,10 +470,10 @@
@Test
public void testThrottlingOnBootFailures() {
- SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
+ setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
- SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(beforeTimeout));
+ setCrashRecoveryPropLastFactoryReset(beforeTimeout);
for (int i = 1; i <= LEVEL_FACTORY_RESET; i++) {
noteBoot(i);
}
@@ -476,10 +482,10 @@
@Test
public void testThrottlingOnAppCrash() {
- SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
+ setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
- SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(beforeTimeout));
+ setCrashRecoveryPropLastFactoryReset(beforeTimeout);
for (int i = 0; i <= LEVEL_FACTORY_RESET; i++) {
noteAppCrash(i + 1, true);
}
@@ -488,10 +494,10 @@
@Test
public void testNotThrottlingAfterTimeoutOnBootFailures() {
- SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
+ setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
- SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(afterTimeout));
+ setCrashRecoveryPropLastFactoryReset(afterTimeout);
for (int i = 1; i <= LEVEL_FACTORY_RESET; i++) {
noteBoot(i);
}
@@ -499,10 +505,10 @@
}
@Test
public void testNotThrottlingAfterTimeoutOnAppCrash() {
- SystemProperties.set(RescueParty.PROP_ATTEMPTING_REBOOT, Boolean.toString(false));
+ setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
- SystemProperties.set(PROP_LAST_FACTORY_RESET_TIME_MS, Long.toString(afterTimeout));
+ setCrashRecoveryPropLastFactoryReset(afterTimeout);
for (int i = 0; i <= LEVEL_FACTORY_RESET; i++) {
noteAppCrash(i + 1, true);
}
@@ -753,4 +759,138 @@
RescuePartyObserver.getInstance(mMockContext).execute(new VersionedPackage(
packageName, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH, mitigationCount);
}
+
+ // Mock CrashRecoveryProperties as they cannot be accessed due to SEPolicy restrictions
+ private void mockCrashRecoveryProperties(PackageWatchdog watchdog) {
+ // mock properties in RescueParty
+ try {
+
+ doAnswer((Answer<Boolean>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.attempting_factory_reset", "false");
+ return Boolean.parseBoolean(storedValue);
+ }).when(() -> RescueParty.isFactoryResetPropertySet());
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ boolean value = invocationOnMock.getArgument(0);
+ mCrashRecoveryPropertiesMap.put("crashrecovery.attempting_factory_reset",
+ Boolean.toString(value));
+ return null;
+ }).when(() -> RescueParty.setFactoryResetProperty(anyBoolean()));
+
+ doAnswer((Answer<Boolean>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.attempting_reboot", "false");
+ return Boolean.parseBoolean(storedValue);
+ }).when(() -> RescueParty.isRebootPropertySet());
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ boolean value = invocationOnMock.getArgument(0);
+ setCrashRecoveryPropAttemptingReboot(value);
+ return null;
+ }).when(() -> RescueParty.setRebootProperty(anyBoolean()));
+
+ doAnswer((Answer<Long>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("persist.crashrecovery.last_factory_reset", "0");
+ return Long.parseLong(storedValue);
+ }).when(() -> RescueParty.getLastFactoryResetTimeMs());
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ long value = invocationOnMock.getArgument(0);
+ setCrashRecoveryPropLastFactoryReset(value);
+ return null;
+ }).when(() -> RescueParty.setLastFactoryResetTimeMs(anyLong()));
+
+ doAnswer((Answer<Integer>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.max_rescue_level_attempted", "0");
+ return Integer.parseInt(storedValue);
+ }).when(() -> RescueParty.getMaxRescueLevelAttempted());
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ int value = invocationOnMock.getArgument(0);
+ mCrashRecoveryPropertiesMap.put("crashrecovery.max_rescue_level_attempted",
+ Integer.toString(value));
+ return null;
+ }).when(() -> RescueParty.setMaxRescueLevelAttempted(anyInt()));
+
+ } catch (Exception e) {
+ // tests will fail, just printing the error
+ System.out.println("Error while mocking crashrecovery properties " + e.getMessage());
+ }
+
+ // mock properties in BootThreshold
+ try {
+ mSpyBootThreshold = spy(watchdog.new BootThreshold(
+ PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
+ PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
+ mCrashRecoveryPropertiesMap = new HashMap<>();
+
+ doAnswer((Answer<Integer>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.rescue_boot_count", "0");
+ return Integer.parseInt(storedValue);
+ }).when(mSpyBootThreshold).getCount();
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ int count = invocationOnMock.getArgument(0);
+ setCrashRecoveryPropRescueBootCount(count);
+ return null;
+ }).when(mSpyBootThreshold).setCount(anyInt());
+
+ doAnswer((Answer<Integer>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.boot_mitigation_count", "0");
+ return Integer.parseInt(storedValue);
+ }).when(mSpyBootThreshold).getMitigationCount();
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ int count = invocationOnMock.getArgument(0);
+ mCrashRecoveryPropertiesMap.put("crashrecovery.boot_mitigation_count",
+ Integer.toString(count));
+ return null;
+ }).when(mSpyBootThreshold).setMitigationCount(anyInt());
+
+ doAnswer((Answer<Long>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.rescue_boot_start", "0");
+ return Long.parseLong(storedValue);
+ }).when(mSpyBootThreshold).getStart();
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ long count = invocationOnMock.getArgument(0);
+ mCrashRecoveryPropertiesMap.put("crashrecovery.rescue_boot_start",
+ Long.toString(count));
+ return null;
+ }).when(mSpyBootThreshold).setStart(anyLong());
+
+ doAnswer((Answer<Long>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.boot_mitigation_start", "0");
+ return Long.parseLong(storedValue);
+ }).when(mSpyBootThreshold).getMitigationStart();
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ long count = invocationOnMock.getArgument(0);
+ mCrashRecoveryPropertiesMap.put("crashrecovery.boot_mitigation_start",
+ Long.toString(count));
+ return null;
+ }).when(mSpyBootThreshold).setMitigationStart(anyLong());
+
+ Field mBootThresholdField = watchdog.getClass().getDeclaredField("mBootThreshold");
+ mBootThresholdField.setAccessible(true);
+ mBootThresholdField.set(watchdog, mSpyBootThreshold);
+ } catch (Exception e) {
+ // tests will fail, just printing the error
+ System.out.println("Error while spying BootThreshold " + e.getMessage());
+ }
+ }
+
+ private void setCrashRecoveryPropRescueBootCount(int count) {
+ mCrashRecoveryPropertiesMap.put("crashrecovery.rescue_boot_count",
+ Integer.toString(count));
+ }
+
+ private void setCrashRecoveryPropAttemptingReboot(boolean value) {
+ mCrashRecoveryPropertiesMap.put("crashrecovery.attempting_reboot",
+ Boolean.toString(value));
+ }
+
+ private void setCrashRecoveryPropLastFactoryReset(long value) {
+ mCrashRecoveryPropertiesMap.put("persist.crashrecovery.last_factory_reset",
+ Long.toString(value));
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java
index 64cc397..9ba4f5b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java
@@ -218,4 +218,9 @@
assertEquals(errMsg, Thread.State.TERMINATED, getState());
}
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 2bc66ac..40b5458 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -1210,4 +1210,9 @@
return returnValueForstartUserOnSecondaryDisplay;
}
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
index 1c0989c..9391d5b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
@@ -338,4 +338,8 @@
}
}
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index d56229c..e15942b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -1126,4 +1126,9 @@
};
}
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
index 1fd7c4a..fa5bfd6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
@@ -284,4 +284,9 @@
return app;
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
index 434d200..dfb8fda 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
@@ -803,4 +803,9 @@
return mHandler;
}
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 0504344..732d0ce 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -2578,6 +2578,31 @@
assertTrue(CACHED_APP_MAX_ADJ >= app3.mState.getSetAdj());
}
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_AboveClient_NotStarted() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+ doReturn(app).when(sService).getTopApp();
+ sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+ sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE);
+
+ assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+
+ // Start binding to a service that isn't running yet.
+ ServiceRecord sr = makeServiceRecord(app);
+ sr.app = null;
+ bindService(null, app, sr, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
+
+ // Since sr.app is null, this service cannot be in the same process as the
+ // client so we expect the BIND_ABOVE_CLIENT adjustment to take effect.
+ app.mServices.updateHasAboveClientLocked();
+ sService.mOomAdjuster.updateOomAdjLocked(app, OOM_ADJ_REASON_NONE);
+ assertTrue(app.mServices.hasAboveClient());
+ assertNotEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+ }
+
private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
String packageName, boolean hasShownUi) {
long now = SystemClock.uptimeMillis();
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java
index fd1b068..7ec27be 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java
@@ -201,4 +201,9 @@
return mActiveServices;
}
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
index a140730..6e41685 100644
--- a/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java
@@ -23,7 +23,15 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -33,14 +41,18 @@
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
-import android.util.Log;
-import android.util.Xml;
+import android.crashrecovery.flags.Flags;
+import android.os.Handler;
+import android.os.MessageQueue;
+import android.os.SystemProperties;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.server.PackageWatchdog;
import com.android.server.SystemConfig;
+import com.android.server.pm.ApexManager;
import org.junit.After;
import org.junit.Before;
@@ -49,18 +61,17 @@
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
import org.mockito.stubbing.Answer;
-import org.xmlpull.v1.XmlPullParser;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
+import java.time.Duration;
+import java.util.HashMap;
import java.util.List;
-import java.util.Scanner;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
@@ -78,12 +89,23 @@
@Mock
PackageManager mMockPackageManager;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private ApexManager mApexManager;
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ private HashMap<String, String> mSystemSettingsMap;
private MockitoSession mSession;
private static final String APP_A = "com.package.a";
private static final String APP_B = "com.package.b";
+ private static final String APP_C = "com.package.c";
private static final long VERSION_CODE = 1L;
+ private static final long VERSION_CODE_2 = 2L;
private static final String LOG_TAG = "RollbackPackageHealthObserverTest";
+ private static final String PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG =
+ "persist.device_config.configuration.disable_high_impact_rollback";
+
private SystemConfig mSysConfig;
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
@@ -96,12 +118,34 @@
.initMocks(this)
.strictness(Strictness.LENIENT)
.spyStatic(PackageWatchdog.class)
+ .spyStatic(SystemProperties.class)
.startMocking();
+ mSystemSettingsMap = new HashMap<>();
// Mock PackageWatchdog
doAnswer((Answer<PackageWatchdog>) invocationOnMock -> mMockPackageWatchdog)
.when(() -> PackageWatchdog.getInstance(mMockContext));
+ // Mock SystemProperties setter and various getters
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ String key = invocationOnMock.getArgument(0);
+ String value = invocationOnMock.getArgument(1);
+
+ mSystemSettingsMap.put(key, value);
+ return null;
+ }
+ ).when(() -> SystemProperties.set(anyString(), anyString()));
+
+ doAnswer((Answer<Boolean>) invocationOnMock -> {
+ String key = invocationOnMock.getArgument(0);
+ boolean defaultValue = invocationOnMock.getArgument(1);
+
+ String storedValue = mSystemSettingsMap.get(key);
+ return storedValue == null ? defaultValue : Boolean.parseBoolean(storedValue);
+ }
+ ).when(() -> SystemProperties.getBoolean(anyString(), anyBoolean()));
+
+ SystemProperties.set(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, Boolean.toString(false));
}
@After
@@ -121,7 +165,7 @@
@Test
public void testHealthCheckLevels() {
RollbackPackageHealthObserver observer =
- spy(new RollbackPackageHealthObserver(mMockContext));
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
VersionedPackage testFailedPackage = new VersionedPackage(APP_A, VERSION_CODE);
VersionedPackage secondFailedPackage = new VersionedPackage(APP_B, VERSION_CODE);
@@ -165,14 +209,14 @@
@Test
public void testIsPersistent() {
RollbackPackageHealthObserver observer =
- spy(new RollbackPackageHealthObserver(mMockContext));
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
assertTrue(observer.isPersistent());
}
@Test
public void testMayObservePackage_withoutAnyRollback() {
RollbackPackageHealthObserver observer =
- spy(new RollbackPackageHealthObserver(mMockContext));
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of());
assertFalse(observer.mayObservePackage(APP_A));
@@ -182,7 +226,7 @@
public void testMayObservePackage_forPersistentApp()
throws PackageManager.NameNotFoundException {
RollbackPackageHealthObserver observer =
- spy(new RollbackPackageHealthObserver(mMockContext));
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
ApplicationInfo info = new ApplicationInfo();
info.flags = ApplicationInfo.FLAG_PERSISTENT | ApplicationInfo.FLAG_SYSTEM;
when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
@@ -197,7 +241,7 @@
public void testMayObservePackage_forNonPersistentApp()
throws PackageManager.NameNotFoundException {
RollbackPackageHealthObserver observer =
- spy(new RollbackPackageHealthObserver(mMockContext));
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(mRollbackInfo));
when(mRollbackInfo.getPackages()).thenReturn(List.of(mPackageRollbackInfo));
@@ -208,96 +252,790 @@
}
/**
- * Test that isAutomaticRollbackDenied works correctly when packages that are not
- * denied are sent.
+ * Test that when impactLevel is low returns user impact level 70
*/
@Test
- public void isRollbackAllowedTest_false() throws IOException {
- final String contents =
- "<config>\n"
- + " <automatic-rollback-denylisted-app package=\"com.android.vending\" />\n"
- + "</config>";
- final File folder = createTempSubfolder("folder");
- createTempFile(folder, "automatic-rollback-denylisted-app.xml", contents);
+ public void healthCheckFailed_impactLevelLow_onePackage()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(1, List.of(packageRollbackInfo),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ VersionedPackage secondFailedPackage = new VersionedPackage(APP_B, VERSION_CODE);
- readPermissions(folder, /* Grant all permission flags */ ~0);
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo1));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
- assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig,
- new VersionedPackage("com.test.package", 1))).isEqualTo(false);
+ assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_70,
+ observer.onHealthCheckFailed(secondFailedPackage,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1));
}
/**
- * Test that isAutomaticRollbackDenied works correctly when packages that are
- * denied are sent.
+ * HealthCheckFailed should only return low impact rollbacks. High impact rollbacks are only
+ * for bootloop.
*/
@Test
- public void isRollbackAllowedTest_true() throws IOException {
- final String contents =
- "<config>\n"
- + " <automatic-rollback-denylisted-app package=\"com.android.vending\" />\n"
- + "</config>";
- final File folder = createTempSubfolder("folder");
- createTempFile(folder, "automatic-rollback-denylisted-app.xml", contents);
+ public void healthCheckFailed_impactLevelHigh_onePackage()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+ null, null, false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(1, List.of(packageRollbackInfo),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ VersionedPackage secondFailedPackage = new VersionedPackage(APP_B, VERSION_CODE);
- readPermissions(folder, /* Grant all permission flags */ ~0);
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo1));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
- assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig,
- new VersionedPackage("com.android.vending", 1))).isEqualTo(true);
+ assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
+ observer.onHealthCheckFailed(secondFailedPackage,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1));
}
/**
- * Test that isAutomaticRollbackDenied works correctly when no config is present
+ * When the rollback impact level is manual only return user impact level 0. (User impact level
+ * 0 is ignored by package watchdog)
*/
@Test
- public void isRollbackAllowedTest_noConfig() throws IOException {
- final File folder = createTempSubfolder("folder");
+ public void healthCheckFailed_impactLevelManualOnly_onePackage()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+ null, null, false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(1, List.of(packageRollbackInfo),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ VersionedPackage secondFailedPackage = new VersionedPackage(APP_B, VERSION_CODE);
- readPermissions(folder, /* Grant all permission flags */ ~0);
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo1));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
- assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig,
- new VersionedPackage("com.android.vending", 1))).isEqualTo(false);
+ assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
+ observer.onHealthCheckFailed(secondFailedPackage,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1));
}
/**
- * Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
- *
- * @param folder pre-existing subdirectory of mTemporaryFolder to put the file
- * @param fileName name of the file (e.g. filename.xml) to create
- * @param contents contents to write to the file
- * @return the newly created file
+ * When both low impact and high impact are present, return 70.
*/
- private File createTempFile(File folder, String fileName, String contents)
- throws IOException {
- File file = new File(folder, fileName);
- BufferedWriter bw = new BufferedWriter(new FileWriter(file));
- bw.write(contents);
- bw.close();
+ @Test
+ public void healthCheckFailed_impactLevelLowAndHigh_onePackage()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+ null, null, false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(1, List.of(packageRollbackInfo),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null, false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(2, List.of(packageRollbackInfoB),
+ false, null, 222,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ VersionedPackage failedPackage = new VersionedPackage(APP_C, VERSION_CODE);
- // Print to logcat for test debugging.
- Log.d(LOG_TAG, "Contents of file " + file.getAbsolutePath());
- Scanner input = new Scanner(file);
- while (input.hasNextLine()) {
- Log.d(LOG_TAG, input.nextLine());
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(rollbackInfo1, rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_70,
+ observer.onHealthCheckFailed(failedPackage,
+ PackageWatchdog.FAILURE_REASON_APP_CRASH, 1));
+ }
+
+ /**
+ * When low impact rollback is available roll it back.
+ */
+ @Test
+ public void execute_impactLevelLow_nativeCrash_rollback()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId = 1;
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId, List.of(packageRollbackInfo),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ VersionedPackage secondFailedPackage = new VersionedPackage(APP_B, VERSION_CODE);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo1));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.execute(secondFailedPackage,
+ PackageWatchdog.FAILURE_REASON_NATIVE_CRASH, 1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager).getAvailableRollbacks();
+ verify(mRollbackManager).commitRollback(eq(rollbackId), any(), any());
+ }
+
+ /**
+ * Rollback the failing package if rollback is available for it
+ */
+ @Test
+ public void execute_impactLevelLow_rollbackFailedPackage()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId1 = 1;
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoA = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId1, List.of(packageRollbackInfoA),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ int rollbackId2 = 2;
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoB),
+ false, null, 222,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(rollbackInfo1, rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.execute(appBFrom, PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager).commitRollback(argument.capture(), any(), any());
+ // Rollback package App B as the failing package is B
+ assertThat(argument.getValue()).isEqualTo(rollbackId2);
+ }
+
+ /**
+ * Rollback all available rollbacks if the rollback is not available for failing package.
+ */
+ @Test
+ public void execute_impactLevelLow_rollbackAll()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId1 = 1;
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoA = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId1, List.of(packageRollbackInfoA),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ int rollbackId2 = 2;
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoB),
+ false, null, 222,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ VersionedPackage failedPackage = new VersionedPackage(APP_C, VERSION_CODE);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(rollbackInfo1, rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.execute(failedPackage, PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager, times(2)).commitRollback(
+ argument.capture(), any(), any());
+ // Rollback A and B when the failing package doesn't have a rollback
+ assertThat(argument.getAllValues()).isEqualTo(List.of(rollbackId1, rollbackId2));
+ }
+
+ /**
+ * rollback low impact package if both low and high impact packages are available
+ */
+ @Test
+ public void execute_impactLevelLowAndHigh_rollbackLow()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId1 = 1;
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoA = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId1, List.of(packageRollbackInfoA),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ int rollbackId2 = 2;
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoB),
+ false, null, 222,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ VersionedPackage failedPackage = new VersionedPackage(APP_C, VERSION_CODE);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(rollbackInfo1, rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.execute(failedPackage, PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager, times(1)).commitRollback(
+ argument.capture(), any(), any());
+ // Rollback A and B when the failing package doesn't have a rollback
+ assertThat(argument.getAllValues()).isEqualTo(List.of(rollbackId1));
+ }
+
+ /**
+ * Don't roll back high impact package if only high impact package is available. high impact
+ * rollback to be rolled back only on bootloop.
+ */
+ @Test
+ public void execute_impactLevelHigh_rollbackHigh()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId2 = 2;
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoB),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ VersionedPackage failedPackage = new VersionedPackage(APP_C, VERSION_CODE);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.execute(failedPackage, PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager, never()).commitRollback(argument.capture(), any(), any());
+
+ }
+
+ /**
+ * Test that when impactLevel is low returns user impact level 70
+ */
+ @Test
+ public void onBootLoop_impactLevelLow_onePackage() throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(1, List.of(packageRollbackInfo),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo1));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_70,
+ observer.onBootLoop(1));
+ }
+
+ @Test
+ public void onBootLoop_impactLevelHigh_onePackage()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+ null, null, false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(1, List.of(packageRollbackInfo),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo1));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_90,
+ observer.onBootLoop(1));
+ }
+
+ @Test
+ public void onBootLoop_impactLevelHighDisableHighImpactRollback_onePackage()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ SystemProperties.set(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, Boolean.toString(true));
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+ null, null, false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(1, List.of(packageRollbackInfo),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo1));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
+ observer.onBootLoop(1));
+ }
+
+ /**
+ * When the rollback impact level is manual only return user impact level 0. (User impact level
+ * 0 is ignored by package watchdog)
+ */
+ @Test
+ public void onBootLoop_impactLevelManualOnly_onePackage()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+ null, null, false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(1, List.of(packageRollbackInfo),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo1));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
+ observer.onBootLoop(1));
+ }
+
+ /**
+ * When both low impact and high impact are present, return 70.
+ */
+ @Test
+ public void onBootLoop_impactLevelLowAndHigh_onePackage()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(appAFrom, appATo,
+ null, null, false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(1, List.of(packageRollbackInfo),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null, false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(2, List.of(packageRollbackInfoB),
+ false, null, 222,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(rollbackInfo1, rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_70,
+ observer.onBootLoop(1));
+ }
+
+ /**
+ * Rollback all available rollbacks if the rollback is not available for failing package.
+ */
+ @Test
+ public void executeBootLoopMitigation_impactLevelLow_rollbackAll()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId1 = 1;
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoA = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId1, List.of(packageRollbackInfoA),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ int rollbackId2 = 2;
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoB),
+ false, null, 222,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(rollbackInfo1, rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.executeBootLoopMitigation(1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager, times(2)).commitRollback(
+ argument.capture(), any(), any());
+ // Rollback A and B when the failing package doesn't have a rollback
+ assertThat(argument.getAllValues()).isEqualTo(List.of(rollbackId1, rollbackId2));
+ }
+
+ /**
+ * rollback low impact package if both low and high impact packages are available
+ */
+ @Test
+ public void executeBootLoopMitigation_impactLevelLowAndHigh_rollbackLow()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId1 = 1;
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoA = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId1, List.of(packageRollbackInfoA),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ int rollbackId2 = 2;
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoB),
+ false, null, 222,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(rollbackInfo1, rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.executeBootLoopMitigation(1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager, times(1)).commitRollback(
+ argument.capture(), any(), any());
+ // Rollback A and B when the failing package doesn't have a rollback
+ assertThat(argument.getAllValues()).isEqualTo(List.of(rollbackId1));
+ }
+
+ /**
+ * Rollback high impact package if only high impact package is available
+ */
+ @Test
+ public void executeBootLoopMitigation_impactLevelHigh_rollbackHigh()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId2 = 2;
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoB),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.executeBootLoopMitigation(1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager, times(1)).commitRollback(
+ argument.capture(), any(), any());
+ // Rollback high impact packages when no other rollback available
+ assertThat(argument.getAllValues()).isEqualTo(List.of(rollbackId2));
+ }
+
+ /**
+ * Rollback only low impact available rollbacks if both low and manual only are available.
+ */
+ @Test
+ public void execute_impactLevelLowAndManual_rollbackLowImpactOnly()
+ throws PackageManager.NameNotFoundException, InterruptedException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId1 = 1;
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoA = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId1, List.of(packageRollbackInfoA),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
+ int rollbackId2 = 2;
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoB),
+ false, null, 222,
+ PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL);
+ VersionedPackage failedPackage = new VersionedPackage(APP_C, VERSION_CODE);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(rollbackInfo1, rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.execute(failedPackage, PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager, times(1)).commitRollback(
+ argument.capture(), any(), any());
+ assertThat(argument.getAllValues()).isEqualTo(List.of(rollbackId1));
+ }
+
+ /**
+ * Do not roll back if only manual rollback is available.
+ */
+ @Test
+ public void execute_impactLevelManual_rollbackLowImpactOnly()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId1 = 1;
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoA = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId1, List.of(packageRollbackInfoA),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL);
+ VersionedPackage failedPackage = new VersionedPackage(APP_C, VERSION_CODE);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(rollbackInfo1));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.execute(failedPackage, PackageWatchdog.FAILURE_REASON_APP_CRASH, 1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager, never()).commitRollback(argument.capture(), any(), any());
+ }
+
+ /**
+ * Rollback alphabetically first package if multiple high impact rollbacks are available.
+ */
+ @Test
+ public void executeBootLoopMitigation_impactLevelHighMultiplePackage_rollbackHigh()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ int rollbackId1 = 1;
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId1, List.of(packageRollbackInfoB),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ int rollbackId2 = 2;
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoA = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoA),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ VersionedPackage failedPackage = new VersionedPackage(APP_C, VERSION_CODE);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(rollbackInfo1, rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.executeBootLoopMitigation(1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager, times(1)).commitRollback(
+ argument.capture(), any(), any());
+ // Rollback APP_A because it is first alphabetically
+ assertThat(argument.getAllValues()).isEqualTo(List.of(rollbackId2));
+ }
+
+ /**
+ * Don't roll back if kill switch is enabled.
+ */
+ @Test
+ public void executeBootLoopMitigation_impactLevelHighKillSwitchTrue_rollbackHigh()
+ throws PackageManager.NameNotFoundException {
+ mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+ SystemProperties.set(PROP_DISABLE_HIGH_IMPACT_ROLLBACK_FLAG, Boolean.toString(true));
+ int rollbackId1 = 1;
+ VersionedPackage appBFrom = new VersionedPackage(APP_B, VERSION_CODE_2);
+ VersionedPackage appBTo = new VersionedPackage(APP_B, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoB = new PackageRollbackInfo(appBFrom, appBTo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo1 = new RollbackInfo(rollbackId1, List.of(packageRollbackInfoB),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ int rollbackId2 = 2;
+ VersionedPackage appAFrom = new VersionedPackage(APP_A, VERSION_CODE_2);
+ VersionedPackage appATo = new VersionedPackage(APP_A, VERSION_CODE);
+ PackageRollbackInfo packageRollbackInfoA = new PackageRollbackInfo(appAFrom, appATo,
+ null, null , false, false,
+ null);
+ RollbackInfo rollbackInfo2 = new RollbackInfo(rollbackId2, List.of(packageRollbackInfoA),
+ false, null, 111,
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
+ RollbackPackageHealthObserver observer =
+ spy(new RollbackPackageHealthObserver(mMockContext, mApexManager));
+ ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
+
+ when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager);
+ // Make the rollbacks available
+ when(mRollbackManager.getAvailableRollbacks()).thenReturn(
+ List.of(rollbackInfo1, rollbackInfo2));
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getModuleInfo(any(), eq(0))).thenReturn(null);
+
+ observer.executeBootLoopMitigation(1);
+ waitForIdleHandler(observer.getHandler(), Duration.ofSeconds(10));
+
+ verify(mRollbackManager, never()).commitRollback(
+ argument.capture(), any(), any());
+ }
+
+ private void waitForIdleHandler(Handler handler, Duration timeout) {
+ final MessageQueue queue = handler.getLooper().getQueue();
+ final CountDownLatch latch = new CountDownLatch(1);
+ queue.addIdleHandler(() -> {
+ latch.countDown();
+ // Remove idle handler
+ return false;
+ });
+ try {
+ latch.await(timeout.toMillis(), TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ fail("Interrupted unexpectedly: " + e);
}
-
- return file;
- }
-
- private void readPermissions(File libraryDir, int permissionFlag) {
- final XmlPullParser parser = Xml.newPullParser();
- mSysConfig.readPermissions(parser, libraryDir, permissionFlag);
- }
-
- /**
- * Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
- *
- * @param folderName subdirectory of mTemporaryFolder to put the file, creating if needed
- * @return the folder
- */
- private File createTempSubfolder(String folderName)
- throws IOException {
- File folder = new File(mTemporaryFolder.getRoot(), folderName);
- folder.mkdirs();
- return folder;
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING b/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING
new file mode 100644
index 0000000..e42bdad
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "postsubmit": [
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.rollback"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/src/com/android/server/selinux/OWNERS b/services/tests/mockingservicestests/src/com/android/server/selinux/OWNERS
new file mode 100644
index 0000000..49a0934
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/selinux/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/selinux/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
index 9851bc1..b415682 100644
--- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
@@ -16,24 +16,24 @@
package com.android.server.trust;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.argThat;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-
import android.Manifest;
import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.IActivityManager;
+import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustListener;
import android.app.trust.ITrustManager;
import android.content.BroadcastReceiver;
@@ -45,14 +45,26 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.net.Uri;
+import android.content.pm.UserInfo;
+import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.SensorProperties;
+import android.hardware.face.FaceManager;
+import android.hardware.face.FaceSensorProperties;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.os.test.TestLooper;
+import android.os.UserManager;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
+import android.security.Authorization;
+import android.security.authorization.IKeystoreAuthorization;
import android.service.trust.TrustAgentService;
import android.testing.TestableContext;
import android.view.IWindowManager;
@@ -61,12 +73,12 @@
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
-import com.google.android.collect.Lists;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -74,37 +86,81 @@
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Random;
+import java.util.Collection;
+import java.util.List;
public class TrustManagerServiceTest {
@Rule
- public MockitoRule mMockitoRule = MockitoJUnit.rule();
+ public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+ .spyStatic(ActivityManager.class)
+ .spyStatic(Authorization.class)
+ .mockStatic(ServiceManager.class)
+ .mockStatic(WindowManagerGlobal.class)
+ .build();
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
@Rule
public final MockContext mMockContext = new MockContext(
ApplicationProvider.getApplicationContext());
private static final String URI_SCHEME_PACKAGE = "package";
- private static final int TEST_USER_ID = UserHandle.USER_SYSTEM;
+ private static final int TEST_USER_ID = 50;
+ private static final UserInfo TEST_USER =
+ new UserInfo(TEST_USER_ID, "user", UserInfo.FLAG_FULL);
+ private static final int PARENT_USER_ID = 60;
+ private static final int PROFILE_USER_ID = 70;
+ private static final long[] PARENT_BIOMETRIC_SIDS = new long[] { 600L, 601L };
+ private static final long[] PROFILE_BIOMETRIC_SIDS = new long[] { 700L, 701L };
- private final TestLooper mLooper = new TestLooper();
private final ArrayList<ResolveInfo> mTrustAgentResolveInfoList = new ArrayList<>();
- private final LockPatternUtils mLockPatternUtils = new LockPatternUtils(mMockContext);
- private final TrustManagerService mService = new TrustManagerService(mMockContext);
+ private final ArrayList<ComponentName> mKnownTrustAgents = new ArrayList<>();
+ private final ArrayList<ComponentName> mEnabledTrustAgents = new ArrayList<>();
- @Mock
- private PackageManager mPackageManagerMock;
+ private @Mock ActivityManager mActivityManager;
+ private @Mock BiometricManager mBiometricManager;
+ private @Mock DevicePolicyManager mDevicePolicyManager;
+ private @Mock FaceManager mFaceManager;
+ private @Mock FingerprintManager mFingerprintManager;
+ private @Mock IKeystoreAuthorization mKeystoreAuthorization;
+ private @Mock LockPatternUtils mLockPatternUtils;
+ private @Mock PackageManager mPackageManager;
+ private @Mock UserManager mUserManager;
+ private @Mock IWindowManager mWindowManager;
+
+ private HandlerThread mHandlerThread;
+ private TrustManagerService.Injector mInjector;
+ private TrustManagerService mService;
+ private ITrustManager mTrustManager;
@Before
- public void setUp() {
- resetTrustAgentLockSettings();
- LocalServices.addService(SystemServiceManager.class, mock(SystemServiceManager.class));
+ public void setUp() throws Exception {
+ when(mActivityManager.isUserRunning(TEST_USER_ID)).thenReturn(true);
+ doReturn(mock(IActivityManager.class)).when(() -> ActivityManager.getService());
+
+ when(mFaceManager.getSensorProperties()).thenReturn(List.of());
+ when(mFingerprintManager.getSensorProperties()).thenReturn(List.of());
+
+ doReturn(mKeystoreAuthorization).when(() -> Authorization.getService());
+
+ when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
+ when(mLockPatternUtils.isSecure(TEST_USER_ID)).thenReturn(true);
+ when(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).thenReturn(mKnownTrustAgents);
+ when(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).thenReturn(mEnabledTrustAgents);
+ doAnswer(invocation -> {
+ mKnownTrustAgents.clear();
+ mKnownTrustAgents.addAll((Collection<ComponentName>) invocation.getArgument(0));
+ return null;
+ }).when(mLockPatternUtils).setKnownTrustAgents(any(), eq(TEST_USER_ID));
+ doAnswer(invocation -> {
+ mEnabledTrustAgents.clear();
+ mEnabledTrustAgents.addAll((Collection<ComponentName>) invocation.getArgument(0));
+ return null;
+ }).when(mLockPatternUtils).setEnabledTrustAgents(any(), eq(TEST_USER_ID));
ArgumentMatcher<Intent> trustAgentIntentMatcher = new ArgumentMatcher<Intent>() {
@Override
@@ -112,17 +168,46 @@
return TrustAgentService.SERVICE_INTERFACE.equals(argument.getAction());
}
};
- when(mPackageManagerMock.queryIntentServicesAsUser(argThat(trustAgentIntentMatcher),
+ when(mPackageManager.queryIntentServicesAsUser(argThat(trustAgentIntentMatcher),
anyInt(), anyInt())).thenReturn(mTrustAgentResolveInfoList);
- when(mPackageManagerMock.checkPermission(any(), any())).thenReturn(
+ when(mPackageManager.checkPermission(any(), any())).thenReturn(
PackageManager.PERMISSION_GRANTED);
- mMockContext.setMockPackageManager(mPackageManagerMock);
+
+ when(mUserManager.getAliveUsers()).thenReturn(List.of(TEST_USER));
+ when(mUserManager.getEnabledProfileIds(TEST_USER_ID)).thenReturn(new int[0]);
+ when(mUserManager.getUserInfo(TEST_USER_ID)).thenReturn(TEST_USER);
+
+ when(mWindowManager.isKeyguardLocked()).thenReturn(true);
+
+ mMockContext.addMockSystemService(ActivityManager.class, mActivityManager);
+ mMockContext.addMockSystemService(BiometricManager.class, mBiometricManager);
+ mMockContext.addMockSystemService(FaceManager.class, mFaceManager);
+ mMockContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
+ mMockContext.setMockPackageManager(mPackageManager);
+ mMockContext.addMockSystemService(UserManager.class, mUserManager);
+ doReturn(mWindowManager).when(() -> WindowManagerGlobal.getWindowManagerService());
+ LocalServices.addService(SystemServiceManager.class, mock(SystemServiceManager.class));
+
+ grantPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE);
+ grantPermission(Manifest.permission.TRUST_LISTENER);
+
+ mHandlerThread = new HandlerThread("handler");
+ mHandlerThread.start();
+ mInjector = new TrustManagerService.Injector(mLockPatternUtils, mHandlerThread.getLooper());
+ mService = new TrustManagerService(mMockContext, mInjector);
+
+ // Get the ITrustManager from the new TrustManagerService.
+ mService.onStart();
+ ArgumentCaptor<IBinder> binderArgumentCaptor = ArgumentCaptor.forClass(IBinder.class);
+ verify(() -> ServiceManager.addService(eq(Context.TRUST_SERVICE),
+ binderArgumentCaptor.capture(), anyBoolean(), anyInt()));
+ mTrustManager = ITrustManager.Stub.asInterface(binderArgumentCaptor.getValue());
}
@After
public void tearDown() {
- resetTrustAgentLockSettings();
LocalServices.removeServiceForTest(SystemServiceManager.class);
+ mHandlerThread.quit();
}
@Test
@@ -142,10 +227,9 @@
bootService();
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- systemTrustAgent1, systemTrustAgent2);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- systemTrustAgent1, systemTrustAgent2, userTrustAgent1, userTrustAgent2);
+ assertThat(mEnabledTrustAgents).containsExactly(systemTrustAgent1, systemTrustAgent2);
+ assertThat(mKnownTrustAgents).containsExactly(systemTrustAgent1, systemTrustAgent2,
+ userTrustAgent1, userTrustAgent2);
}
@Test
@@ -162,10 +246,8 @@
bootService();
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- defaultTrustAgent);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- systemTrustAgent, defaultTrustAgent);
+ assertThat(mEnabledTrustAgents).containsExactly(defaultTrustAgent);
+ assertThat(mKnownTrustAgents).containsExactly(systemTrustAgent, defaultTrustAgent);
}
@Test
@@ -174,16 +256,16 @@
"com.android/.SystemTrustAgent");
ComponentName trustAgent2 = ComponentName.unflattenFromString(
"com.android/.AnotherSystemTrustAgent");
- initializeEnabledAgents(trustAgent1);
+ mEnabledTrustAgents.add(trustAgent1);
+ Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
+ Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
addTrustAgent(trustAgent1, /* isSystemApp= */ true);
addTrustAgent(trustAgent2, /* isSystemApp= */ true);
bootService();
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- trustAgent1);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- trustAgent1, trustAgent2);
+ assertThat(mEnabledTrustAgents).containsExactly(trustAgent1);
+ assertThat(mKnownTrustAgents).containsExactly(trustAgent1, trustAgent2);
}
@Test
@@ -192,17 +274,17 @@
"com.android/.SystemTrustAgent");
ComponentName trustAgent2 = ComponentName.unflattenFromString(
"com.android/.AnotherSystemTrustAgent");
- initializeEnabledAgents(trustAgent1);
- initializeKnownAgents(trustAgent1);
+ Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
+ Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
+ Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
+ Settings.Secure.KNOWN_TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
addTrustAgent(trustAgent1, /* isSystemApp= */ true);
addTrustAgent(trustAgent2, /* isSystemApp= */ true);
bootService();
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- trustAgent1, trustAgent2);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- trustAgent1, trustAgent2);
+ assertThat(mEnabledTrustAgents).containsExactly(trustAgent1, trustAgent2);
+ assertThat(mKnownTrustAgents).containsExactly(trustAgent1, trustAgent2);
}
@Test
@@ -212,12 +294,10 @@
"com.android/.SystemTrustAgent");
addTrustAgent(newAgentComponentName, /* isSystemApp= */ true);
- mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
+ notifyPackageChanged(newAgentComponentName);
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- newAgentComponentName);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- newAgentComponentName);
+ assertThat(mEnabledTrustAgents).containsExactly(newAgentComponentName);
+ assertThat(mKnownTrustAgents).containsExactly(newAgentComponentName);
}
@Test
@@ -233,12 +313,10 @@
"com.android/.SystemTrustAgent");
addTrustAgent(newAgentComponentName, /* isSystemApp= */ true);
- mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
+ notifyPackageChanged(newAgentComponentName);
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- defaultTrustAgent);
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- defaultTrustAgent, newAgentComponentName);
+ assertThat(mEnabledTrustAgents).containsExactly(defaultTrustAgent);
+ assertThat(mKnownTrustAgents).containsExactly(defaultTrustAgent, newAgentComponentName);
}
@Test
@@ -248,11 +326,10 @@
"com.user/.UserTrustAgent");
addTrustAgent(newAgentComponentName, /* isSystemApp= */ false);
- mMockContext.sendPackageChangedBroadcast(newAgentComponentName);
+ notifyPackageChanged(newAgentComponentName);
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).isEmpty();
- assertThat(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).containsExactly(
- newAgentComponentName);
+ assertThat(mEnabledTrustAgents).isEmpty();
+ assertThat(mKnownTrustAgents).containsExactly(newAgentComponentName);
}
@Test
@@ -265,50 +342,269 @@
addTrustAgent(systemTrustAgent2, /* isSystemApp= */ true);
bootService();
// Simulate user turning off systemTrustAgent2
- mLockPatternUtils.setEnabledTrustAgents(Collections.singletonList(systemTrustAgent1),
- TEST_USER_ID);
+ mLockPatternUtils.setEnabledTrustAgents(List.of(systemTrustAgent1), TEST_USER_ID);
- mMockContext.sendPackageChangedBroadcast(systemTrustAgent2);
+ notifyPackageChanged(systemTrustAgent2);
- assertThat(mLockPatternUtils.getEnabledTrustAgents(TEST_USER_ID)).containsExactly(
- systemTrustAgent1);
+ assertThat(mEnabledTrustAgents).containsExactly(systemTrustAgent1);
}
@Test
public void reportEnabledTrustAgentsChangedInformsListener() throws RemoteException {
- final LockPatternUtils utils = mock(LockPatternUtils.class);
- final TrustManagerService service = new TrustManagerService(mMockContext,
- new TrustManagerService.Injector(utils, mLooper.getLooper()));
final ITrustListener trustListener = mock(ITrustListener.class);
- final IWindowManager windowManager = mock(IWindowManager.class);
- final int userId = new Random().nextInt();
+ mTrustManager.registerTrustListener(trustListener);
+ mService.waitForIdle();
+ mTrustManager.reportEnabledTrustAgentsChanged(TEST_USER_ID);
+ mService.waitForIdle();
+ verify(trustListener).onEnabledTrustAgentsChanged(TEST_USER_ID);
+ }
- mMockContext.getTestablePermissions().setPermission(Manifest.permission.TRUST_LISTENER,
- PERMISSION_GRANTED);
+ // Tests that when the device is locked for a managed profile with a *unified* challenge, the
+ // device locked notification that is sent to Keystore contains the biometric SIDs of the parent
+ // user, not the profile. This matches the authentication that is needed to unlock the device
+ // for the profile again.
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testLockDeviceForManagedProfileWithUnifiedChallenge_usesParentBiometricSids()
+ throws Exception {
+ setupMocksForProfile(/* unifiedChallenge= */ true);
- when(utils.getKnownTrustAgents(anyInt())).thenReturn(new ArrayList<>());
+ when(mWindowManager.isKeyguardLocked()).thenReturn(false);
+ mTrustManager.reportKeyguardShowingChanged();
+ verify(mKeystoreAuthorization).onDeviceUnlocked(PARENT_USER_ID, null);
+ verify(mKeystoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null);
- MockitoSession mockSession = mockitoSession()
- .initMocks(this)
- .mockStatic(ServiceManager.class)
- .mockStatic(WindowManagerGlobal.class)
- .startMocking();
+ when(mWindowManager.isKeyguardLocked()).thenReturn(true);
+ mTrustManager.reportKeyguardShowingChanged();
+ verify(mKeystoreAuthorization)
+ .onDeviceLocked(eq(PARENT_USER_ID), eq(PARENT_BIOMETRIC_SIDS), eq(false));
+ verify(mKeystoreAuthorization)
+ .onDeviceLocked(eq(PROFILE_USER_ID), eq(PARENT_BIOMETRIC_SIDS), eq(false));
+ }
- doReturn(windowManager).when(() -> {
- WindowManagerGlobal.getWindowManagerService();
- });
+ // Tests that when the device is locked for a managed profile with a *separate* challenge, the
+ // device locked notification that is sent to Keystore contains the biometric SIDs of the
+ // profile itself. This matches the authentication that is needed to unlock the device for the
+ // profile again.
+ @Test
+ public void testLockDeviceForManagedProfileWithSeparateChallenge_usesProfileBiometricSids()
+ throws Exception {
+ setupMocksForProfile(/* unifiedChallenge= */ false);
- service.onStart();
- ArgumentCaptor<IBinder> binderArgumentCaptor = ArgumentCaptor.forClass(IBinder.class);
- verify(() -> ServiceManager.addService(eq(Context.TRUST_SERVICE),
- binderArgumentCaptor.capture(), anyBoolean(), anyInt()));
- ITrustManager manager = ITrustManager.Stub.asInterface(binderArgumentCaptor.getValue());
- manager.registerTrustListener(trustListener);
- mLooper.dispatchAll();
- manager.reportEnabledTrustAgentsChanged(userId);
- mLooper.dispatchAll();
- verify(trustListener).onEnabledTrustAgentsChanged(eq(userId));
- mockSession.finishMocking();
+ mTrustManager.setDeviceLockedForUser(PROFILE_USER_ID, false);
+ verify(mKeystoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null);
+
+ mTrustManager.setDeviceLockedForUser(PROFILE_USER_ID, true);
+ verify(mKeystoreAuthorization)
+ .onDeviceLocked(eq(PROFILE_USER_ID), eq(PROFILE_BIOMETRIC_SIDS), eq(false));
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockEnabled_whenWeakFingerprintIsSetupAndAllowed()
+ throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ setupFingerprint(SensorProperties.STRENGTH_WEAK);
+ verifyWeakUnlockEnabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockEnabled_whenWeakFaceIsSetupAndAllowed() throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ setupFace(SensorProperties.STRENGTH_WEAK);
+ verifyWeakUnlockEnabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockEnabled_whenConvenienceFingerprintIsSetupAndAllowed()
+ throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ setupFingerprint(SensorProperties.STRENGTH_CONVENIENCE);
+ verifyWeakUnlockEnabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockEnabled_whenConvenienceFaceIsSetupAndAllowed()
+ throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ setupFace(SensorProperties.STRENGTH_CONVENIENCE);
+ verifyWeakUnlockEnabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockDisabled_whenStrongAuthRequired() throws Exception {
+ setupStrongAuthTracker(StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN, true);
+ setupFace(SensorProperties.STRENGTH_WEAK);
+ verifyWeakUnlockDisabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockDisabled_whenNonStrongBiometricNotAllowed() throws Exception {
+ setupStrongAuthTracker(StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED,
+ /* isNonStrongBiometricAllowed= */ false);
+ setupFace(SensorProperties.STRENGTH_WEAK);
+ verifyWeakUnlockDisabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockDisabled_whenWeakFingerprintSensorIsPresentButNotEnrolled()
+ throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ setupFingerprint(SensorProperties.STRENGTH_WEAK, /* enrolled= */ false);
+ verifyWeakUnlockDisabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockDisabled_whenWeakFaceSensorIsPresentButNotEnrolled()
+ throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ setupFace(SensorProperties.STRENGTH_WEAK, /* enrolled= */ false);
+ verifyWeakUnlockDisabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void
+ testKeystoreWeakUnlockDisabled_whenWeakFingerprintIsSetupButForbiddenByDevicePolicy()
+ throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ setupFingerprint(SensorProperties.STRENGTH_WEAK);
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, TEST_USER_ID))
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
+ verifyWeakUnlockDisabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockDisabled_whenWeakFaceIsSetupButForbiddenByDevicePolicy()
+ throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ setupFace(SensorProperties.STRENGTH_WEAK);
+ when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, TEST_USER_ID))
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FACE);
+ verifyWeakUnlockDisabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockDisabled_whenOnlyStrongFingerprintIsSetup() throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ setupFingerprint(SensorProperties.STRENGTH_STRONG);
+ verifyWeakUnlockDisabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockDisabled_whenOnlyStrongFaceIsSetup() throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ setupFace(SensorProperties.STRENGTH_STRONG);
+ verifyWeakUnlockDisabled();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2)
+ public void testKeystoreWeakUnlockDisabled_whenNoBiometricsAreSetup() throws Exception {
+ setupStrongAuthTrackerToAllowEverything();
+ verifyWeakUnlockDisabled();
+ }
+
+ private void setupStrongAuthTrackerToAllowEverything() throws Exception {
+ setupStrongAuthTracker(StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED, true);
+ }
+
+ private void setupStrongAuthTracker(int strongAuthFlags, boolean isNonStrongBiometricAllowed)
+ throws Exception {
+ bootService();
+ mService.onUserSwitching(null, new SystemService.TargetUser(TEST_USER));
+
+ ArgumentCaptor<StrongAuthTracker> strongAuthTracker =
+ ArgumentCaptor.forClass(StrongAuthTracker.class);
+ verify(mLockPatternUtils).registerStrongAuthTracker(strongAuthTracker.capture());
+ strongAuthTracker.getValue().getStub().onStrongAuthRequiredChanged(
+ strongAuthFlags, TEST_USER_ID);
+ strongAuthTracker.getValue().getStub().onIsNonStrongBiometricAllowedChanged(
+ isNonStrongBiometricAllowed, TEST_USER_ID);
+ mService.waitForIdle();
+ }
+
+ private void setupFingerprint(int strength) {
+ setupFingerprint(strength, /* enrolled= */ true);
+ }
+
+ private void setupFingerprint(int strength, boolean enrolled) {
+ int sensorId = 100;
+ List<SensorProperties.ComponentInfo> componentInfo = List.of();
+ SensorProperties sensor = new SensorProperties(sensorId, strength, componentInfo);
+ when(mFingerprintManager.getSensorProperties()).thenReturn(List.of(sensor));
+ when(mFingerprintManager.hasEnrolledTemplates(TEST_USER_ID)).thenReturn(enrolled);
+ }
+
+ private void setupFace(int strength) {
+ setupFace(strength, /* enrolled= */ true);
+ }
+
+ private void setupFace(int strength, boolean enrolled) {
+ int sensorId = 100;
+ List<SensorProperties.ComponentInfo> componentInfo = List.of();
+ FaceSensorProperties sensor = new FaceSensorProperties(
+ sensorId, strength, componentInfo, FaceSensorProperties.TYPE_RGB);
+ when(mFaceManager.getSensorProperties()).thenReturn(List.of(sensor));
+ when(mFaceManager.hasEnrolledTemplates(TEST_USER_ID)).thenReturn(enrolled);
+ }
+
+ private void verifyWeakUnlockEnabled() throws Exception {
+ verifyWeakUnlockValue(true);
+ }
+
+ private void verifyWeakUnlockDisabled() throws Exception {
+ verifyWeakUnlockValue(false);
+ }
+
+ // Simulates a device unlock and a device lock, then verifies that the expected
+ // weakUnlockEnabled flag was passed to Keystore's onDeviceLocked method.
+ private void verifyWeakUnlockValue(boolean expectedWeakUnlockEnabled) throws Exception {
+ when(mWindowManager.isKeyguardLocked()).thenReturn(false);
+ mTrustManager.reportKeyguardShowingChanged();
+ verify(mKeystoreAuthorization).onDeviceUnlocked(TEST_USER_ID, null);
+
+ when(mWindowManager.isKeyguardLocked()).thenReturn(true);
+ mTrustManager.reportKeyguardShowingChanged();
+ verify(mKeystoreAuthorization).onDeviceLocked(eq(TEST_USER_ID), any(),
+ eq(expectedWeakUnlockEnabled));
+ }
+
+ private void setupMocksForProfile(boolean unifiedChallenge) {
+ UserInfo parent = new UserInfo(PARENT_USER_ID, "parent", UserInfo.FLAG_FULL);
+ UserInfo profile = new UserInfo(PROFILE_USER_ID, "profile", UserInfo.FLAG_MANAGED_PROFILE);
+ when(mUserManager.getAliveUsers()).thenReturn(List.of(parent, profile));
+ when(mUserManager.getUserInfo(PARENT_USER_ID)).thenReturn(parent);
+ when(mUserManager.getUserInfo(PROFILE_USER_ID)).thenReturn(profile);
+ when(mUserManager.getProfileParent(PROFILE_USER_ID)).thenReturn(parent);
+ when(mUserManager.getEnabledProfileIds(PARENT_USER_ID))
+ .thenReturn(new int[] { PROFILE_USER_ID });
+
+ when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+ when(mLockPatternUtils.isProfileWithUnifiedChallenge(PROFILE_USER_ID))
+ .thenReturn(unifiedChallenge);
+ when(mLockPatternUtils.isManagedProfileWithUnifiedChallenge(PROFILE_USER_ID))
+ .thenReturn(unifiedChallenge);
+ when(mLockPatternUtils.isSeparateProfileChallengeEnabled(PROFILE_USER_ID))
+ .thenReturn(!unifiedChallenge);
+
+ when(mBiometricManager.getAuthenticatorIds(PARENT_USER_ID))
+ .thenReturn(PARENT_BIOMETRIC_SIDS);
+ when(mBiometricManager.getAuthenticatorIds(PROFILE_USER_ID))
+ .thenReturn(PROFILE_BIOMETRIC_SIDS);
+
+ bootService();
+ mService.onUserSwitching(null, new SystemService.TargetUser(parent));
}
private void addTrustAgent(ComponentName agentComponentName, boolean isSystemApp) {
@@ -327,33 +623,29 @@
mTrustAgentResolveInfoList.add(resolveInfo);
}
- private void initializeEnabledAgents(ComponentName... enabledAgents) {
- mLockPatternUtils.setEnabledTrustAgents(Lists.newArrayList(enabledAgents), TEST_USER_ID);
- Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
- Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
- }
-
- private void initializeKnownAgents(ComponentName... knownAgents) {
- mLockPatternUtils.setKnownTrustAgents(Lists.newArrayList(knownAgents), TEST_USER_ID);
- Settings.Secure.putIntForUser(mMockContext.getContentResolver(),
- Settings.Secure.KNOWN_TRUST_AGENTS_INITIALIZED, 1, TEST_USER_ID);
- }
-
private void bootService() {
mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+ mMockContext.sendUserStartedBroadcast();
}
- private void resetTrustAgentLockSettings() {
- mLockPatternUtils.setEnabledTrustAgents(Collections.emptyList(), TEST_USER_ID);
- mLockPatternUtils.setKnownTrustAgents(Collections.emptyList(), TEST_USER_ID);
+ private void grantPermission(String permission) {
+ mMockContext.getTestablePermissions().setPermission(
+ permission, PackageManager.PERMISSION_GRANTED);
+ }
+
+ private void notifyPackageChanged(ComponentName changedComponent) {
+ mService.mPackageMonitor.onPackageChanged(
+ changedComponent.getPackageName(),
+ UserHandle.of(TEST_USER_ID).getUid(1234),
+ new String[] { changedComponent.getClassName() });
}
/** A mock Context that allows the test process to send protected broadcasts. */
private static final class MockContext extends TestableContext {
- private final ArrayList<BroadcastReceiver> mPackageChangedBroadcastReceivers =
+ private final ArrayList<BroadcastReceiver> mUserStartedBroadcastReceivers =
new ArrayList<>();
MockContext(Context base) {
@@ -366,23 +658,22 @@
UserHandle user, IntentFilter filter, @Nullable String broadcastPermission,
@Nullable Handler scheduler) {
- if (filter.hasAction(Intent.ACTION_PACKAGE_CHANGED)) {
- mPackageChangedBroadcastReceivers.add(receiver);
+ if (filter.hasAction(Intent.ACTION_USER_STARTED)) {
+ mUserStartedBroadcastReceivers.add(receiver);
}
return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
scheduler);
}
- void sendPackageChangedBroadcast(ComponentName changedComponent) {
- Intent intent = new Intent(
- Intent.ACTION_PACKAGE_CHANGED,
- Uri.fromParts(URI_SCHEME_PACKAGE,
- changedComponent.getPackageName(), /* fragment= */ null))
- .putExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST,
- new String[]{changedComponent.getClassName()})
- .putExtra(Intent.EXTRA_USER_HANDLE, TEST_USER_ID)
- .putExtra(Intent.EXTRA_UID, UserHandle.of(TEST_USER_ID).getUid(1234));
- for (BroadcastReceiver receiver : mPackageChangedBroadcastReceivers) {
+ @Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user,
+ @Nullable String receiverPermission, @Nullable Bundle options) {
+ }
+
+ void sendUserStartedBroadcast() {
+ Intent intent = new Intent(Intent.ACTION_USER_STARTED)
+ .putExtra(Intent.EXTRA_USER_HANDLE, TEST_USER_ID);
+ for (BroadcastReceiver receiver : mUserStartedBroadcastReceivers) {
receiver.onReceive(this, intent);
}
}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 27fd8a6..92628f4 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -2,6 +2,13 @@
// Build FrameworksServicesTests package
//########################################################################
+java_defaults {
+ name: "FrameworksServicesTests-jni-defaults",
+ jni_libs: [
+ "libservicestestjni",
+ ],
+}
+
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
@@ -13,6 +20,9 @@
android_test {
name: "FrameworksServicesTests",
+ defaults: [
+ "FrameworksServicesTests-jni-defaults",
+ ],
// Include all test java files.
srcs: [
@@ -68,6 +78,7 @@
"coretests-aidl",
"securebox",
"flag-junit",
+ "net_flags_lib",
],
libs: [
diff --git a/services/tests/servicestests/jni/Android.bp b/services/tests/servicestests/jni/Android.bp
new file mode 100644
index 0000000..174beb8
--- /dev/null
+++ b/services/tests/servicestests/jni/Android.bp
@@ -0,0 +1,58 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+cc_library_shared {
+ name: "libservicestestjni",
+
+ defaults: ["android.hardware.graphics.common-ndk_shared"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
+ ],
+
+ srcs: [
+ ":lib_cachedAppOptimizer_native",
+ ":lib_gameManagerService_native",
+ ":lib_oomConnection_native",
+ "onload.cpp",
+ ],
+
+ include_dirs: [
+ "frameworks/base/libs",
+ "frameworks/native/services",
+ "frameworks/native/libs/math/include",
+ "frameworks/native/libs/ui/include",
+ "system/memory/libmeminfo/include",
+ ],
+
+ shared_libs: [
+ "libandroid",
+ "libandroid_runtime",
+ "libbase",
+ "libbinder",
+ "libgralloctypes",
+ "libgui",
+ "libhidlbase",
+ "liblog",
+ "libmeminfo",
+ "libmemevents",
+ "libnativehelper",
+ "libprocessgroup",
+ "libutils",
+ "libcutils",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.graphics.mapper@4.0",
+ "android.hidl.token@1.0-utils",
+ ],
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/jni/onload.cpp b/services/tests/servicestests/jni/onload.cpp
new file mode 100644
index 0000000..f160b3d
--- /dev/null
+++ b/services/tests/servicestests/jni/onload.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/*
+ * this is a mini native libaray for cached app optimizer tests to run properly. It
+ * loads all the native methods necessary.
+ */
+#include <nativehelper/JNIHelp.h>
+#include "jni.h"
+#include "utils/Log.h"
+#include "utils/misc.h"
+
+namespace android {
+int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
+int register_android_server_app_GameManagerService(JNIEnv* env);
+int register_android_server_am_OomConnection(JNIEnv* env);
+};
+
+using namespace android;
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
+{
+ JNIEnv* env = NULL;
+ jint result = -1;
+
+ if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+ ALOGE("GetEnv failed!");
+ return result;
+ }
+ ALOG_ASSERT(env, "Could not retrieve the env!");
+ register_android_server_am_CachedAppOptimizer(env);
+ register_android_server_app_GameManagerService(env);
+ register_android_server_am_OomConnection(env);
+ return JNI_VERSION_1_4;
+}
diff --git a/services/tests/servicestests/src/com/android/server/OWNERS b/services/tests/servicestests/src/com/android/server/OWNERS
index 177d72b..f433e4e 100644
--- a/services/tests/servicestests/src/com/android/server/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/OWNERS
@@ -4,5 +4,6 @@
per-file *Bluetooth* = file:platform/packages/modules/Bluetooth:master:/framework/java/android/bluetooth/OWNERS
per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
-per-file BatteryServiceTest.java = file:platform/hardware/interfaces:/health/aidl/OWNERS
+per-file BatteryServiceTest.java = file:platform/hardware/interfaces:/health/OWNERS
per-file GestureLauncherServiceTest.java = file:platform/packages/apps/EmergencyInfo:/OWNERS
+per-file SecurityStateTest.java = file:/SECURITY_STATE_OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
index acdfee9..c0051c6 100644
--- a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
@@ -172,4 +172,9 @@
anyString(), any(), any(), any(), anyBoolean(), any(), eq(mAuxExecutorService),
anyBoolean(), anyBoolean(), any());
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("servicestestjni");
+ }
}
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 d26d671..f04a4e6 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -756,8 +756,7 @@
mUserController.startUser(TEST_USER_ID, USER_START_MODE_BACKGROUND);
- verify(mInjector.mStorageManagerMock, never())
- .unlockCeStorage(eq(TEST_USER_ID), anyInt(), any());
+ verify(mInjector.mStorageManagerMock, never()).unlockCeStorage(eq(TEST_USER_ID), any());
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
index 84af9dd..218b7c0 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
@@ -30,6 +30,7 @@
deviceId: Int,
vendorId: Int,
productId: Int,
+ deviceBus: Int,
languageTag: String?,
layoutType: String?
): InputDevice =
@@ -42,6 +43,7 @@
.setExternal(true)
.setVendorId(vendorId)
.setProductId(productId)
+ .setDeviceBus(deviceBus)
.setKeyboardLanguageTag(languageTag)
.setKeyboardLayoutType(layoutType)
.build()
@@ -67,6 +69,7 @@
const val DEVICE_ID = 1
const val DEFAULT_VENDOR_ID = 123
const val DEFAULT_PRODUCT_ID = 456
+ const val DEFAULT_DEVICE_BUS = 789
}
@Test
@@ -77,6 +80,7 @@
DEVICE_ID,
DEFAULT_VENDOR_ID,
DEFAULT_PRODUCT_ID,
+ DEFAULT_DEVICE_BUS,
null,
null
)
@@ -92,6 +96,7 @@
DEVICE_ID,
DEFAULT_VENDOR_ID,
DEFAULT_PRODUCT_ID,
+ DEFAULT_DEVICE_BUS,
null,
null
)
@@ -107,6 +112,7 @@
DEVICE_ID,
DEFAULT_VENDOR_ID,
DEFAULT_PRODUCT_ID,
+ DEFAULT_DEVICE_BUS,
"de-CH",
"qwertz"
)
@@ -135,6 +141,11 @@
DEFAULT_PRODUCT_ID,
event.productId
)
+ assertEquals(
+ "KeyboardConfigurationEvent should pick device bus from provided InputDevice",
+ DEFAULT_DEVICE_BUS,
+ event.deviceBus
+ )
assertTrue(event.isFirstConfiguration)
assertEquals(
@@ -178,6 +189,7 @@
DEVICE_ID,
DEFAULT_VENDOR_ID,
DEFAULT_PRODUCT_ID,
+ DEFAULT_DEVICE_BUS,
"und", // Undefined language tag
"azerty"
)
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 f5d50d1..6986cab 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -305,9 +305,9 @@
doAnswer(invocation -> {
Object[] args = invocation.getArguments();
mStorageManager.unlockCeStorage(/* userId= */ (int) args[0],
- /* secret= */ (byte[]) args[2]);
+ /* secret= */ (byte[]) args[1]);
return null;
- }).when(sm).unlockCeStorage(anyInt(), anyInt(), any());
+ }).when(sm).unlockCeStorage(anyInt(), any());
doAnswer(invocation -> {
Object[] args = invocation.getArguments();
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
index 5a62d92..7053597 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -16,6 +16,8 @@
package com.android.server.locksettings;
+import static android.security.Flags.FLAG_REPORT_PRIMARY_AUTH_ATTEMPTS;
+
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
@@ -30,6 +32,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -38,6 +41,7 @@
import android.app.PropertyInvalidatedCache;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.service.gatekeeper.GateKeeperResponse;
import android.text.TextUtils;
@@ -45,10 +49,12 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockSettingsStateListener;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.VerifyCredentialResponse;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -59,6 +65,7 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Before
public void setUp() {
@@ -399,6 +406,60 @@
}
@Test
+ public void testVerifyCredential_notifyLockSettingsStateListeners_whenGoodPassword()
+ throws Exception {
+ mSetFlagsRule.enableFlags(FLAG_REPORT_PRIMARY_AUTH_ATTEMPTS);
+ final LockscreenCredential password = newPassword("password");
+ setCredential(PRIMARY_USER_ID, password);
+ final LockSettingsStateListener listener = mock(LockSettingsStateListener.class);
+ mLocalService.registerLockSettingsStateListener(listener);
+
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+ mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */)
+ .getResponseCode());
+
+ verify(listener).onAuthenticationSucceeded(PRIMARY_USER_ID);
+ }
+
+ @Test
+ public void testVerifyCredential_notifyLockSettingsStateListeners_whenBadPassword()
+ throws Exception {
+ mSetFlagsRule.enableFlags(FLAG_REPORT_PRIMARY_AUTH_ATTEMPTS);
+ final LockscreenCredential password = newPassword("password");
+ setCredential(PRIMARY_USER_ID, password);
+ final LockscreenCredential badPassword = newPassword("badPassword");
+ final LockSettingsStateListener listener = mock(LockSettingsStateListener.class);
+ mLocalService.registerLockSettingsStateListener(listener);
+
+ assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
+ mService.verifyCredential(badPassword, PRIMARY_USER_ID, 0 /* flags */)
+ .getResponseCode());
+
+ verify(listener).onAuthenticationFailed(PRIMARY_USER_ID);
+ }
+
+ @Test
+ public void testLockSettingsStateListener_registeredThenUnregistered() throws Exception {
+ mSetFlagsRule.enableFlags(FLAG_REPORT_PRIMARY_AUTH_ATTEMPTS);
+ final LockscreenCredential password = newPassword("password");
+ setCredential(PRIMARY_USER_ID, password);
+ final LockscreenCredential badPassword = newPassword("badPassword");
+ final LockSettingsStateListener listener = mock(LockSettingsStateListener.class);
+
+ mLocalService.registerLockSettingsStateListener(listener);
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+ mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */)
+ .getResponseCode());
+ verify(listener).onAuthenticationSucceeded(PRIMARY_USER_ID);
+
+ mLocalService.unregisterLockSettingsStateListener(listener);
+ assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
+ mService.verifyCredential(badPassword, PRIMARY_USER_ID, 0 /* flags */)
+ .getResponseCode());
+ verify(listener, never()).onAuthenticationFailed(PRIMARY_USER_ID);
+ }
+
+ @Test
public void testSetCredentialNotPossibleInSecureFrpModeDuringSuw() {
setUserSetupComplete(false);
setSecureFrpMode(true);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index eca19c8..2da2f50 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -506,6 +506,14 @@
}
@Test
+ public void testUnlockUserWithTokenWithBadHandleReturnsFalse() {
+ final long badTokenHandle = 123456789;
+ final byte[] token = "some-high-entropy-secure-token".getBytes();
+ mService.initializeSyntheticPassword(PRIMARY_USER_ID);
+ assertFalse(mLocalService.unlockUserWithToken(badTokenHandle, token, PRIMARY_USER_ID));
+ }
+
+ @Test
public void testGetHashFactorPrimaryUser() throws RemoteException {
LockscreenCredential password = newPassword("password");
initSpAndSetCredential(PRIMARY_USER_ID, password);
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
index 13dc120..d6d2b6d 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
@@ -16,6 +16,7 @@
package com.android.server.net;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
@@ -327,12 +328,20 @@
isRestrictedForLowPowerStandby.put(INetd.FIREWALL_RULE_DENY, true);
expected.put(FIREWALL_CHAIN_LOW_POWER_STANDBY, isRestrictedForLowPowerStandby);
+ // Background chain
+ final ArrayMap<Integer, Boolean> isRestrictedInBackground = new ArrayMap<>();
+ isRestrictedInBackground.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
+ isRestrictedInBackground.put(INetd.FIREWALL_RULE_ALLOW, false);
+ isRestrictedInBackground.put(INetd.FIREWALL_RULE_DENY, true);
+ expected.put(FIREWALL_CHAIN_BACKGROUND, isRestrictedInBackground);
+
final int[] chains = {
FIREWALL_CHAIN_STANDBY,
FIREWALL_CHAIN_POWERSAVE,
FIREWALL_CHAIN_DOZABLE,
FIREWALL_CHAIN_RESTRICTED,
- FIREWALL_CHAIN_LOW_POWER_STANDBY
+ FIREWALL_CHAIN_LOW_POWER_STANDBY,
+ FIREWALL_CHAIN_BACKGROUND
};
final int[] states = {
INetd.FIREWALL_RULE_ALLOW,
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 2a76452..15cd5115 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.Manifest.permission.NETWORK_STACK;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
@@ -26,12 +27,14 @@
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
+import static android.net.ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND;
import static android.net.ConnectivityManager.BLOCKED_REASON_APP_STANDBY;
import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE;
import static android.net.ConnectivityManager.BLOCKED_REASON_LOW_POWER_STANDBY;
import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
import static android.net.ConnectivityManager.TYPE_MOBILE;
@@ -48,12 +51,19 @@
import static android.net.NetworkPolicyManager.ALLOWED_REASON_FOREGROUND;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_NOT_IN_BACKGROUND;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_ALLOWLIST;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM;
import static android.net.NetworkPolicyManager.ALLOWED_REASON_TOP;
+import static android.net.NetworkPolicyManager.BACKGROUND_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
+import static android.net.NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+import static android.net.NetworkPolicyManager.TOP_THRESHOLD_STATE;
import static android.net.NetworkPolicyManager.allowedReasonsToString;
import static android.net.NetworkPolicyManager.blockedReasonsToString;
import static android.net.NetworkPolicyManager.uidPoliciesToString;
@@ -64,6 +74,7 @@
import static android.net.NetworkTemplate.MATCH_CARRIER;
import static android.net.NetworkTemplate.MATCH_MOBILE;
import static android.net.NetworkTemplate.MATCH_WIFI;
+import static android.os.PowerExemptionManager.REASON_OTHER;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
@@ -80,6 +91,7 @@
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
+import static com.android.server.net.NetworkPolicyManagerService.UID_MSG_STATE_CHANGED;
import static com.android.server.net.NetworkPolicyManagerService.UidBlockedState.getEffectiveBlockedReasons;
import static com.android.server.net.NetworkPolicyManagerService.normalizeTemplate;
@@ -137,6 +149,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkPolicy;
+import android.net.NetworkPolicyManager;
import android.net.NetworkStateSnapshot;
import android.net.NetworkTemplate;
import android.net.TelephonyNetworkSpecifier;
@@ -146,6 +159,8 @@
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.PersistableBundle;
+import android.os.PowerExemptionManager;
+import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.RemoteException;
@@ -153,6 +168,9 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -169,6 +187,7 @@
import android.util.Range;
import android.util.RecurrenceRule;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
@@ -182,8 +201,6 @@
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.usage.AppStandbyInternal;
-import com.google.common.util.concurrent.AbstractFuture;
-
import libcore.io.Streams;
import org.junit.After;
@@ -227,10 +244,8 @@
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -243,6 +258,9 @@
public class NetworkPolicyManagerServiceTest {
private static final String TAG = "NetworkPolicyManagerServiceTest";
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
private static final long TEST_START = 1194220800000L;
private static final String TEST_IFACE = "test0";
private static final String TEST_WIFI_NETWORK_KEY = "TestWifiNetworkKey";
@@ -285,6 +303,7 @@
private @Mock TelephonyManager mTelephonyManager;
private @Mock UserManager mUserManager;
private @Mock NetworkStatsManager mStatsManager;
+ private @Mock PowerExemptionManager mPowerExemptionManager;
private TestDependencies mDeps;
private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor =
@@ -302,6 +321,7 @@
private NetworkPolicyManagerService mService;
private final ArraySet<BroadcastReceiver> mRegisteredReceivers = new ArraySet<>();
+ private BroadcastReceiver mPowerAllowlistReceiver;
/**
* In some of the tests while initializing NetworkPolicyManagerService,
@@ -446,6 +466,7 @@
@Before
public void callSystemReady() throws Exception {
MockitoAnnotations.initMocks(this);
+ when(mPowerExemptionManager.getAllowListedAppIds(anyBoolean())).thenReturn(new int[0]);
final Context context = InstrumentationRegistry.getContext();
@@ -482,6 +503,8 @@
return mUserManager;
case Context.NETWORK_STATS_SERVICE:
return mStatsManager;
+ case Context.POWER_EXEMPTION_SERVICE:
+ return mPowerExemptionManager;
default:
return super.getSystemService(name);
}
@@ -495,6 +518,9 @@
@Override
public Intent registerReceiver(BroadcastReceiver receiver,
IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ if (filter.hasAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED)) {
+ mPowerAllowlistReceiver = receiver;
+ }
mRegisteredReceivers.add(receiver);
return super.registerReceiver(receiver, filter, broadcastPermission, scheduler);
}
@@ -1594,6 +1620,12 @@
verify(mActivityManagerInternal).notifyNetworkPolicyRulesUpdated(UID_A, procStateSeq);
}
+ private void callAndWaitOnUidGone(int uid) throws Exception {
+ // The disabled argument is used only for ephemeral apps and does not matter here.
+ mUidObserver.onUidGone(uid, false /* disabled */);
+ waitForUidEventHandlerIdle();
+ }
+
private void callAndWaitOnUidStateChanged(int uid, int procState, long procStateSeq)
throws Exception {
callAndWaitOnUidStateChanged(uid, procState, procStateSeq,
@@ -2066,6 +2098,12 @@
expectHasUseRestrictedNetworksPermission(UID_A, true);
expectHasUseRestrictedNetworksPermission(UID_B, false);
+ // Set low enough proc-states to ensure these uids are allowed in the background chain.
+ // To maintain clean separation between separate firewall chains, the tests could
+ // check for the specific blockedReasons in the uidBlockedState.
+ callAndWaitOnUidStateChanged(UID_A, BACKGROUND_THRESHOLD_STATE - 1, 21);
+ callAndWaitOnUidStateChanged(UID_B, BACKGROUND_THRESHOLD_STATE - 1, 21);
+
Map<Integer, Integer> firewallUidRules = new ArrayMap<>();
doAnswer(arg -> {
int[] uids = arg.getArgument(1);
@@ -2113,7 +2151,261 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
+ public void testBackgroundChainEnabled() throws Exception {
+ verify(mNetworkManager).setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, true);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
+ public void testBackgroundChainOnProcStateChange() throws Exception {
+ // initialization calls setFirewallChainEnabled, so we want to reset the invocations.
+ clearInvocations(mNetworkManager);
+
+ mService.mBackgroundRestrictionDelayMs = 500; // To avoid waiting too long in tests.
+
+ // The app will be blocked when there is no prior proc-state.
+ assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
+
+ int procStateSeq = 23;
+ callAndWaitOnUidStateChanged(UID_A, BACKGROUND_THRESHOLD_STATE - 1, procStateSeq++);
+
+ verify(mNetworkManager).setFirewallUidRule(FIREWALL_CHAIN_BACKGROUND, UID_A,
+ FIREWALL_RULE_ALLOW);
+ assertFalse(mService.isUidNetworkingBlocked(UID_A, false));
+
+ callAndWaitOnUidStateChanged(UID_A, BACKGROUND_THRESHOLD_STATE + 1, procStateSeq++);
+
+ // The app should be blocked after a delay. Posting a message just after the delay and
+ // waiting for it to complete to ensure that the blocking code has executed.
+ waitForDelayedMessageOnHandler(mService.mBackgroundRestrictionDelayMs + 1);
+
+ verify(mNetworkManager).setFirewallUidRule(FIREWALL_CHAIN_BACKGROUND, UID_A,
+ FIREWALL_RULE_DEFAULT);
+ assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
+ public void testBackgroundChainOnAllowlistChange() throws Exception {
+ // initialization calls setFirewallChainEnabled, so we want to reset the invocations.
+ clearInvocations(mNetworkManager);
+
+ // The apps will be blocked when there is no prior proc-state.
+ assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
+ assertTrue(mService.isUidNetworkingBlocked(UID_B, false));
+
+ final int procStateSeq = 29;
+ callAndWaitOnUidStateChanged(UID_A, BACKGROUND_THRESHOLD_STATE + 1, procStateSeq);
+ assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
+
+ when(mPowerExemptionManager.getAllowListedAppIds(anyBoolean()))
+ .thenReturn(new int[]{APP_ID_A, APP_ID_B});
+ final SparseIntArray firewallUidRules = new SparseIntArray();
+ doAnswer(arg -> {
+ final int[] uids = arg.getArgument(1);
+ final int[] rules = arg.getArgument(2);
+ assertTrue(uids.length == rules.length);
+
+ for (int i = 0; i < uids.length; ++i) {
+ firewallUidRules.put(uids[i], rules[i]);
+ }
+ return null;
+ }).when(mNetworkManager).setFirewallUidRules(eq(FIREWALL_CHAIN_BACKGROUND),
+ any(int[].class), any(int[].class));
+
+ mPowerAllowlistReceiver.onReceive(mServiceContext, null);
+
+ assertEquals(FIREWALL_RULE_ALLOW, firewallUidRules.get(UID_A, -1));
+ assertEquals(FIREWALL_RULE_ALLOW, firewallUidRules.get(UID_B, -1));
+
+ assertFalse(mService.isUidNetworkingBlocked(UID_A, false));
+ assertFalse(mService.isUidNetworkingBlocked(UID_B, false));
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
+ public void testBackgroundChainOnTempAllowlistChange() throws Exception {
+ // initialization calls setFirewallChainEnabled, so we want to reset the invocations.
+ clearInvocations(mNetworkManager);
+
+ // The app will be blocked as is no prior proc-state.
+ assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
+
+ final int procStateSeq = 19;
+ callAndWaitOnUidStateChanged(UID_A, BACKGROUND_THRESHOLD_STATE + 1, procStateSeq);
+ assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
+
+ final NetworkPolicyManagerInternal internal = LocalServices.getService(
+ NetworkPolicyManagerInternal.class);
+
+ internal.onTempPowerSaveWhitelistChange(APP_ID_A, true, REASON_OTHER, "testing");
+
+ verify(mNetworkManager).setFirewallUidRule(FIREWALL_CHAIN_BACKGROUND, UID_A,
+ FIREWALL_RULE_ALLOW);
+ assertFalse(mService.isUidNetworkingBlocked(UID_A, false));
+
+ internal.onTempPowerSaveWhitelistChange(APP_ID_A, false, REASON_OTHER, "testing");
+
+ verify(mNetworkManager).setFirewallUidRule(FIREWALL_CHAIN_BACKGROUND, UID_A,
+ FIREWALL_RULE_DEFAULT);
+ assertTrue(mService.isUidNetworkingBlocked(UID_A, false));
+ }
+
+ private boolean isUidState(int uid, int procState, int procStateSeq, int capability) {
+ final NetworkPolicyManager.UidState uidState = mService.getUidStateForTest(uid);
+ if (uidState == null) {
+ return false;
+ }
+ return uidState.uid == uid && uidState.procStateSeq == procStateSeq
+ && uidState.procState == procState && uidState.capability == capability;
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
+ public void testUidObserverFiltersProcStateChanges() throws Exception {
+ int testProcStateSeq = 0;
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // First callback for uid.
+ callOnUidStatechanged(UID_A, BACKGROUND_THRESHOLD_STATE + 1, testProcStateSeq++,
+ PROCESS_CAPABILITY_NONE);
+ assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // Doesn't cross the background threshold.
+ callOnUidStatechanged(UID_A, BACKGROUND_THRESHOLD_STATE, testProcStateSeq++,
+ PROCESS_CAPABILITY_NONE);
+ assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // Crosses the background threshold.
+ callOnUidStatechanged(UID_A, BACKGROUND_THRESHOLD_STATE - 1, testProcStateSeq++,
+ PROCESS_CAPABILITY_NONE);
+ assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // Doesn't cross the foreground threshold.
+ callOnUidStatechanged(UID_A, FOREGROUND_THRESHOLD_STATE + 1, testProcStateSeq++,
+ PROCESS_CAPABILITY_NONE);
+ assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // Crosses the foreground threshold.
+ callOnUidStatechanged(UID_A, FOREGROUND_THRESHOLD_STATE, testProcStateSeq++,
+ PROCESS_CAPABILITY_NONE);
+ assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // Doesn't cross the top threshold.
+ callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE + 1, testProcStateSeq++,
+ PROCESS_CAPABILITY_NONE);
+ assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // Crosses the top threshold.
+ callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++,
+ PROCESS_CAPABILITY_NONE);
+ assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // Doesn't cross any other threshold.
+ callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE - 1, testProcStateSeq++,
+ PROCESS_CAPABILITY_NONE);
+ assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
+ public void testUidObserverFiltersStaleChanges() throws Exception {
+ final int testProcStateSeq = 51;
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // First callback for uid.
+ callOnUidStatechanged(UID_B, BACKGROUND_THRESHOLD_STATE + 100, testProcStateSeq,
+ PROCESS_CAPABILITY_NONE);
+ assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // Stale callback because the procStateSeq is smaller.
+ callOnUidStatechanged(UID_B, BACKGROUND_THRESHOLD_STATE - 100, testProcStateSeq - 10,
+ PROCESS_CAPABILITY_NONE);
+ assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_NETWORK_BLOCKED_FOR_TOP_SLEEPING_AND_ABOVE)
+ public void testUidObserverFiltersCapabilityChanges() throws Exception {
+ int testProcStateSeq = 0;
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // First callback for uid.
+ callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++,
+ PROCESS_CAPABILITY_NONE);
+ assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // The same process-state with one network capability added.
+ callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++,
+ PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK);
+ assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // The same process-state with another network capability added.
+ callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++,
+ PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
+ | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK);
+ assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // The same process-state with all capabilities, but no change in network capabilities.
+ callOnUidStatechanged(UID_A, TOP_THRESHOLD_STATE, testProcStateSeq++,
+ PROCESS_CAPABILITY_ALL);
+ assertFalse(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ }
+
+ @Test
+ public void testUidStateChangeAfterUidGone() throws Exception {
+ final int testProcStateSeq = 51;
+ final int testProcState = PROCESS_STATE_IMPORTANT_FOREGROUND;
+
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // First callback for uid.
+ callOnUidStatechanged(UID_B, testProcState, testProcStateSeq, PROCESS_CAPABILITY_NONE);
+ assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ assertTrue(isUidState(UID_B, testProcState, testProcStateSeq, PROCESS_CAPABILITY_NONE));
+
+ callAndWaitOnUidGone(UID_B);
+ try (SyncBarrier b = new SyncBarrier(mService.mUidEventHandler)) {
+ // Even though the procState is the same, the uid had exited - so this should be
+ // processed as a fresh callback.
+ callOnUidStatechanged(UID_B, testProcState, testProcStateSeq + 1,
+ PROCESS_CAPABILITY_NONE);
+ assertTrue(mService.mUidEventHandler.hasMessages(UID_MSG_STATE_CHANGED));
+ }
+ waitForUidEventHandlerIdle();
+ assertTrue(isUidState(UID_B, testProcState, testProcStateSeq + 1, PROCESS_CAPABILITY_NONE));
+ }
+
+ @Test
public void testLowPowerStandbyAllowlist() throws Exception {
+ // Chain background is also enabled but these procstates are important enough to be exempt.
callAndWaitOnUidStateChanged(UID_A, PROCESS_STATE_TOP, 0);
callAndWaitOnUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
callAndWaitOnUidStateChanged(UID_C, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
@@ -2200,7 +2492,21 @@
ALLOWED_REASON_TOP), BLOCKED_REASON_NONE);
effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_LOW_POWER_STANDBY,
ALLOWED_REASON_LOW_POWER_STANDBY_ALLOWLIST), BLOCKED_REASON_NONE);
- // TODO: test more combinations of blocked reasons.
+
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_APP_BACKGROUND,
+ ALLOWED_REASON_NOT_IN_BACKGROUND), BLOCKED_REASON_NONE);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_APP_BACKGROUND
+ | BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_NOT_IN_BACKGROUND),
+ BLOCKED_REASON_BATTERY_SAVER);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_APP_BACKGROUND
+ | BLOCKED_REASON_DOZE, ALLOWED_REASON_NOT_IN_BACKGROUND),
+ BLOCKED_REASON_DOZE);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_APP_BACKGROUND,
+ ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS), BLOCKED_REASON_APP_BACKGROUND);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_APP_BACKGROUND,
+ ALLOWED_REASON_POWER_SAVE_ALLOWLIST), BLOCKED_REASON_NONE);
+ effectiveBlockedReasons.put(Pair.create(BLOCKED_REASON_APP_BACKGROUND,
+ ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST), BLOCKED_REASON_NONE);
for (Map.Entry<Pair<Integer, Integer>, Integer> test : effectiveBlockedReasons.entrySet()) {
final int expectedEffectiveBlockedReasons = test.getValue();
@@ -2410,17 +2716,6 @@
verify(mStatsManager).setDefaultGlobalAlert(anyLong());
}
- private static class TestAbstractFuture<T> extends AbstractFuture<T> {
- @Override
- public T get() throws InterruptedException, ExecutionException {
- try {
- return get(5, TimeUnit.SECONDS);
- } catch (TimeoutException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
private static void assertTimeEquals(long expected, long actual) {
if (expected != actual) {
fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
@@ -2529,7 +2824,6 @@
private FutureIntent mRestrictBackgroundChanged;
private void postMsgAndWaitForCompletion() throws InterruptedException {
- final Handler handler = mService.getHandlerForTesting();
final CountDownLatch latch = new CountDownLatch(1);
mService.getHandlerForTesting().post(latch::countDown);
if (!latch.await(5, TimeUnit.SECONDS)) {
@@ -2537,6 +2831,14 @@
}
}
+ private void waitForDelayedMessageOnHandler(long delayMs) throws InterruptedException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ mService.getHandlerForTesting().postDelayed(latch::countDown, delayMs);
+ if (!latch.await(delayMs + 5_000, TimeUnit.MILLISECONDS)) {
+ fail("Timed out waiting for delayed msg to be handled");
+ }
+ }
+
private void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage)
throws InterruptedException {
mService.setSubscriptionPlans(subId, plans, 0, callingPackage);
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java
index e075379..c0ea157 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java
@@ -106,13 +106,13 @@
}
@Test
- public void testRecord_changeUserForFile_throws() {
+ public void testRecord_changeUserForFile_ignored() {
Entry entry1 = new Entry("owning.package1", "/path/file1", 'D', 10, "loading.package1");
Entry entry2 = new Entry("owning.package1", "/path/file1", 'D', 20, "loading.package1");
PackageDynamicCodeLoading info = makePackageDcl(entry1);
- assertThrows(() -> record(info, entry2));
+ assertThat(record(info, entry2)).isFalse();
assertHasEntries(info, entry1);
}
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
index 9d56a36..5e11e17 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
import android.util.SparseIntArray;
@@ -81,7 +82,8 @@
+ "'installedUsers':[55,79],"
+ "'ceSnapshotInodes':[]}],'isStaged':false,'causePackages':[{'packageName':'hello',"
+ "'longVersionCode':23},{'packageName':'something','longVersionCode':999}],"
- + "'committedSessionId':45654465},'timestamp':'2019-10-01T12:29:08.855Z',"
+ + "'committedSessionId':45654465, 'rollbackImpactLevel':1},"
+ + "'timestamp':'2019-10-01T12:29:08.855Z',"
+ "'originalSessionId':567,'state':'enabling','apkSessionId':-1,"
+ "'restoreUserDataInProgress':true, 'userId':0,"
+ "'installerPackageName':'some.installer'}";
@@ -138,6 +140,8 @@
assertThat(rollback.getOriginalSessionId()).isEqualTo(567);
assertThat(rollback.info.getRollbackId()).isEqualTo(ID);
assertThat(rollback.info.getPackages()).isEmpty();
+ assertThat(rollback.info.getRollbackImpactLevel()).isEqualTo(
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
assertThat(rollback.isEnabling()).isTrue();
assertThat(rollback.getExtensionVersions().toString())
.isEqualTo(extensionVersions.toString());
@@ -158,6 +162,8 @@
assertThat(rollback.info.getRollbackId()).isEqualTo(ID);
assertThat(rollback.info.getPackages()).isEmpty();
+ assertThat(rollback.info.getRollbackImpactLevel()).isEqualTo(
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
assertThat(rollback.isEnabling()).isTrue();
assertThat(rollback.getExtensionVersions().toString())
.isEqualTo(extensionVersions.toString());
@@ -175,6 +181,7 @@
origRb.info.getCausePackages().add(new VersionedPackage("com.made.up", 2));
origRb.info.getCausePackages().add(new VersionedPackage("com.pack.age", 99));
origRb.info.setCommittedSessionId(123456);
+ origRb.info.setRollbackImpactLevel(PackageManager.ROLLBACK_USER_IMPACT_HIGH);
PackageRollbackInfo pkgInfo1 =
new PackageRollbackInfo(new VersionedPackage("com.made.up", 18),
@@ -226,6 +233,7 @@
expectedRb.info.getCausePackages().add(new VersionedPackage("hello", 23));
expectedRb.info.getCausePackages().add(new VersionedPackage("something", 999));
expectedRb.info.setCommittedSessionId(45654465);
+ expectedRb.info.setRollbackImpactLevel(PackageManager.ROLLBACK_USER_IMPACT_HIGH);
PackageRollbackInfo pkgInfo1 = new PackageRollbackInfo(new VersionedPackage("blah", 55),
new VersionedPackage("blah1", 50), new ArrayList<>(), new ArrayList<>(),
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index aca96ad..d073f5b 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -595,56 +595,6 @@
}
/**
- * Test that getRollbackDenylistedPackages works correctly for the tag:
- * {@code automatic-rollback-denylisted-app}.
- */
- @Test
- public void automaticRollbackDeny_vending() throws IOException {
- final String contents =
- "<config>\n"
- + " <automatic-rollback-denylisted-app package=\"com.android.vending\" />\n"
- + "</config>";
- final File folder = createTempSubfolder("folder");
- createTempFile(folder, "automatic-rollback-denylisted-app.xml", contents);
-
- readPermissions(folder, /* Grant all permission flags */ ~0);
-
- assertThat(mSysConfig.getAutomaticRollbackDenylistedPackages())
- .containsExactly("com.android.vending");
- }
-
- /**
- * Test that getRollbackDenylistedPackages works correctly for the tag:
- * {@code automatic-rollback-denylisted-app} without any packages.
- */
- @Test
- public void automaticRollbackDeny_empty() throws IOException {
- final String contents =
- "<config>\n"
- + " <automatic-rollback-denylisted-app />\n"
- + "</config>";
- final File folder = createTempSubfolder("folder");
- createTempFile(folder, "automatic-rollback-denylisted-app.xml", contents);
-
- readPermissions(folder, /* Grant all permission flags */ ~0);
-
- assertThat(mSysConfig.getAutomaticRollbackDenylistedPackages()).isEmpty();
- }
-
- /**
- * Test that getRollbackDenylistedPackages works correctly for the tag:
- * {@code automatic-rollback-denylisted-app} without the corresponding config.
- */
- @Test
- public void automaticRollbackDeny_noConfig() throws IOException {
- final File folder = createTempSubfolder("folder");
-
- readPermissions(folder, /* Grant all permission flags */ ~0);
-
- assertThat(mSysConfig.getAutomaticRollbackDenylistedPackages()).isEmpty();
- }
-
- /**
* Tests that readPermissions works correctly for the tag: {@code update-ownership}.
*/
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 6a6fa3f..189dbdc 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -1104,6 +1104,11 @@
verify(mAlarmManager).setExactAndAllowWhileIdle(anyInt(), anyLong(), captor.capture());
assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME,
captor.getValue().getIntent().getPackage());
+
+ mService.cancelScheduledTimeoutLocked(r);
+ verify(mAlarmManager).cancel(captor.capture());
+ assertEquals(PackageManagerService.PLATFORM_PACKAGE_NAME,
+ captor.getValue().getIntent().getPackage());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
index feca326..84925f9 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
@@ -38,6 +38,7 @@
private static final int VENDOR_ID = 0x123;
private static final int PRODUCT_ID = 0x456;
+ private static final int DEVICE_BUS = 0x789;
private static final int META_KEY = KeyEvent.KEYCODE_META_LEFT;
private static final int META_ON = MODIFIER.get(KeyEvent.KEYCODE_META_LEFT);
private static final int ALT_KEY = KeyEvent.KEYCODE_ALT_LEFT;
@@ -224,7 +225,7 @@
@Override
public void setUp() {
super.setUp();
- mPhoneWindowManager.overrideKeyEventSource(VENDOR_ID, PRODUCT_ID);
+ mPhoneWindowManager.overrideKeyEventSource(VENDOR_ID, PRODUCT_ID, DEVICE_BUS);
mPhoneWindowManager.overrideLaunchHome();
mPhoneWindowManager.overrideSearchKeyBehavior(
PhoneWindowManager.SEARCH_BEHAVIOR_TARGET_ACTIVITY);
@@ -240,6 +241,7 @@
int expectedKey, int expectedModifierState) {
sendKeyCombination(testKeys, 0);
mPhoneWindowManager.assertShortcutLogged(VENDOR_ID, PRODUCT_ID, expectedLogEvent,
- expectedKey, expectedModifierState, "Failed while executing " + testName);
+ expectedKey, expectedModifierState, DEVICE_BUS,
+ "Failed while executing " + testName);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 1866767..9aaf291 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -423,10 +423,15 @@
doReturn(isShowing).when(mKeyguardServiceDelegate).isShowing();
}
- void overrideKeyEventSource(int vendorId, int productId) {
- InputDevice device = new InputDevice.Builder().setId(1).setVendorId(vendorId).setProductId(
- productId).setSources(InputDevice.SOURCE_KEYBOARD).setKeyboardType(
- InputDevice.KEYBOARD_TYPE_ALPHABETIC).build();
+ void overrideKeyEventSource(int vendorId, int productId, int deviceBus) {
+ InputDevice device = new InputDevice.Builder()
+ .setId(1)
+ .setVendorId(vendorId)
+ .setProductId(productId)
+ .setDeviceBus(deviceBus)
+ .setSources(InputDevice.SOURCE_KEYBOARD)
+ .setKeyboardType(InputDevice.KEYBOARD_TYPE_ALPHABETIC)
+ .build();
doReturn(mInputManager).when(mContext).getSystemService(eq(InputManager.class));
doReturn(device).when(mInputManager).getInputDevice(anyInt());
}
@@ -604,10 +609,10 @@
}
void assertShortcutLogged(int vendorId, int productId, KeyboardLogEvent logEvent,
- int expectedKey, int expectedModifierState, String errorMsg) {
+ int expectedKey, int expectedModifierState, int deviceBus, String errorMsg) {
waitForIdle();
verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED,
vendorId, productId, logEvent.getIntValue(), new int[]{expectedKey},
- expectedModifierState), description(errorMsg));
+ expectedModifierState, deviceBus), description(errorMsg));
}
}
diff --git a/services/usage/java/com/android/server/usage/BroadcastResponseStatsLogger.java b/services/usage/java/com/android/server/usage/BroadcastResponseStatsLogger.java
index bfc1771..a8fd6f2 100644
--- a/services/usage/java/com/android/server/usage/BroadcastResponseStatsLogger.java
+++ b/services/usage/java/com/android/server/usage/BroadcastResponseStatsLogger.java
@@ -39,6 +39,9 @@
import com.android.internal.util.RingBuffer;
import com.android.server.usage.BroadcastResponseStatsTracker.NotificationEventType;
+import java.util.function.IntFunction;
+import java.util.function.Supplier;
+
public class BroadcastResponseStatsLogger {
private static final int MAX_LOG_SIZE =
@@ -48,10 +51,10 @@
@GuardedBy("mLock")
private final LogBuffer mBroadcastEventsBuffer = new LogBuffer(
- BroadcastEvent.class, MAX_LOG_SIZE);
+ BroadcastEvent::new, BroadcastEvent[]::new, MAX_LOG_SIZE);
@GuardedBy("mLock")
private final LogBuffer mNotificationEventsBuffer = new LogBuffer(
- NotificationEvent.class, MAX_LOG_SIZE);
+ NotificationEvent::new, NotificationEvent[]::new, MAX_LOG_SIZE);
void logBroadcastDispatchEvent(int sourceUid, @NonNull String targetPackage,
UserHandle targetUser, long idForResponseEvent,
@@ -95,8 +98,8 @@
private static final class LogBuffer<T extends Data> extends RingBuffer<T> {
- LogBuffer(Class<T> classType, int capacity) {
- super(classType, capacity);
+ LogBuffer(Supplier<T> newItem, IntFunction<T[]> newBacking, int capacity) {
+ super(newItem, newBacking, capacity);
}
void logBroadcastDispatchEvent(int sourceUid, @NonNull String targetPackage,
@@ -178,7 +181,7 @@
}
}
- public static final class BroadcastEvent implements Data {
+ private static final class BroadcastEvent implements Data {
public int sourceUid;
public int targetUserId;
public int targetUidProcessState;
@@ -198,7 +201,7 @@
}
}
- public static final class NotificationEvent implements Data {
+ private static final class NotificationEvent implements Data {
public int type;
public String packageName;
public int userId;
@@ -215,7 +218,7 @@
}
}
- public interface Data {
+ private interface Data {
void reset();
}
}
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index 9f3b52e..826cf8e 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -35,4 +35,7 @@
"android.hardware.usb-V1.3-java",
"android.hardware.usb-V2-java",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/telecomm/OWNERS b/telecomm/OWNERS
index b57b7c7..bb2ac51 100644
--- a/telecomm/OWNERS
+++ b/telecomm/OWNERS
@@ -6,4 +6,5 @@
rgreenwalt@google.com
grantmenke@google.com
pmadapurmath@google.com
-tjstuart@google.com
\ No newline at end of file
+tjstuart@google.com
+huiwang@google.com
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 287aa65..7607c64 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -15,4 +15,4 @@
per-file CarrierConfigManager.java=amruthr@google.com,tgunn@google.com,rgreenwalt@google.com,satk@google.com
#Domain Selection is jointly owned, add additional owners for domain selection specific files
-per-file TransportSelectorCallback.java,WwanSelectorCallback.java,DomainSelectionService.java,DomainSelectionService.aidl,DomainSelector.java,EmergencyRegResult.java,EmergencyRegResult.aidl,IDomainSelectionServiceController.aidl,IDomainSelector.aidl,ITransportSelectorCallback.aidl,ITransportSelectorResultCallback.aidl,IWwanSelectorCallback.aidl,IWwanSelectorResultCallback.aidl=hwangoo@google.com,forestchoi@google.com,avinashmp@google.com,mkoon@google.com,seheele@google.com,radhikaagrawal@google.com
+per-file TransportSelectorCallback.java,WwanSelectorCallback.java,DomainSelectionService.java,DomainSelectionService.aidl,DomainSelector.java,EmergencyRegResult.java,EmergencyRegResult.aidl,IDomainSelectionServiceController.aidl,IDomainSelector.aidl,ITransportSelectorCallback.aidl,ITransportSelectorResultCallback.aidl,IWwanSelectorCallback.aidl,IWwanSelectorResultCallback.aidl=hwangoo@google.com,forestchoi@google.com,avinashmp@google.com,mkoon@google.com,seheele@google.com,radhikaagrawal@google.com,jdyou@google.com
diff --git a/telephony/java/android/telephony/AnomalyReporter.java b/telephony/java/android/telephony/AnomalyReporter.java
index db38f88..575ec27 100644
--- a/telephony/java/android/telephony/AnomalyReporter.java
+++ b/telephony/java/android/telephony/AnomalyReporter.java
@@ -187,14 +187,15 @@
}
for (ResolveInfo r : packages) {
- if (r.activityInfo == null
- || pm.checkPermission(
+ if (r.activityInfo == null) {
+ Rlog.w(TAG, "Found package without activity");
+ continue;
+ } else if (pm.checkPermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
r.activityInfo.packageName)
- != PackageManager.PERMISSION_GRANTED) {
- Rlog.w(TAG,
- "Found package without proper permissions or no activity"
- + r.activityInfo.packageName);
+ != PackageManager.PERMISSION_GRANTED) {
+ Rlog.w(TAG, "Found package without proper permissions"
+ + r.activityInfo.packageName);
continue;
}
Rlog.d(TAG, "Found a valid package " + r.activityInfo.packageName);
diff --git a/test-base/Android.bp b/test-base/Android.bp
index 527159a..70a9540 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -120,12 +120,13 @@
path: "src",
}
-// Make the current.txt available for use by the cts/tests/signature tests.
+// Make the current.txt available for use by the cts/tests/signature and /vendor tests.
// ========================================================================
filegroup {
name: "android-test-base-current.txt",
visibility: [
"//cts/tests/signature/api",
+ "//vendor:__subpackages__",
],
srcs: [
"api/current.txt",
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 22320fd..7c4d12e 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -54,12 +54,13 @@
dist_group: "android",
}
-// Make the current.txt available for use by the cts/tests/signature tests.
+// Make the current.txt available for use by the cts/tests/signature and /vendor tests.
// ========================================================================
filegroup {
name: "android-test-mock-current.txt",
visibility: [
"//cts/tests/signature/api",
+ "//vendor:__subpackages__",
],
srcs: [
"api/current.txt",
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
index 13a5dac..21e09d3 100644
--- a/test-runner/Android.bp
+++ b/test-runner/Android.bp
@@ -79,12 +79,13 @@
],
}
-// Make the current.txt available for use by the cts/tests/signature tests.
+// Make the current.txt available for use by the cts/tests/signature and /vendor tests.
// ========================================================================
filegroup {
name: "android-test-runner-current.txt",
visibility: [
"//cts/tests/signature/api",
+ "//vendor:__subpackages__",
],
srcs: [
"api/current.txt",
diff --git a/tests/BootImageProfileTest/AndroidTest.xml b/tests/BootImageProfileTest/AndroidTest.xml
index 7e97fa3..9b527dc 100644
--- a/tests/BootImageProfileTest/AndroidTest.xml
+++ b/tests/BootImageProfileTest/AndroidTest.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<configuration description="Config for BootImageProfileTest">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
<!-- do not use DeviceSetup#set-property because it reboots the device b/136200738.
furthermore the changes in /data/local.prop don't actually seem to get picked up.
-->
diff --git a/tests/Camera2Tests/CameraToo/tests/Android.bp b/tests/Camera2Tests/CameraToo/tests/Android.bp
new file mode 100644
index 0000000..8339a2c
--- /dev/null
+++ b/tests/Camera2Tests/CameraToo/tests/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "frameworks_base_license",
+ ],
+}
+
+android_test {
+ name: "CameraTooTests",
+ instrumentation_for: "CameraToo",
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+ static_libs: [
+ "androidx.test.rules",
+ "mockito-target-minus-junit4",
+ ],
+ data: [
+ ":CameraToo",
+ ],
+}
diff --git a/tests/Camera2Tests/CameraToo/tests/Android.mk b/tests/Camera2Tests/CameraToo/tests/Android.mk
deleted file mode 100644
index dfa64f1..0000000
--- a/tests/Camera2Tests/CameraToo/tests/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := CameraTooTests
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../NOTICE
-LOCAL_INSTRUMENTATION_FOR := CameraToo
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules mockito-target-minus-junit4
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Camera2Tests/CameraToo/tests/AndroidTest.xml b/tests/Camera2Tests/CameraToo/tests/AndroidTest.xml
new file mode 100644
index 0000000..884c095
--- /dev/null
+++ b/tests/Camera2Tests/CameraToo/tests/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs CameraToo tests.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CameraTooTests.apk" />
+ <option name="test-file-name" value="CameraToo.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.example.android.camera2.cameratoo.tests" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ </test>
+</configuration>
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index 292fbcb..d996ee6 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_input_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/tests/Input/AndroidTest.xml b/tests/Input/AndroidTest.xml
index c62db1ea..13b5f0d 100644
--- a/tests/Input/AndroidTest.xml
+++ b/tests/Input/AndroidTest.xml
@@ -4,6 +4,7 @@
-->
<configuration description="Runs Input Tests">
<option name="test-tag" value="InputTests" />
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on" />
diff --git a/tests/Input/src/com/android/test/input/InputDeviceTest.java b/tests/Input/src/com/android/test/input/InputDeviceTest.java
index d075b5f..5434c82 100644
--- a/tests/Input/src/com/android/test/input/InputDeviceTest.java
+++ b/tests/Input/src/com/android/test/input/InputDeviceTest.java
@@ -51,6 +51,7 @@
assertEquals(device.getName(), outDevice.getName());
assertEquals(device.getVendorId(), outDevice.getVendorId());
assertEquals(device.getProductId(), outDevice.getProductId());
+ assertEquals(device.getDeviceBus(), outDevice.getDeviceBus());
assertEquals(device.getDescriptor(), outDevice.getDescriptor());
assertEquals(device.isExternal(), outDevice.isExternal());
assertEquals(device.getSources(), outDevice.getSources());
@@ -79,6 +80,7 @@
.setName("Test Device " + DEVICE_ID)
.setVendorId(44)
.setProductId(45)
+ .setDeviceBus(3)
.setDescriptor("descriptor")
.setExternal(true)
.setSources(InputDevice.SOURCE_HDMI)
diff --git a/tests/InputMethodStressTest/Android.bp b/tests/InputMethodStressTest/Android.bp
index 58ceb3f..5ed8d8d 100644
--- a/tests/InputMethodStressTest/Android.bp
+++ b/tests/InputMethodStressTest/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_input_method_framework",
default_applicable_licenses: ["frameworks_base_license"],
}
diff --git a/tests/Internal/src/com/android/internal/protolog/OWNERS b/tests/Internal/src/com/android/internal/protolog/OWNERS
new file mode 100644
index 0000000..18cf2be
--- /dev/null
+++ b/tests/Internal/src/com/android/internal/protolog/OWNERS
@@ -0,0 +1,3 @@
+# ProtoLog owners
+# Bug component: 1157642
+include platform/development:/tools/winscope/OWNERS
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index d7fa124..755636a 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -70,6 +70,7 @@
import java.io.File;
import java.io.FileOutputStream;
+import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -107,10 +108,13 @@
private ConnectivityModuleConnector mConnectivityModuleConnector;
@Mock
private PackageManager mMockPackageManager;
+ // Mock only sysprop apis
+ private PackageWatchdog.BootThreshold mSpyBootThreshold;
@Captor
private ArgumentCaptor<ConnectivityModuleHealthListener> mConnectivityModuleCallbackCaptor;
private MockitoSession mSession;
private HashMap<String, String> mSystemSettingsMap;
+ private HashMap<String, String> mCrashRecoveryPropertiesMap;
private boolean retry(Supplier<Boolean> supplier) throws Exception {
for (int i = 0; i < RETRY_MAX_COUNT; ++i) {
@@ -1416,6 +1420,8 @@
PackageWatchdog watchdog =
new PackageWatchdog(mSpyContext, policyFile, handler, handler, controller,
mConnectivityModuleConnector, mTestClock);
+ mockCrashRecoveryProperties(watchdog);
+
// Verify controller is not automatically started
assertThat(controller.mIsEnabled).isFalse();
if (withPackagesReady) {
@@ -1432,6 +1438,71 @@
return watchdog;
}
+ // Mock CrashRecoveryProperties as they cannot be accessed due to SEPolicy restrictions
+ private void mockCrashRecoveryProperties(PackageWatchdog watchdog) {
+ try {
+ mSpyBootThreshold = spy(watchdog.new BootThreshold(
+ PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
+ PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
+ mCrashRecoveryPropertiesMap = new HashMap<>();
+
+ doAnswer((Answer<Integer>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.rescue_boot_count", "0");
+ return Integer.parseInt(storedValue);
+ }).when(mSpyBootThreshold).getCount();
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ int count = invocationOnMock.getArgument(0);
+ mCrashRecoveryPropertiesMap.put("crashrecovery.rescue_boot_count",
+ Integer.toString(count));
+ return null;
+ }).when(mSpyBootThreshold).setCount(anyInt());
+
+ doAnswer((Answer<Integer>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.boot_mitigation_count", "0");
+ return Integer.parseInt(storedValue);
+ }).when(mSpyBootThreshold).getMitigationCount();
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ int count = invocationOnMock.getArgument(0);
+ mCrashRecoveryPropertiesMap.put("crashrecovery.boot_mitigation_count",
+ Integer.toString(count));
+ return null;
+ }).when(mSpyBootThreshold).setMitigationCount(anyInt());
+
+ doAnswer((Answer<Long>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.rescue_boot_start", "0");
+ return Long.parseLong(storedValue);
+ }).when(mSpyBootThreshold).getStart();
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ long count = invocationOnMock.getArgument(0);
+ mCrashRecoveryPropertiesMap.put("crashrecovery.rescue_boot_start",
+ Long.toString(count));
+ return null;
+ }).when(mSpyBootThreshold).setStart(anyLong());
+
+ doAnswer((Answer<Long>) invocationOnMock -> {
+ String storedValue = mCrashRecoveryPropertiesMap
+ .getOrDefault("crashrecovery.boot_mitigation_start", "0");
+ return Long.parseLong(storedValue);
+ }).when(mSpyBootThreshold).getMitigationStart();
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ long count = invocationOnMock.getArgument(0);
+ mCrashRecoveryPropertiesMap.put("crashrecovery.boot_mitigation_start",
+ Long.toString(count));
+ return null;
+ }).when(mSpyBootThreshold).setMitigationStart(anyLong());
+
+ Field mBootThresholdField = watchdog.getClass().getDeclaredField("mBootThreshold");
+ mBootThresholdField.setAccessible(true);
+ mBootThresholdField.set(watchdog, mSpyBootThreshold);
+ } catch (Exception e) {
+ // tests will fail, just printing the error
+ System.out.println("Error detected while spying BootThreshold" + e.getMessage());
+ }
+ }
+
private static class TestObserver implements PackageHealthObserver {
private final String mName;
private int mImpact;
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index cbdcb88..518183f 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -30,6 +30,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.os.UserManager;
@@ -146,7 +147,8 @@
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
// Upgrade from v1 to v2, with rollbacks enabled.
- Install.single(TestApp.A2).setEnableRollback().commit();
+ Install.single(TestApp.A2).setEnableRollback().setRollbackImpactLevel(
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH).commit();
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
// The app should now be available for rollback.
@@ -154,6 +156,8 @@
assertThat(available).isNotStaged();
assertThat(available).packagesContainsExactly(
Rollback.from(TestApp.A2).to(TestApp.A1));
+ assertThat(available.getRollbackImpactLevel()).isEqualTo(
+ PackageManager.ROLLBACK_USER_IMPACT_HIGH);
// We should not have received any rollback requests yet.
// TODO: Possibly flaky if, by chance, some other app on device
@@ -264,6 +268,8 @@
RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B);
assertThat(rollbackB).packagesContainsExactly(
Rollback.from(TestApp.B2).to(TestApp.B1));
+ assertThat(rollbackB.getRollbackImpactLevel()).isEqualTo(
+ PackageManager.ROLLBACK_USER_IMPACT_LOW);
// Register rollback committed receiver
RollbackBroadcastReceiver rollbackReceiver = new RollbackBroadcastReceiver();
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index 23efe54..2751141 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_framework_android_packages",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/tests/UpdatableSystemFontTest/Android.bp b/tests/UpdatableSystemFontTest/Android.bp
index ddb3649..12d4338 100644
--- a/tests/UpdatableSystemFontTest/Android.bp
+++ b/tests/UpdatableSystemFontTest/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_android_gpu",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/Android.bp b/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/Android.bp
index ed34fa9..0f21035 100644
--- a/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/Android.bp
+++ b/tests/UpdatableSystemFontTest/EmojiRenderingTestApp/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_android_gpu",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/tests/UpdatableSystemFontTest/testdata/Android.bp b/tests/UpdatableSystemFontTest/testdata/Android.bp
index 0bdb3a8..38355530 100644
--- a/tests/UpdatableSystemFontTest/testdata/Android.bp
+++ b/tests/UpdatableSystemFontTest/testdata/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_android_gpu",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/tests/vcn/Android.bp b/tests/vcn/Android.bp
index 228520e..bc1df75 100644
--- a/tests/vcn/Android.bp
+++ b/tests/vcn/Android.bp
@@ -3,6 +3,7 @@
//########################################################################
package {
+ default_team: "trendy_team_enigma",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index f846164..20b7f1f 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -269,6 +269,7 @@
@Test
public void testCreatedTransformsAreApplied() throws Exception {
verifyVcnTransformsApplied(mGatewayConnection, false /* expectForwardTransform */);
+ verify(mUnderlyingNetworkController).updateInboundTransform(any(), any());
}
@Test
@@ -327,6 +328,8 @@
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(direction), anyInt(), any());
}
+ verify(mUnderlyingNetworkController).updateInboundTransform(any(), any());
+
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
final List<ChildSaProposal> saProposals =
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
index 692c8a8..49665f7 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
@@ -27,15 +27,18 @@
import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR;
+import static com.android.server.vcn.VcnGatewayConnection.SAFEMODE_TIMEOUT_SECONDS;
import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
+import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
@@ -55,6 +58,7 @@
import android.net.TelephonyNetworkSpecifier;
import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnGatewayConnectionConfigTest;
+import android.net.vcn.VcnManager;
import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
import android.os.ParcelUuid;
@@ -81,6 +85,7 @@
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
/** Tests for TelephonySubscriptionTracker */
@RunWith(AndroidJUnit4.class)
@@ -352,4 +357,71 @@
any(Executor.class),
any(ConnectivityDiagnosticsCallback.class));
}
+
+ private void verifyGetSafeModeTimeoutMs(
+ boolean isInTestMode,
+ boolean isConfigTimeoutSupported,
+ PersistableBundleWrapper carrierConfig,
+ long expectedTimeoutMs)
+ throws Exception {
+ doReturn(isInTestMode).when(mVcnContext).isInTestMode();
+ doReturn(isConfigTimeoutSupported).when(mVcnContext).isFlagSafeModeTimeoutConfigEnabled();
+
+ final TelephonySubscriptionSnapshot snapshot = mock(TelephonySubscriptionSnapshot.class);
+ doReturn(carrierConfig).when(snapshot).getCarrierConfigForSubGrp(TEST_SUB_GRP);
+
+ final long result =
+ VcnGatewayConnection.getSafeModeTimeoutMs(mVcnContext, snapshot, TEST_SUB_GRP);
+
+ assertEquals(expectedTimeoutMs, result);
+ }
+
+ @Test
+ public void testGetSafeModeTimeoutMs_configTimeoutUnsupported() throws Exception {
+ verifyGetSafeModeTimeoutMs(
+ false /* isInTestMode */,
+ false /* isConfigTimeoutSupported */,
+ null /* carrierConfig */,
+ TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
+ }
+
+ @Test
+ public void testGetSafeModeTimeoutMs_configTimeoutSupported() throws Exception {
+ final int carrierConfigTimeoutSeconds = 20;
+ final PersistableBundleWrapper carrierConfig = mock(PersistableBundleWrapper.class);
+ doReturn(carrierConfigTimeoutSeconds)
+ .when(carrierConfig)
+ .getInt(eq(VcnManager.VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY), anyInt());
+
+ verifyGetSafeModeTimeoutMs(
+ false /* isInTestMode */,
+ true /* isConfigTimeoutSupported */,
+ carrierConfig,
+ TimeUnit.SECONDS.toMillis(carrierConfigTimeoutSeconds));
+ }
+
+ @Test
+ public void testGetSafeModeTimeoutMs_configTimeoutSupported_carrierConfigNull()
+ throws Exception {
+ verifyGetSafeModeTimeoutMs(
+ false /* isInTestMode */,
+ true /* isConfigTimeoutSupported */,
+ null /* carrierConfig */,
+ TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
+ }
+
+ @Test
+ public void testGetSafeModeTimeoutMs_configTimeoutOverrideTestModeDefault() throws Exception {
+ final int carrierConfigTimeoutSeconds = 20;
+ final PersistableBundleWrapper carrierConfig = mock(PersistableBundleWrapper.class);
+ doReturn(carrierConfigTimeoutSeconds)
+ .when(carrierConfig)
+ .getInt(eq(VcnManager.VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY), anyInt());
+
+ verifyGetSafeModeTimeoutMs(
+ true /* isInTestMode */,
+ true /* isConfigTimeoutSupported */,
+ carrierConfig,
+ TimeUnit.SECONDS.toMillis(carrierConfigTimeoutSeconds));
+ }
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index edced87..e29e462 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -67,6 +67,8 @@
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback;
+import com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
+import com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
import com.android.server.vcn.VcnGatewayConnection.VcnWakeLock;
import com.android.server.vcn.routeselection.UnderlyingNetworkController;
import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
@@ -118,13 +120,7 @@
NetworkCapabilities networkCapabilities,
LinkProperties linkProperties,
boolean isBlocked) {
- return new UnderlyingNetworkRecord(
- network,
- networkCapabilities,
- linkProperties,
- isBlocked,
- false /* isSelected */,
- 0 /* priorityClass */);
+ return new UnderlyingNetworkRecord(network, networkCapabilities, linkProperties, isBlocked);
}
protected static final String TEST_TCP_BUFFER_SIZES_1 = "1,2,3,4";
@@ -226,6 +222,9 @@
doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper();
doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider();
doReturn(mFeatureFlags).when(mVcnContext).getFeatureFlags();
+ doReturn(true).when(mVcnContext).isFlagSafeModeTimeoutConfigEnabled();
+ doReturn(true).when(mVcnContext).isFlagIpSecTransformStateEnabled();
+ doReturn(true).when(mVcnContext).isFlagNetworkMetricMonitorEnabled();
doReturn(mUnderlyingNetworkController)
.when(mDeps)
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
new file mode 100644
index 0000000..1d7be2f
--- /dev/null
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
@@ -0,0 +1,419 @@
+/*
+ * 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.vcn.routeselection;
+
+import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY;
+import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY;
+
+import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.PACKET_LOSS_UNAVALAIBLE;
+import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.net.IpSecTransformState;
+import android.os.OutcomeReceiver;
+import android.os.PowerManager;
+
+import com.android.server.vcn.routeselection.IpSecPacketLossDetector.PacketLossCalculator;
+import com.android.server.vcn.routeselection.NetworkMetricMonitor.IpSecTransformWrapper;
+import com.android.server.vcn.routeselection.NetworkMetricMonitor.NetworkMetricMonitorCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.concurrent.TimeUnit;
+
+public class IpSecPacketLossDetectorTest extends NetworkEvaluationTestBase {
+ private static final String TAG = IpSecPacketLossDetectorTest.class.getSimpleName();
+
+ private static final int REPLAY_BITMAP_LEN_BYTE = 512;
+ private static final int REPLAY_BITMAP_LEN_BIT = REPLAY_BITMAP_LEN_BYTE * 8;
+ private static final int IPSEC_PACKET_LOSS_PERCENT_THRESHOLD = 5;
+ private static final long POLL_IPSEC_STATE_INTERVAL_MS = TimeUnit.SECONDS.toMillis(30L);
+
+ @Mock private IpSecTransformWrapper mIpSecTransform;
+ @Mock private NetworkMetricMonitorCallback mMetricMonitorCallback;
+ @Mock private PersistableBundleWrapper mCarrierConfig;
+ @Mock private IpSecPacketLossDetector.Dependencies mDependencies;
+ @Spy private PacketLossCalculator mPacketLossCalculator = new PacketLossCalculator();
+
+ @Captor private ArgumentCaptor<OutcomeReceiver> mTransformStateReceiverCaptor;
+ @Captor private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
+
+ private IpSecPacketLossDetector mIpSecPacketLossDetector;
+ private IpSecTransformState mTransformStateInitial;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ mTransformStateInitial = newTransformState(0, 0, newReplayBitmap(0));
+
+ when(mCarrierConfig.getInt(
+ eq(VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY), anyInt()))
+ .thenReturn((int) TimeUnit.MILLISECONDS.toSeconds(POLL_IPSEC_STATE_INTERVAL_MS));
+ when(mCarrierConfig.getInt(
+ eq(VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY),
+ anyInt()))
+ .thenReturn(IPSEC_PACKET_LOSS_PERCENT_THRESHOLD);
+
+ when(mDependencies.getPacketLossCalculator()).thenReturn(mPacketLossCalculator);
+
+ mIpSecPacketLossDetector =
+ new IpSecPacketLossDetector(
+ mVcnContext,
+ mNetwork,
+ mCarrierConfig,
+ mMetricMonitorCallback,
+ mDependencies);
+ }
+
+ private static IpSecTransformState newTransformState(
+ long rxSeqNo, long packtCount, byte[] replayBitmap) {
+ return new IpSecTransformState.Builder()
+ .setRxHighestSequenceNumber(rxSeqNo)
+ .setPacketCount(packtCount)
+ .setReplayBitmap(replayBitmap)
+ .build();
+ }
+
+ private static byte[] newReplayBitmap(int receivedPktCnt) {
+ final BitSet bitSet = new BitSet(REPLAY_BITMAP_LEN_BIT);
+ for (int i = 0; i < receivedPktCnt; i++) {
+ bitSet.set(i);
+ }
+ return Arrays.copyOf(bitSet.toByteArray(), REPLAY_BITMAP_LEN_BYTE);
+ }
+
+ private void verifyStopped() {
+ assertFalse(mIpSecPacketLossDetector.isStarted());
+ assertFalse(mIpSecPacketLossDetector.isValidationFailed());
+ assertNull(mIpSecPacketLossDetector.getLastTransformState());
+
+ // No event scheduled
+ mTestLooper.moveTimeForward(POLL_IPSEC_STATE_INTERVAL_MS);
+ assertNull(mTestLooper.nextMessage());
+ }
+
+ @Test
+ public void testInitialization() throws Exception {
+ assertFalse(mIpSecPacketLossDetector.isSelectedUnderlyingNetwork());
+ verifyStopped();
+ }
+
+ private OutcomeReceiver<IpSecTransformState, RuntimeException>
+ startMonitorAndCaptureStateReceiver() {
+ mIpSecPacketLossDetector.setIsSelectedUnderlyingNetwork(true /* setIsSelected */);
+ mIpSecPacketLossDetector.setInboundTransformInternal(mIpSecTransform);
+
+ // Trigger the runnable
+ mTestLooper.dispatchAll();
+
+ verify(mIpSecTransform)
+ .requestIpSecTransformState(any(), mTransformStateReceiverCaptor.capture());
+ return mTransformStateReceiverCaptor.getValue();
+ }
+
+ @Test
+ public void testStartMonitor() throws Exception {
+ final OutcomeReceiver<IpSecTransformState, RuntimeException> xfrmStateReceiver =
+ startMonitorAndCaptureStateReceiver();
+
+ assertTrue(mIpSecPacketLossDetector.isStarted());
+ assertFalse(mIpSecPacketLossDetector.isValidationFailed());
+ assertTrue(mIpSecPacketLossDetector.isSelectedUnderlyingNetwork());
+ assertEquals(mIpSecTransform, mIpSecPacketLossDetector.getInboundTransformInternal());
+
+ // Mock receiving a state
+ xfrmStateReceiver.onResult(mTransformStateInitial);
+
+ // Verify the first polled state is stored
+ assertEquals(mTransformStateInitial, mIpSecPacketLossDetector.getLastTransformState());
+ verify(mPacketLossCalculator, never())
+ .getPacketLossRatePercentage(any(), any(), anyString());
+
+ // Verify next poll is scheduled
+ assertNull(mTestLooper.nextMessage());
+ mTestLooper.moveTimeForward(POLL_IPSEC_STATE_INTERVAL_MS);
+ assertNotNull(mTestLooper.nextMessage());
+ }
+
+ @Test
+ public void testStartedMonitor_enterDozeMoze() throws Exception {
+ final OutcomeReceiver<IpSecTransformState, RuntimeException> xfrmStateReceiver =
+ startMonitorAndCaptureStateReceiver();
+
+ // Mock receiving a state
+ xfrmStateReceiver.onResult(mTransformStateInitial);
+ assertEquals(mTransformStateInitial, mIpSecPacketLossDetector.getLastTransformState());
+
+ // Mock entering doze mode
+ final Intent intent = mock(Intent.class);
+ when(intent.getAction()).thenReturn(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ when(mPowerManagerService.isDeviceIdleMode()).thenReturn(true);
+
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any());
+ final BroadcastReceiver broadcastReceiver = mBroadcastReceiverCaptor.getValue();
+ broadcastReceiver.onReceive(mContext, intent);
+
+ assertNull(mIpSecPacketLossDetector.getLastTransformState());
+ }
+
+ @Test
+ public void testStartedMonitor_updateInboundTransform() throws Exception {
+ final OutcomeReceiver<IpSecTransformState, RuntimeException> xfrmStateReceiver =
+ startMonitorAndCaptureStateReceiver();
+
+ // Mock receiving a state
+ xfrmStateReceiver.onResult(mTransformStateInitial);
+ assertEquals(mTransformStateInitial, mIpSecPacketLossDetector.getLastTransformState());
+
+ // Update the inbound transform
+ final IpSecTransformWrapper newTransform = mock(IpSecTransformWrapper.class);
+ mIpSecPacketLossDetector.setInboundTransformInternal(newTransform);
+
+ // Verifications
+ assertNull(mIpSecPacketLossDetector.getLastTransformState());
+ mTestLooper.moveTimeForward(POLL_IPSEC_STATE_INTERVAL_MS);
+ mTestLooper.dispatchAll();
+ verify(newTransform).requestIpSecTransformState(any(), any());
+ }
+
+ @Test
+ public void testStartedMonitor_updateCarrierConfig() throws Exception {
+ startMonitorAndCaptureStateReceiver();
+
+ final int additionalPollIntervalMs = (int) TimeUnit.SECONDS.toMillis(10L);
+ when(mCarrierConfig.getInt(
+ eq(VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY), anyInt()))
+ .thenReturn(
+ (int)
+ TimeUnit.MILLISECONDS.toSeconds(
+ POLL_IPSEC_STATE_INTERVAL_MS + additionalPollIntervalMs));
+ mIpSecPacketLossDetector.setCarrierConfig(mCarrierConfig);
+ mTestLooper.dispatchAll();
+
+ // The already scheduled event is still fired with the old timeout
+ mTestLooper.moveTimeForward(POLL_IPSEC_STATE_INTERVAL_MS);
+ mTestLooper.dispatchAll();
+
+ // The next scheduled event will take 10 more seconds to fire
+ mTestLooper.moveTimeForward(POLL_IPSEC_STATE_INTERVAL_MS);
+ assertNull(mTestLooper.nextMessage());
+ mTestLooper.moveTimeForward(additionalPollIntervalMs);
+ assertNotNull(mTestLooper.nextMessage());
+ }
+
+ @Test
+ public void testStopMonitor() throws Exception {
+ mIpSecPacketLossDetector.setIsSelectedUnderlyingNetwork(true /* setIsSelected */);
+ mIpSecPacketLossDetector.setInboundTransformInternal(mIpSecTransform);
+
+ assertTrue(mIpSecPacketLossDetector.isStarted());
+ assertNotNull(mTestLooper.nextMessage());
+
+ // Unselect the monitor
+ mIpSecPacketLossDetector.setIsSelectedUnderlyingNetwork(false /* setIsSelected */);
+ verifyStopped();
+ }
+
+ @Test
+ public void testClose() throws Exception {
+ mIpSecPacketLossDetector.setIsSelectedUnderlyingNetwork(true /* setIsSelected */);
+ mIpSecPacketLossDetector.setInboundTransformInternal(mIpSecTransform);
+
+ assertTrue(mIpSecPacketLossDetector.isStarted());
+ assertNotNull(mTestLooper.nextMessage());
+
+ // Stop the monitor
+ mIpSecPacketLossDetector.close();
+ verifyStopped();
+ verify(mIpSecTransform).close();
+ }
+
+ @Test
+ public void testTransformStateReceiverOnResultWhenStopped() throws Exception {
+ final OutcomeReceiver<IpSecTransformState, RuntimeException> xfrmStateReceiver =
+ startMonitorAndCaptureStateReceiver();
+ xfrmStateReceiver.onResult(mTransformStateInitial);
+
+ // Unselect the monitor
+ mIpSecPacketLossDetector.setIsSelectedUnderlyingNetwork(false /* setIsSelected */);
+ verifyStopped();
+
+ xfrmStateReceiver.onResult(newTransformState(1, 1, newReplayBitmap(1)));
+ verify(mPacketLossCalculator, never())
+ .getPacketLossRatePercentage(any(), any(), anyString());
+ }
+
+ @Test
+ public void testTransformStateReceiverOnError() throws Exception {
+ final OutcomeReceiver<IpSecTransformState, RuntimeException> xfrmStateReceiver =
+ startMonitorAndCaptureStateReceiver();
+ xfrmStateReceiver.onResult(mTransformStateInitial);
+
+ xfrmStateReceiver.onError(new RuntimeException("Test"));
+ verify(mPacketLossCalculator, never())
+ .getPacketLossRatePercentage(any(), any(), anyString());
+ }
+
+ private void checkHandleLossRate(
+ int mockPacketLossRate, boolean isLastStateExpectedToUpdate, boolean isCallbackExpected)
+ throws Exception {
+ final OutcomeReceiver<IpSecTransformState, RuntimeException> xfrmStateReceiver =
+ startMonitorAndCaptureStateReceiver();
+ doReturn(mockPacketLossRate)
+ .when(mPacketLossCalculator)
+ .getPacketLossRatePercentage(any(), any(), anyString());
+
+ // Mock receiving two states with mTransformStateInitial and an arbitrary transformNew
+ final IpSecTransformState transformNew = newTransformState(1, 1, newReplayBitmap(1));
+ xfrmStateReceiver.onResult(mTransformStateInitial);
+ xfrmStateReceiver.onResult(transformNew);
+
+ // Verifications
+ verify(mPacketLossCalculator)
+ .getPacketLossRatePercentage(
+ eq(mTransformStateInitial), eq(transformNew), anyString());
+
+ if (isLastStateExpectedToUpdate) {
+ assertEquals(transformNew, mIpSecPacketLossDetector.getLastTransformState());
+ } else {
+ assertEquals(mTransformStateInitial, mIpSecPacketLossDetector.getLastTransformState());
+ }
+
+ if (isCallbackExpected) {
+ verify(mMetricMonitorCallback).onValidationResultReceived();
+ } else {
+ verify(mMetricMonitorCallback, never()).onValidationResultReceived();
+ }
+ }
+
+ @Test
+ public void testHandleLossRate_validationPass() throws Exception {
+ checkHandleLossRate(
+ 2, true /* isLastStateExpectedToUpdate */, true /* isCallbackExpected */);
+ }
+
+ @Test
+ public void testHandleLossRate_validationFail() throws Exception {
+ checkHandleLossRate(
+ 22, true /* isLastStateExpectedToUpdate */, true /* isCallbackExpected */);
+ }
+
+ @Test
+ public void testHandleLossRate_resultUnavalaible() throws Exception {
+ checkHandleLossRate(
+ PACKET_LOSS_UNAVALAIBLE,
+ false /* isLastStateExpectedToUpdate */,
+ false /* isCallbackExpected */);
+ }
+
+ private void checkGetPacketLossRate(
+ IpSecTransformState oldState, IpSecTransformState newState, int expectedLossRate)
+ throws Exception {
+ assertEquals(
+ expectedLossRate,
+ mPacketLossCalculator.getPacketLossRatePercentage(oldState, newState, TAG));
+ }
+
+ private void checkGetPacketLossRate(
+ IpSecTransformState oldState,
+ int rxSeqNo,
+ int packetCount,
+ int packetInWin,
+ int expectedDataLossRate)
+ throws Exception {
+ final IpSecTransformState newState =
+ newTransformState(rxSeqNo, packetCount, newReplayBitmap(packetInWin));
+ checkGetPacketLossRate(oldState, newState, expectedDataLossRate);
+ }
+
+ @Test
+ public void testGetPacketLossRate_replayWindowUnchanged() throws Exception {
+ checkGetPacketLossRate(
+ mTransformStateInitial, mTransformStateInitial, PACKET_LOSS_UNAVALAIBLE);
+ checkGetPacketLossRate(mTransformStateInitial, 3000, 2000, 2000, PACKET_LOSS_UNAVALAIBLE);
+ }
+
+ @Test
+ public void testGetPacketLossRate_againstInitialState() throws Exception {
+ checkGetPacketLossRate(mTransformStateInitial, 7000, 7001, 4096, 0);
+ checkGetPacketLossRate(mTransformStateInitial, 7000, 6000, 4096, 15);
+ checkGetPacketLossRate(mTransformStateInitial, 7000, 6000, 4000, 14);
+ }
+
+ @Test
+ public void testGetPktLossRate_oldHiSeqSmallerThanWinSize_overlappedWithNewWin()
+ throws Exception {
+ final IpSecTransformState oldState = newTransformState(2000, 1500, newReplayBitmap(1500));
+
+ checkGetPacketLossRate(oldState, 5000, 5001, 4096, 0);
+ checkGetPacketLossRate(oldState, 5000, 4000, 4096, 29);
+ checkGetPacketLossRate(oldState, 5000, 4000, 4000, 27);
+ }
+
+ @Test
+ public void testGetPktLossRate_oldHiSeqSmallerThanWinSize_notOverlappedWithNewWin()
+ throws Exception {
+ final IpSecTransformState oldState = newTransformState(2000, 1500, newReplayBitmap(1500));
+
+ checkGetPacketLossRate(oldState, 7000, 7001, 4096, 0);
+ checkGetPacketLossRate(oldState, 7000, 5000, 4096, 37);
+ checkGetPacketLossRate(oldState, 7000, 5000, 3000, 21);
+ }
+
+ @Test
+ public void testGetPktLossRate_oldHiSeqLargerThanWinSize_overlappedWithNewWin()
+ throws Exception {
+ final IpSecTransformState oldState = newTransformState(10000, 5000, newReplayBitmap(3000));
+
+ checkGetPacketLossRate(oldState, 12000, 8096, 4096, 0);
+ checkGetPacketLossRate(oldState, 12000, 7000, 4096, 36);
+ checkGetPacketLossRate(oldState, 12000, 7000, 3000, 0);
+ }
+
+ @Test
+ public void testGetPktLossRate_oldHiSeqLargerThanWinSize_notOverlappedWithNewWin()
+ throws Exception {
+ final IpSecTransformState oldState = newTransformState(10000, 5000, newReplayBitmap(3000));
+
+ checkGetPacketLossRate(oldState, 20000, 16096, 4096, 0);
+ checkGetPacketLossRate(oldState, 20000, 14000, 4096, 19);
+ checkGetPacketLossRate(oldState, 20000, 14000, 3000, 10);
+ }
+}
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
new file mode 100644
index 0000000..381c574
--- /dev/null
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
@@ -0,0 +1,150 @@
+/*
+ * 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.vcn.routeselection;
+
+import static com.android.server.vcn.VcnTestUtils.setupSystemService;
+import static com.android.server.vcn.routeselection.UnderlyingNetworkControllerTest.getLinkPropertiesWithName;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.IpSecConfig;
+import android.net.IpSecTransform;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.FeatureFlags;
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IThermalService;
+import android.os.ParcelUuid;
+import android.os.PowerManager;
+import android.os.test.TestLooper;
+import android.telephony.TelephonyManager;
+
+import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
+import com.android.server.vcn.VcnContext;
+import com.android.server.vcn.VcnNetworkProvider;
+
+import org.junit.Before;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Set;
+import java.util.UUID;
+
+public abstract class NetworkEvaluationTestBase {
+ protected static final String SSID = "TestWifi";
+ protected static final String SSID_OTHER = "TestWifiOther";
+ protected static final String PLMN_ID = "123456";
+ protected static final String PLMN_ID_OTHER = "234567";
+
+ protected static final int SUB_ID = 1;
+ protected static final int WIFI_RSSI = -60;
+ protected static final int WIFI_RSSI_HIGH = -50;
+ protected static final int WIFI_RSSI_LOW = -80;
+ protected static final int CARRIER_ID = 1;
+ protected static final int CARRIER_ID_OTHER = 2;
+
+ protected static final int LINK_UPSTREAM_BANDWIDTH_KBPS = 1024;
+ protected static final int LINK_DOWNSTREAM_BANDWIDTH_KBPS = 2048;
+
+ protected static final int TEST_MIN_UPSTREAM_BANDWIDTH_KBPS = 100;
+ protected static final int TEST_MIN_DOWNSTREAM_BANDWIDTH_KBPS = 200;
+
+ protected static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
+
+ protected static final NetworkCapabilities WIFI_NETWORK_CAPABILITIES =
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .setSignalStrength(WIFI_RSSI)
+ .setSsid(SSID)
+ .setLinkUpstreamBandwidthKbps(LINK_UPSTREAM_BANDWIDTH_KBPS)
+ .setLinkDownstreamBandwidthKbps(LINK_DOWNSTREAM_BANDWIDTH_KBPS)
+ .build();
+
+ protected static final TelephonyNetworkSpecifier TEL_NETWORK_SPECIFIER =
+ new TelephonyNetworkSpecifier.Builder().setSubscriptionId(SUB_ID).build();
+ protected static final NetworkCapabilities CELL_NETWORK_CAPABILITIES =
+ new NetworkCapabilities.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .setSubscriptionIds(Set.of(SUB_ID))
+ .setNetworkSpecifier(TEL_NETWORK_SPECIFIER)
+ .setLinkUpstreamBandwidthKbps(LINK_UPSTREAM_BANDWIDTH_KBPS)
+ .setLinkDownstreamBandwidthKbps(LINK_DOWNSTREAM_BANDWIDTH_KBPS)
+ .build();
+
+ protected static final LinkProperties LINK_PROPERTIES = getLinkPropertiesWithName("test_iface");
+
+ @Mock protected Context mContext;
+ @Mock protected Network mNetwork;
+ @Mock protected FeatureFlags mFeatureFlags;
+ @Mock protected android.net.platform.flags.FeatureFlags mCoreNetFeatureFlags;
+ @Mock protected TelephonySubscriptionSnapshot mSubscriptionSnapshot;
+ @Mock protected TelephonyManager mTelephonyManager;
+ @Mock protected IPowerManager mPowerManagerService;
+
+ protected TestLooper mTestLooper;
+ protected VcnContext mVcnContext;
+ protected PowerManager mPowerManager;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ when(mNetwork.getNetId()).thenReturn(-1);
+
+ mTestLooper = new TestLooper();
+ mVcnContext =
+ spy(
+ new VcnContext(
+ mContext,
+ mTestLooper.getLooper(),
+ mock(VcnNetworkProvider.class),
+ false /* isInTestMode */));
+ doNothing().when(mVcnContext).ensureRunningOnLooperThread();
+
+ doReturn(true).when(mVcnContext).isFlagNetworkMetricMonitorEnabled();
+ doReturn(true).when(mVcnContext).isFlagIpSecTransformStateEnabled();
+
+ setupSystemService(
+ mContext, mTelephonyManager, Context.TELEPHONY_SERVICE, TelephonyManager.class);
+ when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
+ when(mTelephonyManager.getNetworkOperator()).thenReturn(PLMN_ID);
+ when(mTelephonyManager.getSimSpecificCarrierId()).thenReturn(CARRIER_ID);
+
+ mPowerManager =
+ new PowerManager(
+ mContext,
+ mPowerManagerService,
+ mock(IThermalService.class),
+ mock(Handler.class));
+ setupSystemService(mContext, mPowerManager, Context.POWER_SERVICE, PowerManager.class);
+ }
+
+ protected IpSecTransform makeDummyIpSecTransform() throws Exception {
+ return new IpSecTransform(mContext, new IpSecConfig());
+ }
+}
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
index 2266041..d85c515 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
@@ -24,152 +24,48 @@
import static android.net.vcn.VcnUnderlyingNetworkTemplateTestBase.TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS;
import static android.net.vcn.VcnUnderlyingNetworkTemplateTestBase.TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS;
-import static com.android.server.vcn.VcnTestUtils.setupSystemService;
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.PRIORITY_FALLBACK;
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.PRIORITY_INVALID;
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.checkMatchesCellPriorityRule;
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.checkMatchesPriorityRule;
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.checkMatchesWifiPriorityRule;
-import static com.android.server.vcn.routeselection.UnderlyingNetworkControllerTest.getLinkPropertiesWithName;
import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import android.content.Context;
-import android.net.LinkProperties;
-import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.TelephonyNetworkSpecifier;
import android.net.vcn.VcnCellUnderlyingNetworkTemplate;
import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnManager;
import android.net.vcn.VcnUnderlyingNetworkTemplate;
import android.net.vcn.VcnWifiUnderlyingNetworkTemplate;
-import android.os.ParcelUuid;
import android.os.PersistableBundle;
-import android.os.test.TestLooper;
-import android.telephony.TelephonyManager;
import android.util.ArraySet;
-import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
-import com.android.server.vcn.VcnContext;
-import com.android.server.vcn.VcnNetworkProvider;
-
import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import java.util.UUID;
-public class NetworkPriorityClassifierTest {
- private static final String SSID = "TestWifi";
- private static final String SSID_OTHER = "TestWifiOther";
- private static final String PLMN_ID = "123456";
- private static final String PLMN_ID_OTHER = "234567";
-
- private static final int SUB_ID = 1;
- private static final int WIFI_RSSI = -60;
- private static final int WIFI_RSSI_HIGH = -50;
- private static final int WIFI_RSSI_LOW = -80;
- private static final int CARRIER_ID = 1;
- private static final int CARRIER_ID_OTHER = 2;
-
- private static final int LINK_UPSTREAM_BANDWIDTH_KBPS = 1024;
- private static final int LINK_DOWNSTREAM_BANDWIDTH_KBPS = 2048;
-
- private static final int TEST_MIN_UPSTREAM_BANDWIDTH_KBPS = 100;
- private static final int TEST_MIN_DOWNSTREAM_BANDWIDTH_KBPS = 200;
-
- private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
-
- private static final NetworkCapabilities WIFI_NETWORK_CAPABILITIES =
- new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .setSignalStrength(WIFI_RSSI)
- .setSsid(SSID)
- .setLinkUpstreamBandwidthKbps(LINK_UPSTREAM_BANDWIDTH_KBPS)
- .setLinkDownstreamBandwidthKbps(LINK_DOWNSTREAM_BANDWIDTH_KBPS)
- .build();
-
- private static final TelephonyNetworkSpecifier TEL_NETWORK_SPECIFIER =
- new TelephonyNetworkSpecifier.Builder().setSubscriptionId(SUB_ID).build();
- private static final NetworkCapabilities CELL_NETWORK_CAPABILITIES =
- new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
- .setSubscriptionIds(Set.of(SUB_ID))
- .setNetworkSpecifier(TEL_NETWORK_SPECIFIER)
- .setLinkUpstreamBandwidthKbps(LINK_UPSTREAM_BANDWIDTH_KBPS)
- .setLinkDownstreamBandwidthKbps(LINK_DOWNSTREAM_BANDWIDTH_KBPS)
- .build();
-
- private static final LinkProperties LINK_PROPERTIES = getLinkPropertiesWithName("test_iface");
-
- @Mock private Network mNetwork;
- @Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
- @Mock private TelephonyManager mTelephonyManager;
-
- private TestLooper mTestLooper;
- private VcnContext mVcnContext;
+public class NetworkPriorityClassifierTest extends NetworkEvaluationTestBase {
private UnderlyingNetworkRecord mWifiNetworkRecord;
private UnderlyingNetworkRecord mCellNetworkRecord;
@Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
+ public void setUp() throws Exception {
+ super.setUp();
- final Context mockContext = mock(Context.class);
- mTestLooper = new TestLooper();
- mVcnContext =
- spy(
- new VcnContext(
- mockContext,
- mTestLooper.getLooper(),
- mock(VcnNetworkProvider.class),
- false /* isInTestMode */));
- doNothing().when(mVcnContext).ensureRunningOnLooperThread();
-
- setupSystemService(
- mockContext, mTelephonyManager, Context.TELEPHONY_SERVICE, TelephonyManager.class);
- when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
- when(mTelephonyManager.getNetworkOperator()).thenReturn(PLMN_ID);
- when(mTelephonyManager.getSimSpecificCarrierId()).thenReturn(CARRIER_ID);
-
- mWifiNetworkRecord =
- getTestNetworkRecord(
- WIFI_NETWORK_CAPABILITIES,
- VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
- mCellNetworkRecord =
- getTestNetworkRecord(
- CELL_NETWORK_CAPABILITIES,
- VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
+ mWifiNetworkRecord = getTestNetworkRecord(WIFI_NETWORK_CAPABILITIES);
+ mCellNetworkRecord = getTestNetworkRecord(CELL_NETWORK_CAPABILITIES);
}
- private UnderlyingNetworkRecord getTestNetworkRecord(
- NetworkCapabilities nc, List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates) {
- return new UnderlyingNetworkRecord(
- mNetwork,
- nc,
- LINK_PROPERTIES,
- false /* isBlocked */,
- mVcnContext,
- underlyingNetworkTemplates,
- SUB_GROUP,
- mSubscriptionSnapshot,
- null /* currentlySelected */,
- null /* carrierConfig */);
+ private UnderlyingNetworkRecord getTestNetworkRecord(NetworkCapabilities nc) {
+ return new UnderlyingNetworkRecord(mNetwork, nc, LINK_PROPERTIES, false /* isBlocked */);
}
@Test
@@ -186,14 +82,14 @@
mWifiNetworkRecord,
SUB_GROUP,
mSubscriptionSnapshot,
- null /* currentlySelecetd */,
+ false /* isSelected */,
null /* carrierConfig */));
}
private void verifyMatchesPriorityRuleForUpstreamBandwidth(
int entryUpstreamBandwidth,
int exitUpstreamBandwidth,
- UnderlyingNetworkRecord currentlySelected,
+ boolean isSelected,
boolean expectMatch) {
final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority =
new VcnWifiUnderlyingNetworkTemplate.Builder()
@@ -208,14 +104,14 @@
mWifiNetworkRecord,
SUB_GROUP,
mSubscriptionSnapshot,
- currentlySelected,
+ isSelected,
null /* carrierConfig */));
}
private void verifyMatchesPriorityRuleForDownstreamBandwidth(
int entryDownstreamBandwidth,
int exitDownstreamBandwidth,
- UnderlyingNetworkRecord currentlySelected,
+ boolean isSelected,
boolean expectMatch) {
final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority =
new VcnWifiUnderlyingNetworkTemplate.Builder()
@@ -231,7 +127,7 @@
mWifiNetworkRecord,
SUB_GROUP,
mSubscriptionSnapshot,
- currentlySelected,
+ isSelected,
null /* carrierConfig */));
}
@@ -240,7 +136,7 @@
verifyMatchesPriorityRuleForUpstreamBandwidth(
TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS,
- null /* currentlySelected */,
+ false /* isSelected */,
true);
}
@@ -249,7 +145,7 @@
verifyMatchesPriorityRuleForUpstreamBandwidth(
LINK_UPSTREAM_BANDWIDTH_KBPS + 1,
LINK_UPSTREAM_BANDWIDTH_KBPS + 1,
- null /* currentlySelected */,
+ false /* isSelected */,
false);
}
@@ -258,7 +154,7 @@
verifyMatchesPriorityRuleForDownstreamBandwidth(
TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS,
TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS,
- null /* currentlySelected */,
+ false /* isSelected */,
true);
}
@@ -267,7 +163,7 @@
verifyMatchesPriorityRuleForDownstreamBandwidth(
LINK_DOWNSTREAM_BANDWIDTH_KBPS + 1,
LINK_DOWNSTREAM_BANDWIDTH_KBPS + 1,
- null /* currentlySelected */,
+ false /* isSelected */,
false);
}
@@ -276,7 +172,7 @@
verifyMatchesPriorityRuleForUpstreamBandwidth(
TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS,
TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS,
- mWifiNetworkRecord,
+ true /* isSelected */,
true);
}
@@ -285,7 +181,7 @@
verifyMatchesPriorityRuleForUpstreamBandwidth(
LINK_UPSTREAM_BANDWIDTH_KBPS + 1,
LINK_UPSTREAM_BANDWIDTH_KBPS + 1,
- mWifiNetworkRecord,
+ true /* isSelected */,
false);
}
@@ -294,7 +190,7 @@
verifyMatchesPriorityRuleForDownstreamBandwidth(
TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS,
TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS,
- mWifiNetworkRecord,
+ true /* isSelected */,
true);
}
@@ -303,7 +199,7 @@
verifyMatchesPriorityRuleForDownstreamBandwidth(
LINK_DOWNSTREAM_BANDWIDTH_KBPS + 1,
LINK_DOWNSTREAM_BANDWIDTH_KBPS + 1,
- mWifiNetworkRecord,
+ true /* isSelected */,
false);
}
@@ -318,14 +214,12 @@
TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS,
TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS)
.build();
- final UnderlyingNetworkRecord selectedNetworkRecord =
- isSelectedNetwork ? mWifiNetworkRecord : null;
assertEquals(
expectMatch,
checkMatchesWifiPriorityRule(
wifiNetworkPriority,
mWifiNetworkRecord,
- selectedNetworkRecord,
+ isSelectedNetwork,
carrierConfig == null
? null
: new PersistableBundleWrapper(carrierConfig)));
@@ -381,7 +275,7 @@
checkMatchesWifiPriorityRule(
wifiNetworkPriority,
mWifiNetworkRecord,
- null /* currentlySelecetd */,
+ false /* isSelected */,
null /* carrierConfig */));
}
@@ -516,7 +410,7 @@
mCellNetworkRecord,
SUB_GROUP,
mSubscriptionSnapshot,
- null /* currentlySelected */,
+ false /* isSelected */,
null /* carrierConfig */));
}
@@ -543,7 +437,16 @@
@Test
public void testCalculatePriorityClass() throws Exception {
- assertEquals(2, mCellNetworkRecord.priorityClass);
+ final int priorityClass =
+ NetworkPriorityClassifier.calculatePriorityClass(
+ mVcnContext,
+ mCellNetworkRecord,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ false /* isSelected */,
+ null /* carrierConfig */);
+ assertEquals(2, priorityClass);
}
private void checkCalculatePriorityClassFailToMatchAny(
@@ -561,10 +464,19 @@
ncBuilder.addCapability(NET_CAPABILITY_INTERNET);
}
- final UnderlyingNetworkRecord nonDunNetworkRecord =
- getTestNetworkRecord(ncBuilder.build(), templatesRequireDun);
+ final UnderlyingNetworkRecord nonDunNetworkRecord = getTestNetworkRecord(ncBuilder.build());
- assertEquals(expectedPriorityClass, nonDunNetworkRecord.priorityClass);
+ final int priorityClass =
+ NetworkPriorityClassifier.calculatePriorityClass(
+ mVcnContext,
+ nonDunNetworkRecord,
+ templatesRequireDun,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ false /* isSelected */,
+ null /* carrierConfig */);
+
+ assertEquals(expectedPriorityClass, priorityClass);
}
@Test
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
index 2941fde..588624b 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
@@ -29,13 +29,12 @@
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -48,6 +47,8 @@
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.IpSecConfig;
+import android.net.IpSecTransform;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -67,9 +68,11 @@
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.VcnContext;
import com.android.server.vcn.VcnNetworkProvider;
+import com.android.server.vcn.routeselection.UnderlyingNetworkController.Dependencies;
import com.android.server.vcn.routeselection.UnderlyingNetworkController.NetworkBringupCallback;
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback;
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkListener;
+import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback;
import org.junit.Before;
import org.junit.Test;
@@ -77,6 +80,7 @@
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
import java.util.ArrayList;
import java.util.Arrays;
@@ -152,12 +156,17 @@
@Mock private CarrierConfigManager mCarrierConfigManager;
@Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
@Mock private UnderlyingNetworkControllerCallback mNetworkControllerCb;
+ @Mock private NetworkEvaluatorCallback mEvaluatorCallback;
@Mock private Network mNetwork;
+ @Spy private Dependencies mDependencies = new Dependencies();
+
@Captor private ArgumentCaptor<UnderlyingNetworkListener> mUnderlyingNetworkListenerCaptor;
+ @Captor private ArgumentCaptor<NetworkEvaluatorCallback> mEvaluatorCallbackCaptor;
private TestLooper mTestLooper;
private VcnContext mVcnContext;
+ private UnderlyingNetworkEvaluator mNetworkEvaluator;
private UnderlyingNetworkController mUnderlyingNetworkController;
@Before
@@ -172,7 +181,7 @@
mTestLooper.getLooper(),
mVcnNetworkProvider,
false /* isInTestMode */));
- resetVcnContext();
+ resetVcnContext(mVcnContext);
setupSystemService(
mContext,
@@ -189,18 +198,36 @@
when(mSubscriptionSnapshot.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(INITIAL_SUB_IDS);
+ mNetworkEvaluator =
+ spy(
+ new UnderlyingNetworkEvaluator(
+ mVcnContext,
+ mNetwork,
+ VcnGatewayConnectionConfigTest.buildTestConfig()
+ .getVcnUnderlyingNetworkPriorities(),
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ null,
+ mEvaluatorCallback));
+ doReturn(mNetworkEvaluator)
+ .when(mDependencies)
+ .newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any(), any());
+
mUnderlyingNetworkController =
new UnderlyingNetworkController(
mVcnContext,
VcnGatewayConnectionConfigTest.buildTestConfig(),
SUB_GROUP,
mSubscriptionSnapshot,
- mNetworkControllerCb);
+ mNetworkControllerCb,
+ mDependencies);
}
- private void resetVcnContext() {
- reset(mVcnContext);
- doNothing().when(mVcnContext).ensureRunningOnLooperThread();
+ private void resetVcnContext(VcnContext vcnContext) {
+ reset(vcnContext);
+ doNothing().when(vcnContext).ensureRunningOnLooperThread();
+ doReturn(true).when(vcnContext).isFlagNetworkMetricMonitorEnabled();
+ doReturn(true).when(vcnContext).isFlagIpSecTransformStateEnabled();
}
// Package private for use in NetworkPriorityClassifierTest
@@ -226,11 +253,13 @@
final ConnectivityManager cm = mock(ConnectivityManager.class);
setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
final VcnContext vcnContext =
- new VcnContext(
- mContext,
- mTestLooper.getLooper(),
- mVcnNetworkProvider,
- true /* isInTestMode */);
+ spy(
+ new VcnContext(
+ mContext,
+ mTestLooper.getLooper(),
+ mVcnNetworkProvider,
+ true /* isInTestMode */));
+ resetVcnContext(vcnContext);
new UnderlyingNetworkController(
vcnContext,
@@ -489,13 +518,7 @@
NetworkCapabilities networkCapabilities,
LinkProperties linkProperties,
boolean isBlocked) {
- return new UnderlyingNetworkRecord(
- network,
- networkCapabilities,
- linkProperties,
- isBlocked,
- false /* isSelected */,
- 0 /* priorityClass */);
+ return new UnderlyingNetworkRecord(network, networkCapabilities, linkProperties, isBlocked);
}
@Test
@@ -515,24 +538,12 @@
UnderlyingNetworkRecord recordC =
new UnderlyingNetworkRecord(
mNetwork,
- INITIAL_NETWORK_CAPABILITIES,
- INITIAL_LINK_PROPERTIES,
- false /* isBlocked */,
- true /* isSelected */,
- -1 /* priorityClass */);
- UnderlyingNetworkRecord recordD =
- getTestNetworkRecord(
- mNetwork,
UPDATED_NETWORK_CAPABILITIES,
UPDATED_LINK_PROPERTIES,
false /* isBlocked */);
assertEquals(recordA, recordB);
- assertEquals(recordA, recordC);
- assertNotEquals(recordA, recordD);
-
- assertTrue(UnderlyingNetworkRecord.isEqualIncludingPriorities(recordA, recordB));
- assertFalse(UnderlyingNetworkRecord.isEqualIncludingPriorities(recordA, recordC));
+ assertNotEquals(recordA, recordC);
}
@Test
@@ -540,6 +551,58 @@
verifyRegistrationOnAvailableAndGetCallback();
}
+ @Test
+ public void testUpdateSubscriptionSnapshotAndCarrierConfig() {
+ verifyRegistrationOnAvailableAndGetCallback();
+
+ TelephonySubscriptionSnapshot subscriptionUpdate =
+ mock(TelephonySubscriptionSnapshot.class);
+ when(subscriptionUpdate.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(UPDATED_SUB_IDS);
+
+ mUnderlyingNetworkController.updateSubscriptionSnapshot(subscriptionUpdate);
+
+ verify(mNetworkEvaluator).reevaluate(any(), any(), any(), any());
+ }
+
+ @Test
+ public void testUpdateIpSecTransform() {
+ verifyRegistrationOnAvailableAndGetCallback();
+
+ final UnderlyingNetworkRecord expectedRecord =
+ getTestNetworkRecord(
+ mNetwork,
+ INITIAL_NETWORK_CAPABILITIES,
+ INITIAL_LINK_PROPERTIES,
+ false /* isBlocked */);
+ final IpSecTransform expectedTransform = new IpSecTransform(mContext, new IpSecConfig());
+
+ mUnderlyingNetworkController.updateInboundTransform(expectedRecord, expectedTransform);
+ verify(mNetworkEvaluator).setInboundTransform(expectedTransform);
+ }
+
+ @Test
+ public void testOnEvaluationResultChanged() {
+ verifyRegistrationOnAvailableAndGetCallback();
+
+ // Verify #reevaluateNetworks is called by checking #getNetworkRecord
+ verify(mNetworkEvaluator).getNetworkRecord();
+
+ // Trigger the callback
+ verify(mDependencies)
+ .newUnderlyingNetworkEvaluator(
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ mEvaluatorCallbackCaptor.capture());
+ mEvaluatorCallbackCaptor.getValue().onEvaluationResultChanged();
+
+ // Verify #reevaluateNetworks is called again
+ verify(mNetworkEvaluator, times(2)).getNetworkRecord();
+ }
+
private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback() {
return verifyRegistrationOnAvailableAndGetCallback(INITIAL_NETWORK_CAPABILITIES);
}
@@ -583,6 +646,7 @@
INITIAL_LINK_PROPERTIES,
false /* isBlocked */);
verifyOnSelectedUnderlyingNetworkChanged(expectedRecord);
+ verify(mNetworkEvaluator).setIsSelected(eq(true), any(), any(), any(), any());
return cb;
}
@@ -667,7 +731,7 @@
cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */);
- verifyOnSelectedUnderlyingNetworkChanged(null);
+ verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(null);
}
@Test
@@ -675,6 +739,7 @@
UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onLost(mNetwork);
+ verify(mNetworkEvaluator).close();
verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(null);
}
@@ -713,7 +778,8 @@
VcnGatewayConnectionConfigTest.buildTestConfig(networkTemplates),
SUB_GROUP,
mSubscriptionSnapshot,
- mNetworkControllerCb);
+ mNetworkControllerCb,
+ mDependencies);
verify(cm)
.registerNetworkCallback(
@@ -724,30 +790,44 @@
return mUnderlyingNetworkListenerCaptor.getValue();
}
- private UnderlyingNetworkRecord bringupNetworkAndGetRecord(
+ private UnderlyingNetworkEvaluator bringupNetworkAndGetEvaluator(
UnderlyingNetworkListener cb,
NetworkCapabilities requestNetworkCaps,
- List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
- UnderlyingNetworkRecord currentlySelected) {
+ List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates) {
final Network network = mock(Network.class);
final NetworkCapabilities responseNetworkCaps =
buildResponseNwCaps(requestNetworkCaps, INITIAL_SUB_IDS);
+ final UnderlyingNetworkEvaluator evaluator =
+ spy(
+ new UnderlyingNetworkEvaluator(
+ mVcnContext,
+ network,
+ underlyingNetworkTemplates,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ null,
+ mEvaluatorCallback));
+ doReturn(evaluator)
+ .when(mDependencies)
+ .newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any(), any());
cb.onAvailable(network);
cb.onCapabilitiesChanged(network, responseNetworkCaps);
cb.onLinkPropertiesChanged(network, INITIAL_LINK_PROPERTIES);
cb.onBlockedStatusChanged(network, false /* isFalse */);
- return new UnderlyingNetworkRecord(
- network,
- responseNetworkCaps,
- INITIAL_LINK_PROPERTIES,
- false /* isBlocked */,
- mVcnContext,
- underlyingNetworkTemplates,
- SUB_GROUP,
- mSubscriptionSnapshot,
- currentlySelected,
- null /* carrierConfig */);
+
+ return evaluator;
+ }
+
+ private void verifySelectNetwork(UnderlyingNetworkEvaluator expectedEvaluator) {
+ verifyOnSelectedUnderlyingNetworkChanged(expectedEvaluator.getNetworkRecord());
+ verify(expectedEvaluator).setIsSelected(eq(true), any(), any(), any(), any());
+ }
+
+ private void verifyNeverSelectNetwork(UnderlyingNetworkEvaluator expectedEvaluator) {
+ verify(mNetworkControllerCb, never())
+ .onSelectedUnderlyingNetworkChanged(eq(expectedEvaluator.getNetworkRecord()));
+ verify(expectedEvaluator, never()).setIsSelected(eq(true), any(), any(), any(), any());
}
@Test
@@ -759,19 +839,15 @@
UnderlyingNetworkListener cb = setupControllerAndGetNetworkListener(networkTemplates);
// Bring up CBS network
- final UnderlyingNetworkRecord cbsNetworkRecord =
- bringupNetworkAndGetRecord(
- cb,
- CBS_NETWORK_CAPABILITIES,
- networkTemplates,
- null /* currentlySelected */);
- verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(cbsNetworkRecord));
+ final UnderlyingNetworkEvaluator cbsNetworkEvaluator =
+ bringupNetworkAndGetEvaluator(cb, CBS_NETWORK_CAPABILITIES, networkTemplates);
+ verifySelectNetwork(cbsNetworkEvaluator);
// Bring up DUN network
- final UnderlyingNetworkRecord dunNetworkRecord =
- bringupNetworkAndGetRecord(
- cb, DUN_NETWORK_CAPABILITIES, networkTemplates, cbsNetworkRecord);
- verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(dunNetworkRecord));
+ final UnderlyingNetworkEvaluator dunNetworkEvaluator =
+ bringupNetworkAndGetEvaluator(cb, DUN_NETWORK_CAPABILITIES, networkTemplates);
+ verifySelectNetwork(dunNetworkEvaluator);
+ verify(cbsNetworkEvaluator).setIsSelected(eq(false), any(), any(), any(), any());
}
@Test
@@ -783,20 +859,14 @@
UnderlyingNetworkListener cb = setupControllerAndGetNetworkListener(networkTemplates);
// Bring up DUN network
- final UnderlyingNetworkRecord dunNetworkRecord =
- bringupNetworkAndGetRecord(
- cb,
- DUN_NETWORK_CAPABILITIES,
- networkTemplates,
- null /* currentlySelected */);
- verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(dunNetworkRecord));
+ final UnderlyingNetworkEvaluator dunNetworkEvaluator =
+ bringupNetworkAndGetEvaluator(cb, DUN_NETWORK_CAPABILITIES, networkTemplates);
+ verifySelectNetwork(dunNetworkEvaluator);
// Bring up CBS network
- final UnderlyingNetworkRecord cbsNetworkRecord =
- bringupNetworkAndGetRecord(
- cb, CBS_NETWORK_CAPABILITIES, networkTemplates, dunNetworkRecord);
- verify(mNetworkControllerCb, never())
- .onSelectedUnderlyingNetworkChanged(eq(cbsNetworkRecord));
+ final UnderlyingNetworkEvaluator cbsNetworkEvaluator =
+ bringupNetworkAndGetEvaluator(cb, CBS_NETWORK_CAPABILITIES, networkTemplates);
+ verifyNeverSelectNetwork(cbsNetworkEvaluator);
}
@Test
@@ -808,13 +878,9 @@
UnderlyingNetworkListener cb = setupControllerAndGetNetworkListener(networkTemplates);
// Bring up an Internet network without DUN capability
- final UnderlyingNetworkRecord networkRecord =
- bringupNetworkAndGetRecord(
- cb,
- INITIAL_NETWORK_CAPABILITIES,
- networkTemplates,
- null /* currentlySelected */);
- verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(networkRecord));
+ final UnderlyingNetworkEvaluator evaluator =
+ bringupNetworkAndGetEvaluator(cb, INITIAL_NETWORK_CAPABILITIES, networkTemplates);
+ verifySelectNetwork(evaluator);
}
@Test
@@ -825,10 +891,8 @@
new VcnCellUnderlyingNetworkTemplate.Builder().setDun(MATCH_REQUIRED).build());
UnderlyingNetworkListener cb = setupControllerAndGetNetworkListener(networkTemplates);
- bringupNetworkAndGetRecord(
- cb, CBS_NETWORK_CAPABILITIES, networkTemplates, null /* currentlySelected */);
-
- verify(mNetworkControllerCb, never())
- .onSelectedUnderlyingNetworkChanged(any(UnderlyingNetworkRecord.class));
+ final UnderlyingNetworkEvaluator evaluator =
+ bringupNetworkAndGetEvaluator(cb, CBS_NETWORK_CAPABILITIES, networkTemplates);
+ verifyNeverSelectNetwork(evaluator);
}
}
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java
new file mode 100644
index 0000000..aa81efe
--- /dev/null
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluatorTest.java
@@ -0,0 +1,336 @@
+/*
+ * 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.vcn.routeselection;
+
+import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY;
+
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.PRIORITY_INVALID;
+import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.net.IpSecTransform;
+import android.net.vcn.VcnGatewayConnectionConfig;
+
+import com.android.server.vcn.routeselection.NetworkMetricMonitor.NetworkMetricMonitorCallback;
+import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.Dependencies;
+import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+
+import java.util.concurrent.TimeUnit;
+
+public class UnderlyingNetworkEvaluatorTest extends NetworkEvaluationTestBase {
+ private static final int PENALTY_TIMEOUT_MIN = 10;
+ private static final long PENALTY_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(PENALTY_TIMEOUT_MIN);
+
+ @Mock private PersistableBundleWrapper mCarrierConfig;
+ @Mock private IpSecPacketLossDetector mIpSecPacketLossDetector;
+ @Mock private Dependencies mDependencies;
+ @Mock private NetworkEvaluatorCallback mEvaluatorCallback;
+
+ @Captor private ArgumentCaptor<NetworkMetricMonitorCallback> mMetricMonitorCbCaptor;
+
+ private UnderlyingNetworkEvaluator mNetworkEvaluator;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ when(mDependencies.newIpSecPacketLossDetector(any(), any(), any(), any()))
+ .thenReturn(mIpSecPacketLossDetector);
+
+ when(mCarrierConfig.getIntArray(
+ eq(VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY), anyObject()))
+ .thenReturn(new int[] {PENALTY_TIMEOUT_MIN});
+
+ mNetworkEvaluator = newValidUnderlyingNetworkEvaluator();
+ }
+
+ private UnderlyingNetworkEvaluator newUnderlyingNetworkEvaluator() {
+ return new UnderlyingNetworkEvaluator(
+ mVcnContext,
+ mNetwork,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig,
+ mEvaluatorCallback,
+ mDependencies);
+ }
+
+ private UnderlyingNetworkEvaluator newValidUnderlyingNetworkEvaluator() {
+ final UnderlyingNetworkEvaluator evaluator = newUnderlyingNetworkEvaluator();
+
+ evaluator.setNetworkCapabilities(
+ CELL_NETWORK_CAPABILITIES,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig);
+ evaluator.setLinkProperties(
+ LINK_PROPERTIES,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig);
+ evaluator.setIsBlocked(
+ false /* isBlocked */,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig);
+
+ return evaluator;
+ }
+
+ @Test
+ public void testInitializedEvaluator() throws Exception {
+ final UnderlyingNetworkEvaluator evaluator = newUnderlyingNetworkEvaluator();
+
+ assertFalse(evaluator.isValid());
+ assertEquals(mNetwork, evaluator.getNetwork());
+ assertEquals(PRIORITY_INVALID, evaluator.getPriorityClass());
+
+ try {
+ evaluator.getNetworkRecord();
+ fail("Expected to fail because evaluator is not valid");
+ } catch (Exception expected) {
+ }
+ }
+
+ @Test
+ public void testValidEvaluator() {
+ final UnderlyingNetworkEvaluator evaluator = newUnderlyingNetworkEvaluator();
+ evaluator.setNetworkCapabilities(
+ CELL_NETWORK_CAPABILITIES,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig);
+ evaluator.setLinkProperties(
+ LINK_PROPERTIES,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig);
+ evaluator.setIsBlocked(
+ false /* isBlocked */,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig);
+
+ final UnderlyingNetworkRecord expectedRecord =
+ new UnderlyingNetworkRecord(
+ mNetwork,
+ CELL_NETWORK_CAPABILITIES,
+ LINK_PROPERTIES,
+ false /* isBlocked */);
+
+ assertTrue(evaluator.isValid());
+ assertEquals(mNetwork, evaluator.getNetwork());
+ assertEquals(2, evaluator.getPriorityClass());
+ assertEquals(expectedRecord, evaluator.getNetworkRecord());
+ }
+
+ private void checkSetSelectedNetwork(boolean isSelected) {
+ mNetworkEvaluator.setIsSelected(
+ isSelected,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig);
+ verify(mIpSecPacketLossDetector).setIsSelectedUnderlyingNetwork(isSelected);
+ }
+
+ @Test
+ public void testSetIsSelected_selected() throws Exception {
+ checkSetSelectedNetwork(true /* isSelectedExpected */);
+ }
+
+ @Test
+ public void testSetIsSelected_unselected() throws Exception {
+ checkSetSelectedNetwork(false /* isSelectedExpected */);
+ }
+
+ @Test
+ public void testSetIpSecTransform_onSelectedNetwork() throws Exception {
+ final IpSecTransform transform = makeDummyIpSecTransform();
+
+ // Make the network selected
+ mNetworkEvaluator.setIsSelected(
+ true,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig);
+ mNetworkEvaluator.setInboundTransform(transform);
+
+ verify(mIpSecPacketLossDetector).setInboundTransform(transform);
+ }
+
+ @Test
+ public void testSetIpSecTransform_onUnSelectedNetwork() throws Exception {
+ mNetworkEvaluator.setIsSelected(
+ false,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig);
+ mNetworkEvaluator.setInboundTransform(makeDummyIpSecTransform());
+
+ verify(mIpSecPacketLossDetector, never()).setInboundTransform(any());
+ }
+
+ @Test
+ public void close() throws Exception {
+ mNetworkEvaluator.close();
+
+ verify(mIpSecPacketLossDetector).close();
+ mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS);
+ assertNull(mTestLooper.nextMessage());
+ }
+
+ private NetworkMetricMonitorCallback getMetricMonitorCbCaptor() throws Exception {
+ verify(mDependencies)
+ .newIpSecPacketLossDetector(any(), any(), any(), mMetricMonitorCbCaptor.capture());
+
+ return mMetricMonitorCbCaptor.getValue();
+ }
+
+ private void checkPenalizeNetwork() throws Exception {
+ assertFalse(mNetworkEvaluator.isPenalized());
+
+ // Validation failed
+ when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(true);
+ getMetricMonitorCbCaptor().onValidationResultReceived();
+
+ // Verify the evaluator is penalized
+ assertTrue(mNetworkEvaluator.isPenalized());
+ verify(mEvaluatorCallback).onEvaluationResultChanged();
+ }
+
+ @Test
+ public void testRcvValidationResult_penalizeNetwork_penaltyTimeout() throws Exception {
+ checkPenalizeNetwork();
+
+ // Penalty timeout
+ mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ // Verify the evaluator is not penalized
+ assertFalse(mNetworkEvaluator.isPenalized());
+ verify(mEvaluatorCallback, times(2)).onEvaluationResultChanged();
+ }
+
+ @Test
+ public void testRcvValidationResult_penalizeNetwork_passValidation() throws Exception {
+ checkPenalizeNetwork();
+
+ // Validation passed
+ when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(false);
+ getMetricMonitorCbCaptor().onValidationResultReceived();
+
+ // Verify the evaluator is not penalized and penalty timeout is canceled
+ assertFalse(mNetworkEvaluator.isPenalized());
+ verify(mEvaluatorCallback, times(2)).onEvaluationResultChanged();
+ mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS);
+ assertNull(mTestLooper.nextMessage());
+ }
+
+ @Test
+ public void testRcvValidationResult_penalizeNetwork_closeEvaluator() throws Exception {
+ checkPenalizeNetwork();
+
+ mNetworkEvaluator.close();
+
+ // Verify penalty timeout is canceled
+ mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS);
+ assertNull(mTestLooper.nextMessage());
+ }
+
+ @Test
+ public void testRcvValidationResult_PenaltyStateUnchanged() throws Exception {
+ assertFalse(mNetworkEvaluator.isPenalized());
+
+ // Validation passed
+ when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(false);
+ getMetricMonitorCbCaptor().onValidationResultReceived();
+
+ // Verifications
+ assertFalse(mNetworkEvaluator.isPenalized());
+ verify(mEvaluatorCallback, never()).onEvaluationResultChanged();
+ }
+
+ @Test
+ public void testSetCarrierConfig() throws Exception {
+ final int additionalTimeoutMin = 10;
+ when(mCarrierConfig.getIntArray(
+ eq(VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY), anyObject()))
+ .thenReturn(new int[] {PENALTY_TIMEOUT_MIN + additionalTimeoutMin});
+
+ // Update evaluator and penalize the network
+ mNetworkEvaluator.reevaluate(
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ mCarrierConfig);
+ checkPenalizeNetwork();
+
+ // Verify penalty timeout is changed
+ mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS);
+ assertNull(mTestLooper.nextMessage());
+ mTestLooper.moveTimeForward(TimeUnit.MINUTES.toMillis(additionalTimeoutMin));
+ assertNotNull(mTestLooper.nextMessage());
+
+ // Verify NetworkMetricMonitor is notified
+ verify(mIpSecPacketLossDetector).setCarrierConfig(any());
+ }
+
+ @Test
+ public void testCompare() throws Exception {
+ when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(true);
+ getMetricMonitorCbCaptor().onValidationResultReceived();
+
+ final UnderlyingNetworkEvaluator penalized = mNetworkEvaluator;
+ final UnderlyingNetworkEvaluator notPenalized = newValidUnderlyingNetworkEvaluator();
+
+ assertEquals(penalized.getPriorityClass(), notPenalized.getPriorityClass());
+
+ final int result =
+ UnderlyingNetworkEvaluator.getComparator(mVcnContext)
+ .compare(penalized, notPenalized);
+ assertEquals(1, result);
+ }
+}
diff --git a/tools/aapt/ApkBuilder.h b/tools/aapt/ApkBuilder.h
index 5d3abc6..9276402 100644
--- a/tools/aapt/ApkBuilder.h
+++ b/tools/aapt/ApkBuilder.h
@@ -44,7 +44,7 @@
android::status_t createSplitForConfigs(const std::set<ConfigDescription>& configs);
/**
- * Adds a file to be written to the final APK. It's name must not collide
+ * Adds a file to be written to the final APK. Its name must not collide
* with that of any files previously added. When a Split APK is being
* generated, duplicates can exist as long as they are in different splits
* (resources.arsc, AndroidManifest.xml).
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 2f2ef92..66a0510 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -187,7 +187,7 @@
" be loaded alongside the base APK at runtime.\n"
" --feature-of\n"
" Builds a split APK that is a feature of the apk specified here. Resources\n"
- " in the base APK can be referenced from the the feature APK.\n"
+ " in the base APK can be referenced from the feature APK.\n"
" --feature-after\n"
" An app can have multiple Feature Split APKs which must be totally ordered.\n"
" If --feature-of is specified, this flag specifies which Feature Split APK\n"
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 40cba3e..dbac6ca 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -236,3 +236,56 @@
],
},
}
+
+cc_genrule {
+ name: "aapt2_results",
+ srcs: [
+ ":aapt2_tests",
+ "integration-tests/CompileTest/**/*",
+ "integration-tests/CommandTests/**/*",
+ "integration-tests/ConvertTest/**/*",
+ "integration-tests/DumpTest/**/*",
+ ],
+ host_supported: true,
+ device_supported: false,
+ target: {
+ windows: {
+ compile_multilib: "64",
+ },
+ },
+ out: ["result.xml"],
+ cmd: "mkdir -p $(genDir)/integration-tests/CompileTest/ && " +
+ "cp $(locations integration-tests/CompileTest/**/*) $(genDir)/integration-tests/CompileTest/ && " +
+ "mkdir -p $(genDir)/integration-tests/CommandTests/ && " +
+ "cp $(locations integration-tests/CommandTests/**/*) $(genDir)/integration-tests/CompileTest/ && " +
+ "mkdir -p $(genDir)/integration-tests/ConvertTest/ && " +
+ "cp $(locations integration-tests/ConvertTest/**/*) $(genDir)/integration-tests/ConvertTest/ && " +
+ "mkdir -p $(genDir)/integration-tests/DumpTest/ && " +
+ "cp $(locations integration-tests/DumpTest/**/*) $(genDir)/integration-tests/DumpTest/ && " +
+ "cp $(locations :aapt2_tests) $(genDir)/ && " +
+ "$(genDir)/aapt2_tests " +
+ "--gtest_output=xml:$(out) " +
+ ">/dev/null 2>&1 ; true",
+ dist: {
+ targets: ["aapt2_run_host_unit_tests"],
+ dir: "gtest",
+ dest: "aapt2_host_unit_tests_result.xml",
+ },
+ arch: {
+ x86: {
+ dist: {
+ suffix: "_x86",
+ },
+ },
+ x86_64: {
+ dist: {
+ suffix: "_x86_64",
+ },
+ },
+ },
+}
+
+phony_rule {
+ name: "aapt2_run_host_unit_tests",
+ phony_deps: ["aapt2_results"],
+}
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 34a1b11..15ae2ba 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -1,22 +1,4 @@
-LOCAL_PATH := $(call my-dir)
-
include $(CLEAR_VARS)
-
-aapt2_results := $(call intermediates-dir-for,PACKAGING,aapt2_run_host_unit_tests)/result.xml
-
-# Target for running host unit tests on post/pre-submit.
-.PHONY: aapt2_run_host_unit_tests
-aapt2_run_host_unit_tests: $(aapt2_results)
-
-$(call dist-for-goals,aapt2_run_host_unit_tests,$(aapt2_results):gtest/aapt2_host_unit_tests_result.xml)
-
-# Always run the tests again, even if they haven't changed
-$(aapt2_results): .KATI_IMPLICIT_OUTPUTS := $(aapt2_results)-nocache
-$(aapt2_results): $(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests
- -$(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests --gtest_output=xml:$@ > /dev/null 2>&1
-
+aapt2_results := ./out/soong/.intermediates/frameworks/base/tools/aapt2/aapt2_results
$(call declare-1p-target,$(aapt2_results))
-
aapt2_results :=
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index cf4dd79..c739d77 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -56,6 +56,7 @@
#include "java/JavaClassGenerator.h"
#include "java/ManifestClassGenerator.h"
#include "java/ProguardRules.h"
+#include "link/FeatureFlagsFilter.h"
#include "link/Linkers.h"
#include "link/ManifestFixer.h"
#include "link/NoDefaultResourceRemover.h"
@@ -1986,6 +1987,21 @@
context_->SetNameManglerPolicy(NameManglerPolicy{context_->GetCompilationPackage()});
context_->SetSplitNameDependencies(app_info_.split_name_dependencies);
+ std::unique_ptr<xml::XmlResource> pre_flags_filter_manifest_xml = manifest_xml->Clone();
+
+ FeatureFlagsFilterOptions flags_filter_options;
+ if (context_->GetMinSdkVersion() > SDK_UPSIDE_DOWN_CAKE) {
+ // For API version > U, PackageManager will dynamically read the flag values and disable
+ // manifest elements accordingly when parsing the manifest.
+ // For API version <= U, we remove disabled elements from the manifest with the filter.
+ flags_filter_options.remove_disabled_elements = false;
+ flags_filter_options.flags_must_have_value = false;
+ }
+ FeatureFlagsFilter flags_filter(options_.feature_flag_values, flags_filter_options);
+ if (!flags_filter.Consume(context_, manifest_xml.get())) {
+ return 1;
+ }
+
// Override the package ID when it is "android".
if (context_->GetCompilationPackage() == "android") {
context_->SetPackageId(kAndroidPackageId);
@@ -2282,7 +2298,12 @@
}
if (options_.generate_java_class_path) {
- if (!WriteManifestJavaFile(manifest_xml.get())) {
+ // The FeatureFlagsFilter may remove <permission> and <permission-group> elements that
+ // generate constants in the Manifest Java file. While we want those permissions and
+ // permission groups removed in the SDK (i.e., if a feature flag is disabled), the
+ // constants should still remain so that code referencing it (e.g., within a feature
+ // flag check) will still compile. Therefore we use the manifest XML before the filter.
+ if (!WriteManifestJavaFile(pre_flags_filter_manifest_xml.get())) {
error = true;
}
}
@@ -2530,7 +2551,7 @@
}
for (const std::string& arg : all_feature_flags_args) {
- if (ParseFeatureFlagsParameter(arg, context.GetDiagnostics(), &options_.feature_flag_values)) {
+ if (!ParseFeatureFlagsParameter(arg, context.GetDiagnostics(), &options_.feature_flag_values)) {
return 1;
}
}
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 26713fd..dc18b1c 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -330,7 +330,11 @@
"should only be used together with the --static-lib flag.",
&options_.merge_only);
AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
- AddOptionalFlagList("--feature-flags", "Placeholder, to be implemented.", &feature_flags_args_);
+ AddOptionalFlagList("--feature-flags",
+ "Specify the values of feature flags. The pairs in the argument\n"
+ "are separated by ',' and the name is separated from the value by '='.\n"
+ "Example: \"flag1=true,flag2=false,flag3=\" (flag3 has no given value).",
+ &feature_flags_args_);
}
int Action(const std::vector<std::string>& args) override;
diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp
index 725a1b8..10d0b1f 100644
--- a/tools/aapt2/cmd/Link_test.cpp
+++ b/tools/aapt2/cmd/Link_test.cpp
@@ -16,11 +16,10 @@
#include "Link.h"
-#include <android-base/file.h>
-
-#include "AppInfo.h"
#include "Diagnostics.h"
#include "LoadedApk.h"
+#include "android-base/file.h"
+#include "android-base/stringprintf.h"
#include "test/Test.h"
using testing::Eq;
@@ -993,4 +992,221 @@
ASSERT_FALSE(Link(link_args, &diag));
}
+static void BuildSDKWithFeatureFlagAttr(const std::string& apk_path, const std::string& java_path,
+ CommandTestFixture* fixture, android::IDiagnostics* diag) {
+ const std::string android_values =
+ R"(<resources>
+ <staging-public-group type="attr" first-id="0x01fe0063">
+ <public name="featureFlag" />
+ </staging-public-group>
+ <attr name="featureFlag" format="string" />
+ </resources>)";
+
+ SourceXML source_xml{.res_file_path = "/res/values/values.xml", .file_contents = android_values};
+ BuildSDK({source_xml}, apk_path, java_path, fixture, diag);
+}
+
+TEST_F(LinkTest, FeatureFlagDisabled_SdkAtMostUDC) {
+ StdErrDiagnostics diag;
+ const std::string android_apk = GetTestPath("android.apk");
+ const std::string android_java = GetTestPath("android-java");
+ BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag);
+
+ const std::string manifest_contents = android::base::StringPrintf(
+ R"(<uses-sdk android:minSdkVersion="%d" />"
+ <permission android:name="FOO" android:featureFlag="flag" />)",
+ SDK_UPSIDE_DOWN_CAKE);
+ auto app_manifest = ManifestBuilder(this)
+ .SetPackageName("com.example.app")
+ .AddContents(manifest_contents)
+ .Build();
+
+ const std::string app_java = GetTestPath("app-java");
+ auto app_link_args = LinkCommandBuilder(this)
+ .SetManifestFile(app_manifest)
+ .AddParameter("-I", android_apk)
+ .AddParameter("--java", app_java)
+ .AddParameter("--feature-flags", "flag=false");
+
+ const std::string app_apk = GetTestPath("app.apk");
+ BuildApk({}, app_apk, std::move(app_link_args), this, &diag);
+
+ // Permission element should be removed if flag is disabled
+ auto apk = LoadedApk::LoadApkFromPath(app_apk, &diag);
+ ASSERT_THAT(apk, NotNull());
+ auto apk_manifest = apk->GetManifest();
+ ASSERT_THAT(apk_manifest, NotNull());
+ auto root = apk_manifest->root.get();
+ ASSERT_THAT(root, NotNull());
+ auto maybe_removed = root->FindChild({}, "permission");
+ ASSERT_THAT(maybe_removed, IsNull());
+
+ // Code for the permission should be generated even if the element is removed
+ const std::string manifest_java = app_java + "/com/example/app/Manifest.java";
+ std::string manifest_java_contents;
+ ASSERT_TRUE(android::base::ReadFileToString(manifest_java, &manifest_java_contents));
+ EXPECT_THAT(manifest_java_contents, HasSubstr(" public static final String FOO=\"FOO\";"));
+}
+
+TEST_F(LinkTest, FeatureFlagEnabled_SdkAtMostUDC) {
+ StdErrDiagnostics diag;
+ const std::string android_apk = GetTestPath("android.apk");
+ const std::string android_java = GetTestPath("android-java");
+ BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag);
+
+ const std::string manifest_contents = android::base::StringPrintf(
+ R"(<uses-sdk android:minSdkVersion="%d" />"
+ <permission android:name="FOO" android:featureFlag="flag" />)",
+ SDK_UPSIDE_DOWN_CAKE);
+ auto app_manifest = ManifestBuilder(this)
+ .SetPackageName("com.example.app")
+ .AddContents(manifest_contents)
+ .Build();
+
+ auto app_link_args = LinkCommandBuilder(this)
+ .SetManifestFile(app_manifest)
+ .AddParameter("-I", android_apk)
+ .AddParameter("--feature-flags", "flag=true");
+
+ const std::string app_apk = GetTestPath("app.apk");
+ BuildApk({}, app_apk, std::move(app_link_args), this, &diag);
+
+ // Permission element should be kept if flag is enabled
+ auto apk = LoadedApk::LoadApkFromPath(app_apk, &diag);
+ ASSERT_THAT(apk, NotNull());
+ auto apk_manifest = apk->GetManifest();
+ ASSERT_THAT(apk_manifest, NotNull());
+ auto root = apk_manifest->root.get();
+ ASSERT_THAT(root, NotNull());
+ auto maybe_removed = root->FindChild({}, "permission");
+ ASSERT_THAT(maybe_removed, NotNull());
+}
+
+TEST_F(LinkTest, FeatureFlagWithNoValue_SdkAtMostUDC) {
+ StdErrDiagnostics diag;
+ const std::string android_apk = GetTestPath("android.apk");
+ const std::string android_java = GetTestPath("android-java");
+ BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag);
+
+ const std::string manifest_contents = android::base::StringPrintf(
+ R"(<uses-sdk android:minSdkVersion="%d" />"
+ <permission android:name="FOO" android:featureFlag="flag" />)",
+ SDK_UPSIDE_DOWN_CAKE);
+ auto app_manifest = ManifestBuilder(this)
+ .SetPackageName("com.example.app")
+ .AddContents(manifest_contents)
+ .Build();
+
+ auto app_link_args = LinkCommandBuilder(this)
+ .SetManifestFile(app_manifest)
+ .AddParameter("-I", android_apk)
+ .AddParameter("--feature-flags", "flag=");
+
+ // Flags must have values if <= UDC
+ const std::string app_apk = GetTestPath("app.apk");
+ ASSERT_FALSE(Link(app_link_args.Build(app_apk), &diag));
+}
+
+TEST_F(LinkTest, FeatureFlagDisabled_SdkAfterUDC) {
+ StdErrDiagnostics diag;
+ const std::string android_apk = GetTestPath("android.apk");
+ const std::string android_java = GetTestPath("android-java");
+ BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag);
+
+ const std::string manifest_contents = android::base::StringPrintf(
+ R"(<uses-sdk android:minSdkVersion="%d" />"
+ <permission android:name="FOO" android:featureFlag="flag" />)",
+ SDK_CUR_DEVELOPMENT);
+ auto app_manifest = ManifestBuilder(this)
+ .SetPackageName("com.example.app")
+ .AddContents(manifest_contents)
+ .Build();
+
+ auto app_link_args = LinkCommandBuilder(this)
+ .SetManifestFile(app_manifest)
+ .AddParameter("-I", android_apk)
+ .AddParameter("--feature-flags", "flag=false");
+
+ const std::string app_apk = GetTestPath("app.apk");
+ BuildApk({}, app_apk, std::move(app_link_args), this, &diag);
+
+ // Permission element should be kept if > UDC, regardless of flag value
+ auto apk = LoadedApk::LoadApkFromPath(app_apk, &diag);
+ ASSERT_THAT(apk, NotNull());
+ auto apk_manifest = apk->GetManifest();
+ ASSERT_THAT(apk_manifest, NotNull());
+ auto root = apk_manifest->root.get();
+ ASSERT_THAT(root, NotNull());
+ auto maybe_removed = root->FindChild({}, "permission");
+ ASSERT_THAT(maybe_removed, NotNull());
+}
+
+TEST_F(LinkTest, FeatureFlagEnabled_SdkAfterUDC) {
+ StdErrDiagnostics diag;
+ const std::string android_apk = GetTestPath("android.apk");
+ const std::string android_java = GetTestPath("android-java");
+ BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag);
+
+ const std::string manifest_contents = android::base::StringPrintf(
+ R"(<uses-sdk android:minSdkVersion="%d" />"
+ <permission android:name="FOO" android:featureFlag="flag" />)",
+ SDK_CUR_DEVELOPMENT);
+ auto app_manifest = ManifestBuilder(this)
+ .SetPackageName("com.example.app")
+ .AddContents(manifest_contents)
+ .Build();
+
+ auto app_link_args = LinkCommandBuilder(this)
+ .SetManifestFile(app_manifest)
+ .AddParameter("-I", android_apk)
+ .AddParameter("--feature-flags", "flag=true");
+
+ const std::string app_apk = GetTestPath("app.apk");
+ BuildApk({}, app_apk, std::move(app_link_args), this, &diag);
+
+ // Permission element should be kept if > UDC, regardless of flag value
+ auto apk = LoadedApk::LoadApkFromPath(app_apk, &diag);
+ ASSERT_THAT(apk, NotNull());
+ auto apk_manifest = apk->GetManifest();
+ ASSERT_THAT(apk_manifest, NotNull());
+ auto root = apk_manifest->root.get();
+ ASSERT_THAT(root, NotNull());
+ auto maybe_removed = root->FindChild({}, "permission");
+ ASSERT_THAT(maybe_removed, NotNull());
+}
+
+TEST_F(LinkTest, FeatureFlagWithNoValue_SdkAfterUDC) {
+ StdErrDiagnostics diag;
+ const std::string android_apk = GetTestPath("android.apk");
+ const std::string android_java = GetTestPath("android-java");
+ BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag);
+
+ const std::string manifest_contents = android::base::StringPrintf(
+ R"(<uses-sdk android:minSdkVersion="%d" />"
+ <permission android:name="FOO" android:featureFlag="flag" />)",
+ SDK_CUR_DEVELOPMENT);
+ auto app_manifest = ManifestBuilder(this)
+ .SetPackageName("com.example.app")
+ .AddContents(manifest_contents)
+ .Build();
+
+ auto app_link_args = LinkCommandBuilder(this)
+ .SetManifestFile(app_manifest)
+ .AddParameter("-I", android_apk)
+ .AddParameter("--feature-flags", "flag=");
+
+ const std::string app_apk = GetTestPath("app.apk");
+ BuildApk({}, app_apk, std::move(app_link_args), this, &diag);
+
+ // Permission element should be kept if > UDC, regardless of flag value
+ auto apk = LoadedApk::LoadApkFromPath(app_apk, &diag);
+ ASSERT_THAT(apk, NotNull());
+ auto apk_manifest = apk->GetManifest();
+ ASSERT_THAT(apk_manifest, NotNull());
+ auto root = apk_manifest->root.get();
+ ASSERT_THAT(root, NotNull());
+ auto maybe_removed = root->FindChild({}, "permission");
+ ASSERT_THAT(maybe_removed, NotNull());
+}
+
} // namespace aapt
diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/Android.mk
deleted file mode 100644
index 6361f9b..0000000
--- a/tools/aapt2/integration-tests/MergeOnlyTest/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/App/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/App/Android.mk
deleted file mode 100644
index 27b6068..0000000
--- a/tools/aapt2/integration-tests/MergeOnlyTest/App/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_AAPT_NAMESPACES := true
-LOCAL_PACKAGE_NAME := AaptTestMergeOnly_App
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- AaptTestMergeOnly_LeafLib \
- AaptTestMergeOnly_LocalLib
-include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk
deleted file mode 100644
index c084849..0000000
--- a/tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_AAPT_NAMESPACES := true
-LOCAL_MODULE := AaptTestMergeOnly_LeafLib
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_MIN_SDK_VERSION := 21
-LOCAL_AAPT_FLAGS := --merge-only
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk b/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk
deleted file mode 100644
index 699ad79..0000000
--- a/tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_AAPT_NAMESPACES := true
-LOCAL_MODULE := AaptTestMergeOnly_LocalLib
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_MIN_SDK_VERSION := 21
-LOCAL_AAPT_FLAGS := --merge-only
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/aapt2/integration-tests/NamespaceTest/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/Android.mk
deleted file mode 100644
index 6361f9b..0000000
--- a/tools/aapt2/integration-tests/NamespaceTest/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk
deleted file mode 100644
index 98b7440..0000000
--- a/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_AAPT_NAMESPACES := true
-LOCAL_PACKAGE_NAME := AaptTestNamespace_App
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- AaptTestNamespace_LibOne \
- AaptTestNamespace_LibTwo
-include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk
deleted file mode 100644
index dd41702..0000000
--- a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_AAPT_NAMESPACES := true
-LOCAL_MODULE := AaptTestNamespace_LibOne
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_MIN_SDK_VERSION := 21
-
-# We need this to retain the R.java generated for this library.
-LOCAL_JAR_EXCLUDE_FILES := none
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk
deleted file mode 100644
index 0d11bcb..0000000
--- a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_AAPT_NAMESPACES := true
-LOCAL_MODULE := AaptTestNamespace_LibTwo
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_MIN_SDK_VERSION := 21
-
-# We need this to retain the R.java generated for this library.
-LOCAL_JAR_EXCLUDE_FILES := none
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/aapt2/integration-tests/NamespaceTest/Split/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/Split/Android.mk
deleted file mode 100644
index 30375728..0000000
--- a/tools/aapt2/integration-tests/NamespaceTest/Split/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_AAPT_NAMESPACES := true
-LOCAL_PACKAGE_NAME := AaptTestNamespace_Split
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_APK_LIBRARIES := AaptTestNamespace_App
-LOCAL_RES_LIBRARIES := AaptTestNamespace_App
-LOCAL_AAPT_FLAGS := --package-id 0x80 --rename-manifest-package com.android.aapt.namespace.app
-include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 93c1b61..02e4beae 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -251,10 +251,13 @@
return false;
}
- for (StringPiece line : util::Tokenize(contents, ' ')) {
+ for (StringPiece line : util::Tokenize(contents, '\n')) {
line = util::TrimWhitespace(line);
- if (!line.empty()) {
- out_arglist->emplace_back(line);
+ for (StringPiece arg : util::Tokenize(line, ' ')) {
+ arg = util::TrimWhitespace(arg);
+ if (!arg.empty()) {
+ out_arglist->emplace_back(arg);
+ }
}
}
return true;
@@ -270,10 +273,13 @@
return false;
}
- for (StringPiece line : util::Tokenize(contents, ' ')) {
+ for (StringPiece line : util::Tokenize(contents, '\n')) {
line = util::TrimWhitespace(line);
- if (!line.empty()) {
- out_argset->emplace(line);
+ for (StringPiece arg : util::Tokenize(line, ' ')) {
+ arg = util::TrimWhitespace(arg);
+ if (!arg.empty()) {
+ out_argset->emplace(arg);
+ }
}
}
return true;
diff --git a/tools/aapt2/util/Files_test.cpp b/tools/aapt2/util/Files_test.cpp
index 6c38080..618a3e0 100644
--- a/tools/aapt2/util/Files_test.cpp
+++ b/tools/aapt2/util/Files_test.cpp
@@ -25,6 +25,9 @@
using ::android::base::StringPrintf;
+using ::testing::ElementsAre;
+using ::testing::UnorderedElementsAre;
+
namespace aapt {
namespace file {
@@ -34,9 +37,11 @@
constexpr const char sTestDirSep = '/';
#endif
-class FilesTest : public ::testing::Test {
+class FilesTest : public TestDirectoryFixture {
public:
void SetUp() override {
+ TestDirectoryFixture::SetUp();
+
std::stringstream builder;
builder << "hello" << sDirSep << "there";
expected_path_ = builder.str();
@@ -66,6 +71,42 @@
EXPECT_EQ(expected_path_, base);
}
+TEST_F(FilesTest, AppendArgsFromFile) {
+ const std::string args_file = GetTestPath("args.txt");
+ WriteFile(args_file,
+ " \n"
+ "arg1 arg2 arg3 \n"
+ " arg4 arg5");
+ std::vector<std::string> args;
+ std::string error;
+ ASSERT_TRUE(AppendArgsFromFile(args_file, &args, &error));
+ EXPECT_THAT(args, ElementsAre("arg1", "arg2", "arg3", "arg4", "arg5"));
+}
+
+TEST_F(FilesTest, AppendArgsFromFile_InvalidFile) {
+ std::vector<std::string> args;
+ std::string error;
+ ASSERT_FALSE(AppendArgsFromFile(GetTestPath("not_found.txt"), &args, &error));
+}
+
+TEST_F(FilesTest, AppendSetArgsFromFile) {
+ const std::string args_file = GetTestPath("args.txt");
+ WriteFile(args_file,
+ " \n"
+ "arg2 arg4 arg1 \n"
+ " arg5 arg3");
+ std::unordered_set<std::string> args;
+ std::string error;
+ ASSERT_TRUE(AppendSetArgsFromFile(args_file, &args, &error));
+ EXPECT_THAT(args, UnorderedElementsAre("arg1", "arg2", "arg3", "arg4", "arg5"));
+}
+
+TEST_F(FilesTest, AppendSetArgsFromFile_InvalidFile) {
+ std::unordered_set<std::string> args;
+ std::string error;
+ ASSERT_FALSE(AppendSetArgsFromFile(GetTestPath("not_found.txt"), &args, &error));
+}
+
#ifdef _WIN32
TEST_F(FilesTest, WindowsMkdirsLongPath) {
// Creating directory paths longer than the Windows maximum path length (260 charatcers) should
diff --git a/tools/codegen/src/com/android/codegen/FileInfo.kt b/tools/codegen/src/com/android/codegen/FileInfo.kt
index a1d0389..cc3a156 100644
--- a/tools/codegen/src/com/android/codegen/FileInfo.kt
+++ b/tools/codegen/src/com/android/codegen/FileInfo.kt
@@ -238,7 +238,7 @@
} else if (classBounds.isDataclass) {
// Insert placeholder for generated code to be inserted for the 1st time
- chunks.last = (chunks.last as Code)
+ chunks[chunks.lastIndex] = (chunks.last() as Code)
.lines
.dropLastWhile { it.isBlank() }
.run {
@@ -286,4 +286,4 @@
.let { addAll(it) }
}
}
-}
\ No newline at end of file
+}
diff --git a/tools/codegen/src/com/android/codegen/Utils.kt b/tools/codegen/src/com/android/codegen/Utils.kt
index 9ceb204..a40bdd7 100644
--- a/tools/codegen/src/com/android/codegen/Utils.kt
+++ b/tools/codegen/src/com/android/codegen/Utils.kt
@@ -137,14 +137,4 @@
cause)
}
-var <T> MutableList<T>.last
- get() = last()
- set(value) {
- if (isEmpty()) {
- add(value)
- } else {
- this[size - 1] = value
- }
- }
-
-inline fun <T> buildList(init: MutableList<T>.() -> Unit) = mutableListOf<T>().apply(init)
\ No newline at end of file
+inline fun <T> buildList(init: MutableList<T>.() -> Unit) = mutableListOf<T>().apply(init)
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
index 25d208d..5cbb1aa 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
@@ -77,7 +77,9 @@
.autoFix()
.build()
- return LintFix.create().composite(annotateFix, *replaceOrRemoveFixes.toTypedArray())
+ return LintFix.create()
+ .name(annotateFix.getDisplayName())
+ .composite(annotateFix, *replaceOrRemoveFixes.toTypedArray())
}
private val annotation: String
diff --git a/tools/protologtool/OWNERS b/tools/protologtool/OWNERS
new file mode 100644
index 0000000..18cf2be
--- /dev/null
+++ b/tools/protologtool/OWNERS
@@ -0,0 +1,3 @@
+# ProtoLog owners
+# Bug component: 1157642
+include platform/development:/tools/winscope/OWNERS
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
index 3c55237..ce856cd 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
@@ -25,6 +25,7 @@
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.OutputStream
+import java.time.LocalDateTime
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.jar.JarOutputStream
@@ -42,6 +43,13 @@
return source.contains(protoLogSimpleClassName)
}
+ private fun zipEntry(path: String): ZipEntry {
+ val entry = ZipEntry(path)
+ // Use a constant time to improve the cachability of build actions.
+ entry.timeLocal = LocalDateTime.of(2008, 1, 1, 0, 0, 0)
+ return entry
+ }
+
private fun processClasses(command: CommandOptions) {
val groups = injector.readLogGroups(
command.protoLogGroupsJarArg,
@@ -77,7 +85,7 @@
}
}.map { future ->
val (path, outSrc) = future.get()
- outJar.putNextEntry(ZipEntry(path))
+ outJar.putNextEntry(zipEntry(path))
outJar.write(outSrc.toByteArray())
outJar.closeEntry()
}
@@ -90,7 +98,7 @@
val cachePackage = cacheSplit.dropLast(1).joinToString(".")
val cachePath = "gen/${cacheSplit.joinToString("/")}.java"
- outJar.putNextEntry(ZipEntry(cachePath))
+ outJar.putNextEntry(zipEntry(cachePath))
outJar.write(generateLogGroupCache(cachePackage, cacheName, groups,
command.protoLogImplClassNameArg, command.protoLogGroupsClassNameArg).toByteArray())