Merge Android 24Q1 Release (ab/11220357)
Bug: 319669529
Merged-In: I46c7859ff042ee7aa9193757e5df8269f4892362
Change-Id: I0c7b5036c0b0f5f2caad551edb063350f6eb87e7
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 705a4df..eb896d6 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -13,66 +13,92 @@
// limitations under the License.
aconfig_srcjars = [
- ":android.app.usage.flags-aconfig-java{.generated_srcjars}",
+ // !!! KEEP THIS LIST ALPHABETICAL !!!
+ ":aconfig_mediacodec_flags_java_lib{.generated_srcjars}",
+ ":android.app.flags-aconfig-java{.generated_srcjars}",
":android.app.smartspace.flags-aconfig-java{.generated_srcjars}",
+ ":android.app.usage.flags-aconfig-java{.generated_srcjars}",
+ ":android.appwidget.flags-aconfig-java{.generated_srcjars}",
":android.companion.flags-aconfig-java{.generated_srcjars}",
+ ":android.companion.virtual.flags-aconfig-java{.generated_srcjars}",
":android.content.pm.flags-aconfig-java{.generated_srcjars}",
":android.content.res.flags-aconfig-java{.generated_srcjars}",
+ ":android.crashrecovery.flags-aconfig-java{.generated_srcjars}",
+ ":android.credentials.flags-aconfig-java{.generated_srcjars}",
+ ":android.database.sqlite-aconfig-java{.generated_srcjars}",
+ ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}",
":android.hardware.flags-aconfig-java{.generated_srcjars}",
":android.hardware.radio.flags-aconfig-java{.generated_srcjars}",
+ ":android.hardware.usb.flags-aconfig-java{.generated_srcjars}",
":android.location.flags-aconfig-java{.generated_srcjars}",
+ ":android.media.playback.flags-aconfig-java{.generated_srcjars}",
+ ":android.media.tv.flags-aconfig-java{.generated_srcjars}",
+ ":android.multiuser.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.os.vibrator.flags-aconfig-java{.generated_srcjars}",
+ ":android.permission.flags-aconfig-java{.generated_srcjars}",
+ ":android.provider.flags-aconfig-java{.generated_srcjars}",
":android.security.flags-aconfig-java{.generated_srcjars}",
":android.server.app.flags-aconfig-java{.generated_srcjars}",
+ ":android.service.autofill.flags-aconfig-java{.generated_srcjars}",
":android.service.chooser.flags-aconfig-java{.generated_srcjars}",
+ ":android.service.controls.flags-aconfig-java{.generated_srcjars}",
":android.service.dreams.flags-aconfig-java{.generated_srcjars}",
":android.service.notification.flags-aconfig-java{.generated_srcjars}",
- ":android.view.flags-aconfig-java{.generated_srcjars}",
+ ":android.service.voice.flags-aconfig-java{.generated_srcjars}",
+ ":android.tracing.flags-aconfig-java{.generated_srcjars}",
":android.view.accessibility.flags-aconfig-java{.generated_srcjars}",
+ ":android.view.contentcapture.flags-aconfig-java{.generated_srcjars}",
+ ":android.view.contentprotection.flags-aconfig-java{.generated_srcjars}",
+ ":android.view.flags-aconfig-java{.generated_srcjars}",
+ ":android.view.inputmethod.flags-aconfig-java{.generated_srcjars}",
+ ":android.webkit.flags-aconfig-java{.generated_srcjars}",
+ ":android.widget.flags-aconfig-java{.generated_srcjars}",
":audio-framework-aconfig",
":camera_platform_flags_core_java_lib{.generated_srcjars}",
- ":com.android.window.flags.window-aconfig-java{.generated_srcjars}",
- ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}",
":com.android.hardware.input-aconfig-java{.generated_srcjars}",
":com.android.input.flags-aconfig-java{.generated_srcjars}",
+ ":com.android.internal.foldables.flags-aconfig-java{.generated_srcjars}",
+ ":com.android.media.flags.bettertogether-aconfig-java{.generated_srcjars}",
+ ":com.android.net.flags-aconfig-java{.generated_srcjars}",
+ ":com.android.net.thread.flags-aconfig-java{.generated_srcjars}",
+ ":com.android.server.flags.pinner-aconfig-java{.generated_srcjars}",
":com.android.text.flags-aconfig-java{.generated_srcjars}",
+ ":com.android.window.flags.window-aconfig-java{.generated_srcjars}",
+ ":device_policy_aconfig_flags_lib{.generated_srcjars}",
+ ":display_flags_lib{.generated_srcjars}",
":framework-jobscheduler-job.flags-aconfig-java{.generated_srcjars}",
+ ":framework_graphics_flags_java_lib{.generated_srcjars}",
+ ":hwui_flags_java_lib{.generated_srcjars}",
+ ":sdk_sandbox_flags_lib{.generated_srcjars}",
+ ":surfaceflinger_flags_java_lib{.generated_srcjars}",
":telecom_flags_core_java_lib{.generated_srcjars}",
":telephony_flags_core_java_lib{.generated_srcjars}",
- ":android.companion.virtual.flags-aconfig-java{.generated_srcjars}",
- ":android.view.inputmethod.flags-aconfig-java{.generated_srcjars}",
- ":android.widget.flags-aconfig-java{.generated_srcjars}",
- ":com.android.media.flags.bettertogether-aconfig-java{.generated_srcjars}",
- ":sdk_sandbox_flags_lib{.generated_srcjars}",
- ":android.permission.flags-aconfig-java{.generated_srcjars}",
- ":android.database.sqlite-aconfig-java{.generated_srcjars}",
- ":hwui_flags_java_lib{.generated_srcjars}",
- ":framework_graphics_flags_java_lib{.generated_srcjars}",
- ":display_flags_lib{.generated_srcjars}",
- ":com.android.internal.foldables.flags-aconfig-java{.generated_srcjars}",
- ":android.multiuser.flags-aconfig-java{.generated_srcjars}",
- ":android.app.flags-aconfig-java{.generated_srcjars}",
- ":android.credentials.flags-aconfig-java{.generated_srcjars}",
- ":android.view.contentprotection.flags-aconfig-java{.generated_srcjars}",
- ":com.android.server.flags.pinner-aconfig-java{.generated_srcjars}",
- ":android.service.controls.flags-aconfig-java{.generated_srcjars}",
- ":android.service.voice.flags-aconfig-java{.generated_srcjars}",
- ":android.media.tv.flags-aconfig-java{.generated_srcjars}",
- ":android.service.autofill.flags-aconfig-java{.generated_srcjars}",
- ":com.android.net.flags-aconfig-java{.generated_srcjars}",
- ":device_policy_aconfig_flags_lib{.generated_srcjars}",
- ":surfaceflinger_flags_java_lib{.generated_srcjars}",
- ":android.view.contentcapture.flags-aconfig-java{.generated_srcjars}",
- ":android.hardware.usb.flags-aconfig-java{.generated_srcjars}",
- ":android.tracing.flags-aconfig-java{.generated_srcjars}",
- ":android.appwidget.flags-aconfig-java{.generated_srcjars}",
- ":android.webkit.flags-aconfig-java{.generated_srcjars}",
- ":android.provider.flags-aconfig-java{.generated_srcjars}",
+ // !!! KEEP THIS LIST ALPHABETICAL !!!
]
+stubs_defaults {
+ name: "framework-minus-apex-aconfig-declarations",
+ aconfig_declarations: [
+ "android.content.pm.flags-aconfig",
+ "android.content.res.flags-aconfig",
+ "android.crashrecovery.flags-aconfig",
+ "android.hardware.biometrics.flags-aconfig",
+ "android.media.playback.flags-aconfig",
+ "android.net.vcn.flags-aconfig",
+ "android.nfc.flags-aconfig",
+ "android.os.flags-aconfig",
+ "android.security.flags-aconfig",
+ "camera_platform_flags",
+ "com.android.hardware.input.input-aconfig",
+ "com.android.window.flags.window-aconfig",
+ "com.android.text.flags-aconfig",
+ "com.android.net.flags-aconfig",
+ ],
+}
+
filegroup {
name: "framework-minus-apex-aconfig-srcjars",
srcs: aconfig_srcjars,
@@ -666,12 +692,25 @@
srcs: ["core/java/android/net/flags.aconfig"],
}
+// Thread network
+aconfig_declarations {
+ name: "com.android.net.thread.flags-aconfig",
+ package: "com.android.net.thread.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",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+java_aconfig_library {
+ name: "com.android.net.thread.flags-aconfig-java",
+ aconfig_declarations: "com.android.net.thread.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
// Media
aconfig_declarations {
name: "android.media.playback.flags-aconfig",
@@ -895,3 +934,16 @@
aconfig_declarations: "android.provider.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 676a0f5..e9bdd49 100644
--- a/Android.bp
+++ b/Android.bp
@@ -131,6 +131,7 @@
":libcamera_client_aidl",
":libcamera_client_framework_aidl",
":libupdate_engine_aidl",
+ ":libupdate_engine_stable-V2-java-source",
":logd_aidl",
":resourcemanager_aidl",
":storaged_aidl",
@@ -173,6 +174,9 @@
// and remove this line.
"//frameworks/base/tools/hoststubgen:__subpackages__",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
// AIDL files under these paths are mixture of public and private ones.
@@ -213,6 +217,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",
@@ -260,6 +265,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
@@ -428,6 +436,9 @@
],
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
@@ -471,6 +482,9 @@
],
compile_dex: false,
headers_only: true,
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_library {
@@ -498,6 +512,9 @@
"-Xep:AndroidFrameworkUid:ERROR",
],
},
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_library {
@@ -512,6 +529,7 @@
},
lint: {
enabled: false,
+ baseline_filename: "lint-baseline.xml",
},
}
@@ -536,6 +554,9 @@
],
sdk_version: "core_platform",
apex_available: ["//apex_available:platform"],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_library {
@@ -551,6 +572,9 @@
"calendar-provider-compat-config",
"contacts-provider-platform-compat-config",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
platform_compat_config {
@@ -605,6 +629,9 @@
"rappor",
],
dxflags: ["--core-library"],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
// utility classes statically linked into framework-wifi and dynamically linked
@@ -630,6 +657,10 @@
"//frameworks/base/services/net",
"//packages/modules/Wifi/framework",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
+ apex_available: ["com.android.wifi"],
}
filegroup {
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 117faa2..d59775f 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -132,6 +132,9 @@
},
{
"name": "vts_treble_vintf_vendor_test"
+ },
+ {
+ "name": "CtsStrictJavaPackagesTestCases"
}
],
"postsubmit-ravenwood": [
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 9029d25..b3b18b6 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -60,8 +60,40 @@
metalava_cmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED "
metalava_cmd += " --quiet "
+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",
@@ -269,6 +301,7 @@
// classpath (or sources) somehow.
stubs_defaults {
name: "android-non-updatable-stubs-defaults",
+ defaults: ["framework-minus-apex-aconfig-declarations"],
srcs: [":android-non-updatable-stub-sources"],
sdk_version: "none",
system_modules: "none",
@@ -307,10 +340,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",
@@ -448,3 +477,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 bcfb68f..6b8c02f 100644
--- a/api/ApiDocs.bp
+++ b/api/ApiDocs.bp
@@ -183,6 +183,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
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp
index 28b2d4b..ec4fc46 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -239,6 +239,10 @@
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 +269,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 +295,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 +321,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 +347,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 +362,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 +386,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 +410,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 +434,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 +542,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 +560,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 +601,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 +625,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 +634,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 +671,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",
},
@@ -900,10 +1044,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..a632582 100644
--- a/api/api.go
+++ b/api/api.go
@@ -64,6 +64,7 @@
type CombinedApis struct {
android.ModuleBase
+ android.DefaultableModuleBase
properties CombinedApisProperties
}
@@ -74,6 +75,7 @@
func registerBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("combined_apis", combinedApisModuleFactory)
+ ctx.RegisterModuleType("combined_apis_defaults", CombinedApisModuleDefaultsFactory)
}
var PrepareForCombinedApisTest = android.FixtureRegisterWithContext(registerBuildComponents)
@@ -203,6 +205,15 @@
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"}
+ ctx.CreateModule(java.LibraryFactory, &props)
+}
+
func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) {
// First create the all-updatable-modules-system-stubs
{
@@ -227,6 +238,30 @@
}
}
+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"}
+ 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"}
+ ctx.CreateModule(java.LibraryFactory, &props)
+ }
+}
+
func createMergedTestStubsForNonUpdatableModules(ctx android.LoadHookContext) {
props := libraryProps{}
props.Name = proptools.StringPtr("all-non-updatable-modules-test-stubs")
@@ -236,6 +271,15 @@
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"}
+ ctx.CreateModule(java.LibraryFactory, &props)
+}
+
func createMergedFrameworkImpl(ctx android.LoadHookContext, modules []string) {
// This module is for the "framework-all" module, which should not include the core libraries.
modules = removeAll(modules, core_libraries_modules)
@@ -266,6 +310,19 @@
}
}
+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"}
+ 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.
@@ -381,6 +438,27 @@
}
}
+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"}
+
+ ctx.CreateModule(java.LibraryFactory, &props)
+ }
+}
+
func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
bootclasspath := a.properties.Bootclasspath
system_server_classpath := a.properties.System_server_classpath
@@ -396,6 +474,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 +486,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 +531,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 820d2b0..77b74e9 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -398,8 +398,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 c49971e..11b24f5 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -6172,8 +6172,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..8d8a82b 100644
--- a/core/api/Android.bp
+++ b/core/api/Android.bp
@@ -96,21 +96,3 @@
name: "non-updatable-test-lint-baseline.txt",
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",
- ],
-}
-
-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",
- ],
-}
diff --git a/core/api/current.txt b/core/api/current.txt
index 1b5c953..aa2e39b 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.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";
@@ -16680,7 +16681,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 {
@@ -22222,6 +22222,7 @@
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 public void release();
method public void releaseOutputBuffer(int, boolean);
@@ -22283,6 +22284,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);
}
@@ -22370,6 +22372,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();
@@ -22385,6 +22388,7 @@
public final class MediaCodec.QueueRequest {
method public void queue();
+ method @FlaggedApi("com.android.media.codec.flags.large_audio_frame") @NonNull public android.media.MediaCodec.QueueRequest setBufferInfos(@NonNull java.util.ArrayDeque<android.media.MediaCodec.BufferInfo>);
method @NonNull public android.media.MediaCodec.QueueRequest setByteBufferParameter(@NonNull String, @NonNull java.nio.ByteBuffer);
method @NonNull public android.media.MediaCodec.QueueRequest setEncryptedLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, int, int, @NonNull android.media.MediaCodec.CryptoInfo);
method @NonNull public android.media.MediaCodec.QueueRequest setFlags(int);
@@ -23246,6 +23250,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";
@@ -23274,6 +23280,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";
@@ -28793,6 +28800,8 @@
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";
@@ -28808,6 +28817,13 @@
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 = -1; // 0xffffffff
+ 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 = -1; // 0xffffffff
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
@@ -33723,6 +33739,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.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";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e92564b..70375c2 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -9878,8 +9878,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);
@@ -9888,9 +9888,9 @@
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;
}
@@ -10500,7 +10500,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/test-current.txt b/core/api/test-current.txt
index a3cd3dc..83d72ad 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -156,6 +156,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
@@ -2580,7 +2581,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";
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index b4a6955..845a346 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 6b7f4880..82ad6bc 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -712,6 +712,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;
@@ -3574,7 +3576,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;
@@ -3646,9 +3648,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/OWNERS b/core/java/android/app/OWNERS
index 772b0b4..968aea4 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -88,6 +88,10 @@
# Pinner
per-file pinner-client.aconfig = file:/core/java/android/app/pinner/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/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/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index ec181da..27f6a26 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -156,22 +156,6 @@
}
/**
- * @hide
- */
- public static class AdapterChildHostView extends AppWidgetHostView {
-
- public AdapterChildHostView(Context context) {
- super(context);
- }
-
- @Override
- public Context getRemoteContextEnsuringCorrectCachedApkPath() {
- // To reduce noise in error messages
- return null;
- }
- }
-
- /**
* Set the AppWidget that will be displayed by this view. This method also adds default padding
* to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)}
* and can be overridden in order to add custom padding.
@@ -937,31 +921,17 @@
setColorResources(RemoteViews.ColorResources.create(mContext, colorMapping));
}
- private void setColorResourcesStates(RemoteViews.ColorResources colorResources) {
- mColorResources = colorResources;
- mColorMappingChanged = true;
- mViewMode = VIEW_MODE_NOINIT;
- }
-
/** @hide **/
public void setColorResources(RemoteViews.ColorResources colorResources) {
if (colorResources == mColorResources) {
return;
}
- setColorResourcesStates(colorResources);
+ mColorResources = colorResources;
+ mColorMappingChanged = true;
+ mViewMode = VIEW_MODE_NOINIT;
reapplyLastRemoteViews();
}
- /**
- * @hide
- */
- public void setColorResourcesNoReapply(RemoteViews.ColorResources colorResources) {
- if (colorResources == mColorResources) {
- return;
- }
- setColorResourcesStates(colorResources);
- }
-
/** Check if, in the current context, the two color mappings are equivalent. */
private boolean isSameColorMapping(SparseIntArray oldColors, SparseIntArray newColors) {
if (oldColors.size() != newColors.size()) {
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/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/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/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..6e72f8e
--- /dev/null
+++ b/core/java/android/net/thread/flags.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.net.thread.flags"
+
+flag {
+ name: "thread_user_restriction_enabled"
+ namespace: "thread_network"
+ description: "Controls whether user restriction on thread networks is enabled"
+ bug: "307679182"
+}
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/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index f6beec1..85879ac 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -86,4 +86,5 @@
boolean enableReaderOption(boolean enable);
boolean isObserveModeSupported();
boolean setObserveMode(boolean enabled);
+ void updateDiscoveryTechnology(IBinder b, int pollFlags, int listenFlags);
}
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index 191385a..f4b4604 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/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/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 8d75cac..f03fc0a 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/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/core/java/android/nfc/NfcAdapter.java
index 98a980f..979855e 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -284,6 +284,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 +332,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 +372,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 use current flags.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_LISTEN_KEEP = -1;
+
+ /**
+ * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
+ * <p>
+ * Setting this flag makes polling to use current flags.
+ */
+ @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
+ public static final int FLAG_READER_KEEP = -1;
+
+ /** @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 +519,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
@@ -948,7 +1047,7 @@
*/
@SystemApi
@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public int getAdapterState() {
+ public @AdapterState int getAdapterState() {
try {
return sService.getState();
} catch (RemoteException e) {
@@ -1216,7 +1315,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public void setBeamPushUris(Uri[] uris, Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1286,7 +1385,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1371,7 +1470,7 @@
@UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity,
Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1385,7 +1484,7 @@
@SystemApi
@UnsupportedAppUsage
public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1464,7 +1563,7 @@
@UnsupportedAppUsage
public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1515,7 +1614,7 @@
@UnsupportedAppUsage
public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
Activity activity, Activity ... activities) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1558,7 +1657,7 @@
*/
public void enableForegroundDispatch(Activity activity, PendingIntent intent,
IntentFilter[] filters, String[][] techLists) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1593,7 +1692,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 +1728,7 @@
*/
public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
Bundle extras) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1646,7 +1745,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 +1773,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 +1788,80 @@
}
/**
+ * 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.
+ * 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) {
+ 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,
+ * which were changed by {@link #setDiscoveryTechnology(Activity , int , int)}
+ *
+ * @param activity The Activity that requests to changed 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 +1891,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public boolean invokeBeam(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1756,7 +1929,7 @@
@Deprecated
@UnsupportedAppUsage
public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -1786,7 +1959,7 @@
@Deprecated
@UnsupportedAppUsage
public void disableForegroundNdefPush(Activity activity) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2066,7 +2239,7 @@
@java.lang.Deprecated
@UnsupportedAppUsage
public boolean isNdefPushEnabled() {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
@@ -2180,7 +2353,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 +2402,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
- synchronized (NfcAdapter.class) {
+ synchronized (sLock) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index e331c95..41dee3a 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/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/core/java/android/nfc/cardemulation/CardEmulation.java
index 58b6179..ad86d70 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/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/flags.aconfig b/core/java/android/nfc/flags.aconfig
index 17e0427..11be905 100644
--- a/core/java/android/nfc/flags.aconfig
+++ b/core/java/android/nfc/flags.aconfig
@@ -48,3 +48,17 @@
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"
+}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 02e40cf..05b7827f 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -339,7 +339,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
@android.ravenwood.annotation.RavenwoodReplace
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 3a32b2b..4dc32d5 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;
@@ -474,6 +476,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();
@@ -525,6 +529,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 209a595..eb5b511 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -92,3 +92,10 @@
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
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 7e07e1f..c65c10c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1565,7 +1565,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);
/**
@@ -1599,7 +1607,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 f71c269..07f7690 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;
@@ -75,7 +70,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;
@@ -426,72 +420,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 94f90cc..e32a8f3 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -2435,11 +2435,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
@@ -2492,10 +2493,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..4bcfb4b
--- /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 c280d13..7437f64 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1882,6 +1882,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.flags.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
@@ -1967,6 +1991,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/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/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 78a12f7..3a57e84 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 2cc56d8..3249904 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -13397,6 +13397,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 72c436e..934c0a1 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -368,11 +368,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/flags.aconfig b/core/java/android/security/flags.aconfig
index b56bef3..43163b3 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -50,3 +50,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
index 4e5588c..0bae459 100644
--- a/core/java/android/security/responsible_apis_flags.aconfig
+++ b/core/java/android/security/responsible_apis_flags.aconfig
@@ -20,3 +20,24 @@
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/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/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/widget/RemoteCollectionItemsAdapter.java b/core/java/android/widget/RemoteCollectionItemsAdapter.java
index 9b396ae..d843308 100644
--- a/core/java/android/widget/RemoteCollectionItemsAdapter.java
+++ b/core/java/android/widget/RemoteCollectionItemsAdapter.java
@@ -18,7 +18,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.appwidget.AppWidgetHostView;
import android.util.SparseIntArray;
import android.view.View;
import android.view.ViewGroup;
@@ -26,6 +25,8 @@
import android.widget.RemoteViews.InteractionHandler;
import android.widget.RemoteViews.RemoteCollectionItems;
+import com.android.internal.R;
+
import java.util.stream.IntStream;
/**
@@ -177,14 +178,40 @@
RemoteViews item = mItems.getItemView(position);
item.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD);
+ View reapplyView = getViewToReapply(convertView, item);
- AppWidgetHostView newView = convertView instanceof AppWidgetHostView.AdapterChildHostView
- widgetChildView
- ? widgetChildView
- : new AppWidgetHostView.AdapterChildHostView(parent.getContext());
- newView.setInteractionHandler(mInteractionHandler);
- newView.setColorResourcesNoReapply(mColorResources);
- newView.updateAppWidget(item);
- return newView;
+ // Reapply the RemoteViews if we can.
+ if (reapplyView != null) {
+ try {
+ item.reapply(
+ parent.getContext(),
+ reapplyView,
+ mInteractionHandler,
+ null /* size */,
+ mColorResources);
+ return reapplyView;
+ } catch (RuntimeException e) {
+ // We can't reapply for some reason, we'll fallback to an apply and inflate a
+ // new view.
+ }
+ }
+
+ return item.apply(
+ parent.getContext(),
+ parent,
+ mInteractionHandler,
+ null /* size */,
+ mColorResources);
+ }
+
+ /** Returns {@code convertView} if it can be used to reapply {@code item}, or null otherwise. */
+ @Nullable
+ private static View getViewToReapply(@Nullable View convertView, @NonNull RemoteViews item) {
+ if (convertView == null) return null;
+
+ Object layoutIdTag = convertView.getTag(R.id.widget_frame);
+ if (!(layoutIdTag instanceof Integer)) return null;
+
+ return item.getLayoutId() == (Integer) layoutIdTag ? convertView : null;
}
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 8ad10af..5eb66c5 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -7013,13 +7013,13 @@
View parent = (View) view.getParent();
// Break the for loop on the first encounter of:
// 1) an AdapterView,
- // 2) an AppWidgetHostView that is not a child of an adapter view, or
+ // 2) an AppWidgetHostView that is not a RemoteViewsFrameLayout, or
// 3) a null parent.
// 2) and 3) are unexpected and catch the case where a child is not
// correctly parented in an AdapterView.
while (parent != null && !(parent instanceof AdapterView<?>)
&& !((parent instanceof AppWidgetHostView)
- && !(parent instanceof AppWidgetHostView.AdapterChildHostView))) {
+ && !(parent instanceof RemoteViewsAdapter.RemoteViewsFrameLayout))) {
parent = (View) parent.getParent();
}
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 2f28a87..61a7599 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -368,7 +368,7 @@
* A FrameLayout which contains a loading view, and manages the re/applying of RemoteViews when
* they are loaded.
*/
- static class RemoteViewsFrameLayout extends AppWidgetHostView.AdapterChildHostView {
+ static class RemoteViewsFrameLayout extends AppWidgetHostView {
private final FixedSizeRemoteViewsCache mCache;
public int cacheIndex = -1;
@@ -408,6 +408,11 @@
}
@Override
+ protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
+ return null;
+ }
+
+ @Override
protected View getErrorView() {
// Use the default loading view as the error view.
return getDefaultView();
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/com/android/internal/util/RingBuffer.java b/core/java/com/android/internal/util/RingBuffer.java
index 0488659..342ba1b6 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.
@@ -30,16 +33,35 @@
@android.ravenwood.annotation.RavenwoodKeepWholeClass
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() {
@@ -69,22 +91,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/ILockSettingsStateListener.aidl b/core/java/com/android/internal/widget/ILockSettingsStateListener.aidl
new file mode 100644
index 0000000..25e3003
--- /dev/null
+++ b/core/java/com/android/internal/widget/ILockSettingsStateListener.aidl
@@ -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
+ */
+oneway interface ILockSettingsStateListener {
+ /**
+ * 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);
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/widget/LockSettingsInternal.java b/core/java/com/android/internal/widget/LockSettingsInternal.java
index 8114e1f..627e877 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(ILockSettingsStateListener listener);
+
+ /**
+ * Unregister a LockSettingsStateListener
+ * @param listener The listener to be unregistered
+ */
+ public abstract void unregisterLockSettingsStateListener(ILockSettingsStateListener listener);
}
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 2a744e3..45bb629 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -188,8 +188,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",
@@ -277,6 +275,7 @@
"libdmabufinfo",
"libgif",
"libgui_window_info_static",
+ "libkernelconfigs",
"libseccomp_policy",
"libgrallocusage",
"libscrypt_static",
@@ -346,7 +345,6 @@
"libnativeloader_lazy",
"libmemunreachable",
"libhidlbase",
- "libvintf",
"libnativedisplay",
"libnativewindow",
"libdl",
@@ -453,8 +451,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 c24d21d..653ec2b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -152,8 +152,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);
@@ -653,6 +651,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[
@@ -898,6 +898,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");
@@ -1537,8 +1540,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_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index de1ce4e..1504a00 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
{
@@ -1004,10 +1004,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..ce4a337 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;
@@ -46,6 +44,7 @@
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 +92,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;
}
@@ -170,7 +173,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 +202,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/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 7c5885a..7e325a5 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -2187,6 +2187,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);
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..a854e36 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -18,6 +18,7 @@
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
@@ -31,5 +32,3 @@
# Accessibility
pweaver@google.com
-hongmingjin@google.com
-cbrower@google.com
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c6a241f..4df8e06 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3546,6 +3546,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.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.
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 3a2e50a..9bb2499 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" />
@@ -154,8 +160,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 -->
@@ -193,11 +199,14 @@
<shortcode country="mk" pattern="\\d{1,6}" free="129005|122" />
<!-- 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" />
+
<!-- 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" />
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 60500d5..78a2c1c 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;
@@ -55,6 +57,7 @@
import android.platform.test.annotations.IgnoreUnderRavenwood;
import android.platform.test.ravenwood.RavenwoodRule;
import android.provider.DocumentsContract.Document;
+import android.system.Os;
import android.util.DataUnit;
import androidx.test.runner.AndroidJUnit4;
@@ -67,6 +70,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;
@@ -78,6 +83,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
+import java.net.InetSocketAddress;
@RunWith(AndroidJUnit4.class)
public class FileUtilsTest {
@@ -253,6 +259,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/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/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/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/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/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/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index 9c05a3a..83ddfc5 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) {
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/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index ccc3438..e421356 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
@@ -347,7 +347,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 4741170..14e8653 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -226,15 +226,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/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 0b42c88..f526a28 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -230,7 +230,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 1f3834be..c904542 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -262,7 +262,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 c5ffbb7..c8d5987 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -118,7 +118,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);
}
@@ -171,6 +171,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 098a746..ebe8b6e 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, IRenderPipeline::DrawResult& drawResult,
const SkRect& screenDirty, FrameInfo* currentFrameInfo,
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index d747489..fd0a8e0 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(preTransform);
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index e2ea57d..624eaa5 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, IRenderPipeline::DrawResult& drawResult,
const SkRect& screenDirty, FrameInfo* currentFrameInfo,
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 56b52dc..9c7f7cc 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -625,14 +625,9 @@
{
// 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);
+ drawResult = mRenderPipeline->draw(
+ frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue, mContentDrawBounds,
+ mOpaque, mLightInfo, mRenderNodes, &(profiler()), mBufferParams, profilerLock());
}
uint64_t frameCompleteNr = getFrameNumber();
@@ -762,7 +757,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);
}
@@ -791,7 +786,7 @@
void CanvasContext::reportMetricsWithPresentTime() {
{ // acquire lock
- std::scoped_lock lock(mFrameMetricsReporterMutex);
+ std::scoped_lock lock(mFrameInfoMutex);
if (mFrameMetricsReporter == nullptr) {
return;
}
@@ -826,7 +821,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);
@@ -835,7 +830,7 @@
}
void CanvasContext::addFrameMetricsObserver(FrameMetricsObserver* observer) {
- std::scoped_lock lock(mFrameMetricsReporterMutex);
+ std::scoped_lock lock(mFrameInfoMutex);
if (mFrameMetricsReporter.get() == nullptr) {
mFrameMetricsReporter.reset(new FrameMetricsReporter());
}
@@ -849,7 +844,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()) {
@@ -886,7 +881,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(
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index be9b649..e2e3fa3 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -164,6 +164,7 @@
void notifyFramePending();
FrameInfoVisualizer& profiler() { return mProfiler; }
+ std::mutex& profilerLock() { return mFrameInfoMutex; }
void dumpFrames(int fd);
void resetFrameStats();
@@ -342,9 +343,8 @@
std::string mName;
JankTracker mJankTracker;
FrameInfoVisualizer mProfiler;
- std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter
- GUARDED_BY(mFrameMetricsReporterMutex);
- std::mutex mFrameMetricsReporterMutex;
+ std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter 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 9c879d5..b8c3a4d 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -68,7 +68,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, IRenderPipeline::DrawResult&,
const SkRect& screenDirty, FrameInfo* currentFrameInfo,
bool* requireSwap) = 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/AudioHalVersionInfo.java b/media/java/android/media/AudioHalVersionInfo.java
index 0f48abeb..25b1404 100644
--- a/media/java/android/media/AudioHalVersionInfo.java
+++ b/media/java/android/media/AudioHalVersionInfo.java
@@ -78,11 +78,10 @@
/**
* 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.
*/
- // 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, HIDL_4_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..862ae8d 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -17,6 +17,7 @@
package android.media;
import android.Manifest;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -43,21 +44,25 @@
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;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME;
/**
MediaCodec class can be used to access low-level media codecs, i.e. encoder/decoder components.
It is part of the Android low-level multimedia support infrastructure (normally used together
@@ -1824,6 +1829,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 +1951,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);
@@ -2836,11 +2875,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;
@@ -3462,6 +3562,26 @@
}
/**
+ * Sets MediaCodec.BufferInfo objects describing the access units
+ * contained in this queue request. Access units must be laid out
+ * contiguously without gaps and in order.
+ *
+ * @param infos Represents {@link MediaCodec.BufferInfo} objects to mark
+ * individual access-unit boundaries and the timestamps associated with it.
+ * The buffer is expected to contain the data in a continuous manner.
+ * @return this object
+ */
+ @FlaggedApi(FLAG_LARGE_AUDIO_FRAME)
+ public @NonNull QueueRequest setBufferInfos(@NonNull ArrayDeque<BufferInfo> infos) {
+ if (!isAccessible()) {
+ throw new IllegalStateException("The request is stale");
+ }
+ mBufferInfos.clear();
+ mBufferInfos.addAll(infos);
+ return this;
+ }
+
+ /**
* Add an integer parameter.
* See {@link MediaFormat} for an exhaustive list of supported keys with
* values of type int, that can also be set with {@link MediaFormat#setInteger}.
@@ -3577,10 +3697,18 @@
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, mCryptoInfo,
+ mBufferInfos.toArray(),
mTuningKeys, mTuningValues);
} else if (mHardwareBuffer != null) {
mCodec.native_queueHardwareBuffer(
@@ -3598,6 +3726,7 @@
mHardwareBuffer = null;
mPresentationTimeUs = 0;
mFlags = 0;
+ mBufferInfos.clear();
mTuningKeys.clear();
mTuningValues.clear();
return this;
@@ -3621,6 +3750,7 @@
private HardwareBuffer mHardwareBuffer = null;
private long mPresentationTimeUs = 0;
private @BufferFlag int mFlags = 0;
+ private final ArrayDeque<BufferInfo> mBufferInfos = new ArrayDeque<>();
private final ArrayList<String> mTuningKeys = new ArrayList<>();
private final ArrayList<Object> mTuningValues = new ArrayList<>();
@@ -3630,11 +3760,8 @@
private native void native_queueLinearBlock(
int index,
@NonNull LinearBlock block,
- int offset,
- int size,
@Nullable CryptoInfo cryptoInfo,
- long presentationTimeUs,
- int flags,
+ @NonNull Object[] bufferInfos,
@NonNull ArrayList<String> keys,
@NonNull ArrayList<Object> values);
@@ -4048,6 +4175,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 +4553,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 +4594,7 @@
mLinearBlock = null;
mHardwareBuffer = null;
mFormat = null;
+ mBufferInfos.clear();
mChangedKeys.clear();
mKeySet.clear();
mLoaded = false;
@@ -4448,6 +4613,11 @@
mFlags = info.flags;
}
+ void setBufferInfos(ArrayDeque<BufferInfo> infos) {
+ mBufferInfos.clear();
+ mBufferInfos.addAll(infos);
+ }
+
boolean isLoaded() {
return mLoaded;
}
@@ -4462,6 +4632,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;
@@ -5170,6 +5341,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/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 46db777..5e40eee 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -16,6 +16,10 @@
package android.media;
+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 +122,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 +464,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 +1687,34 @@
*/
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";
+
/* 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 8e9c079..a0f8ae5 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1154,6 +1154,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/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index ef90bf9..8cdd59e 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,
@@ -430,10 +459,11 @@
}
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(
@@ -446,13 +476,13 @@
const uint8_t iv[16],
CryptoPlugin::Mode mode,
const CryptoPlugin::Pattern &pattern,
- int64_t presentationTimeUs,
- uint32_t flags,
+ const sp<RefBase> &infos,
const sp<AMessage> &tunings,
AString *errorDetailMsg) {
+ sp<BufferInfosWrapper> auInfo((BufferInfosWrapper *)infos.get());
return mCodec->queueEncryptedBuffer(
index, buffer, offset, subSamples, numSubSamples, key, iv, mode, pattern,
- presentationTimeUs, flags, tunings, errorDetailMsg);
+ auInfo, tunings, errorDetailMsg);
}
status_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
@@ -722,6 +752,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 +798,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 +818,7 @@
(jlong)context.release(),
true);
env->SetObjectField(frame, gFields.outputFrameLinearBlockID, linearBlock.get());
+ maybeSetBufferInfos(env, frame, bufInfos);
break;
}
case C2BufferData::GRAPHIC: {
@@ -787,6 +859,7 @@
(jlong)context.release(),
true);
env->SetObjectField(frame, gFields.outputFrameLinearBlockID, linearBlock.get());
+ maybeSetBufferInfos(env, frame, bufInfos);
} else {
// No-op.
}
@@ -1250,6 +1323,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 +1361,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 +1449,9 @@
arg2,
obj);
+ for (int i = 0; i < jObjectInfos.size(); i++) {
+ env->DeleteLocalRef(jObjectInfos[i]);
+ }
env->DeleteLocalRef(obj);
}
@@ -1913,6 +2019,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},
@@ -2559,8 +2762,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) {
+ jobject cryptoInfoObj, jobjectArray objArray, jobject keys, jobject values) {
ALOGV("android_media_MediaCodec_native_queueLinearBlock");
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
@@ -2578,7 +2780,24 @@
"error occurred while converting tunings from Java to native");
return;
}
-
+ jint totalSize;
+ jint initialOffset;
+ 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 +2806,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 +2820,6 @@
return;
}
- AString errorDetailMsg;
if (codec->hasCryptoOrDescrambler()) {
if (!memory) {
// It means there was an unexpected failure in extractMemoryFromContext above
@@ -2615,7 +2833,7 @@
return;
}
auto cryptoInfo =
- cryptoInfoObj ? NativeCryptoInfo{env, cryptoInfoObj} : NativeCryptoInfo{size};
+ cryptoInfoObj ? NativeCryptoInfo{env, cryptoInfoObj} : NativeCryptoInfo{totalSize};
if (env->ExceptionCheck()) {
// Creation of cryptoInfo failed. Let the exception bubble up.
return;
@@ -2623,13 +2841,12 @@
err = codec->queueEncryptedLinearBlock(
index,
memory,
- offset,
+ initialOffset,
cryptoInfo.mSubSamples, cryptoInfo.mNumSubSamples,
(const uint8_t *)cryptoInfo.mKey, (const uint8_t *)cryptoInfo.mIv,
cryptoInfo.mMode,
cryptoInfo.mPattern,
- presentationTimeUs,
- flags,
+ infos,
tunings,
&errorDetailMsg);
ALOGI_IF(err != OK, "queueEncryptedLinearBlock returned err = %d", err);
@@ -2646,7 +2863,7 @@
return;
}
err = codec->queueBuffer(
- index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg);
+ index, buffer, infos, tunings, &errorDetailMsg);
}
throwExceptionAsNecessary(
env, err, ACTION_CODE_FATAL,
@@ -2704,8 +2921,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 +3434,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 +3625,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 +3681,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,6 +3944,9 @@
{ "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 },
@@ -3711,8 +3957,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;Landroid/media/MediaCodec$CryptoInfo;"
+ "[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..02708ef 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,
@@ -108,7 +116,7 @@
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(
@@ -121,8 +129,7 @@
const uint8_t iv[16],
CryptoPlugin::Mode mode,
const CryptoPlugin::Pattern &pattern,
- int64_t presentationTimeUs,
- uint32_t flags,
+ const sp<RefBase> &infos,
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/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 9f2a9ac..9605108 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/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/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/SettingsLib/AdaptiveIcon/Android.bp b/packages/SettingsLib/AdaptiveIcon/Android.bp
index df72a92..044ba87 100644
--- a/packages/SettingsLib/AdaptiveIcon/Android.bp
+++ b/packages/SettingsLib/AdaptiveIcon/Android.bp
@@ -15,9 +15,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 b9dc618..1e49330 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -59,6 +59,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 986baf7..bd0dbdc 100644
--- a/packages/SettingsLib/EmergencyNumber/Android.bp
+++ b/packages/SettingsLib/EmergencyNumber/Android.bp
@@ -17,4 +17,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 010a6ce..d9f74da 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 028489d..3b04bd9 100644
--- a/packages/SettingsLib/RestrictedLockUtils/Android.bp
+++ b/packages/SettingsLib/RestrictedLockUtils/Android.bp
@@ -30,4 +30,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 2d93e4e..22e4e94 100644
--- a/packages/SettingsLib/SchedulesProvider/Android.bp
+++ b/packages/SettingsLib/SchedulesProvider/Android.bp
@@ -14,9 +14,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 c07a802..c385d38 100644
--- a/packages/SettingsLib/SearchProvider/Android.bp
+++ b/packages/SettingsLib/SearchProvider/Android.bp
@@ -15,4 +15,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 81a8b324..cea3d13 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 eb9e329..19c59dd 100644
--- a/packages/SettingsLib/Tile/Android.bp
+++ b/packages/SettingsLib/Tile/Android.bp
@@ -14,8 +14,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 c7ad24c..d5a56c8 100644
--- a/packages/SettingsLib/Utils/Android.bp
+++ b/packages/SettingsLib/Utils/Android.bp
@@ -31,4 +31,7 @@
"com.android.healthfitness",
"com.android.permission",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
diff --git a/packages/SettingsLib/search/Android.bp b/packages/SettingsLib/search/Android.bp
index 202e7fe..3b14712 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 {
@@ -24,6 +27,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 5bc27195..943e3fc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
@@ -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 85e8769..1eedb8e 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -282,6 +282,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/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 5b59e7d..2b41178 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -34,6 +34,9 @@
srcs: [
":statslog-SystemUI-java-gen",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
android_library {
@@ -70,6 +73,9 @@
min_sdk_version: "current",
plugins: ["dagger2-compiler"],
kotlincflags: ["-Xjvm-default=all"],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_library {
@@ -81,6 +87,9 @@
static_kotlin_stdlib: false,
java_version: "1.8",
min_sdk_version: "current",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
java_library {
@@ -100,4 +109,7 @@
},
java_version: "1.8",
min_sdk_version: "current",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
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 30a445f..703b3c6 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..10bf068 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 4a4d4e1..2f398fe 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/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 81fd8ce..e52cefb 100644
--- a/packages/SystemUI/unfold/Android.bp
+++ b/packages/SystemUI/unfold/Android.bp
@@ -39,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/services/backup/Android.bp b/services/backup/Android.bp
index acb5911..d08a97e 100644
--- a/services/backup/Android.bp
+++ b/services/backup/Android.bp
@@ -19,7 +19,13 @@
defaults: ["platform_service_defaults"],
srcs: [":services.backup-sources"],
libs: ["services.core"],
- static_libs: ["app-compat-annotations", "backup_flags_lib"],
+ static_libs: [
+ "app-compat-annotations",
+ "backup_flags_lib",
+ ],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
aconfig_declarations {
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
index 550e17b..2bfdd0a 100644
--- a/services/companion/Android.bp
+++ b/services/companion/Android.bp
@@ -31,4 +31,7 @@
"virtualdevice_flags_lib",
"virtual_camera_service_aidl-java",
],
+ 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/core/Android.bp b/services/core/Android.bp
index f5a80d8..5b761d1 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -204,6 +204,7 @@
"com_android_wm_shell_flags_lib",
"com.android.server.utils_aconfig-java",
"service-jobscheduler-deviceidle.flags-aconfig-java",
+ "net_flags_lib",
],
javac_shard_size: 50,
javacflags: [
@@ -213,6 +214,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 {
@@ -231,6 +235,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 c258370..e923e30a 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
@@ -42,3 +43,6 @@
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 39b8643..7a4ac6a 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1356,8 +1356,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);
}
}
@@ -3231,12 +3231,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);
@@ -3276,12 +3276,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);
@@ -3348,27 +3347,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 40b29d7..3483c1a 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -315,6 +315,11 @@
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<>();
@@ -504,6 +509,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.
@@ -1309,6 +1318,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,
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 c436c72..c18bacb 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -136,6 +136,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
};
@@ -171,6 +172,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/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index ae0cd65..c8f6303 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -401,7 +401,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":
@@ -3681,11 +3681,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();
@@ -3720,15 +3719,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 d0ab287..626b70b 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -275,7 +275,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/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 40b1de6..1412259 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 3156e9d..65c2cc5 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2935,7 +2935,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.
@@ -2943,12 +2947,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 {
@@ -2962,12 +2963,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,
@@ -3063,25 +3071,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/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 8091753..a29922b 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1046,11 +1046,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();
}
}
@@ -1113,6 +1111,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);
@@ -1774,6 +1800,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 290bb7e..a79e7db 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -7857,7 +7857,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 */
@@ -12619,12 +12618,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/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 56a94ec0..49f6070 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -1424,7 +1424,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 80c3a27..b542893 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -583,8 +583,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/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 2ab15e6..c6f9203 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -4571,8 +4571,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/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/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 0c2eee5..c81ce26 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;
@@ -90,6 +91,7 @@
import android.os.IBinder;
import android.os.IProgressListener;
import android.os.Process;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -135,6 +137,7 @@
import com.android.internal.util.Preconditions;
import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.ILockSettings;
+import com.android.internal.widget.ILockSettingsStateListener;
import com.android.internal.widget.IWeakEscrowTokenActivatedListener;
import com.android.internal.widget.IWeakEscrowTokenRemovedListener;
import com.android.internal.widget.LockPatternUtils;
@@ -327,6 +330,9 @@
private HashMap<UserHandle, UserManager> mUserManagerCache = new HashMap<>();
+ private final RemoteCallbackList<ILockSettingsStateListener> mLockSettingsStateListeners =
+ new RemoteCallbackList<>();
+
// 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,37 @@
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) {
+ int i = mLockSettingsStateListeners.beginBroadcast();
+ try {
+ while (i > 0) {
+ i--;
+ try {
+ if (success) {
+ mLockSettingsStateListeners.getBroadcastItem(i)
+ .onAuthenticationSucceeded(userId);
+ } else {
+ mLockSettingsStateListeners.getBroadcastItem(i)
+ .onAuthenticationFailed(userId);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception while notifying LockSettingsStateListener:"
+ + " success = " + success + ", userId = " + userId, e);
+ }
+ }
+ } finally {
+ mLockSettingsStateListeners.finishBroadcast();
+ }
+ }
+
@Override
public VerifyCredentialResponse verifyTiedProfileChallenge(LockscreenCredential credential,
int userId, @LockPatternUtils.VerifyFlag int flags) {
@@ -3663,6 +3696,18 @@
public void refreshStrongAuthTimeout(int userId) {
mStrongAuth.refreshStrongAuthTimeout(userId);
}
+
+ @Override
+ public void registerLockSettingsStateListener(
+ @NonNull ILockSettingsStateListener listener) {
+ mLockSettingsStateListeners.register(listener);
+ }
+
+ @Override
+ public void unregisterLockSettingsStateListener(
+ @NonNull ILockSettingsStateListener listener) {
+ mLockSettingsStateListeners.unregister(listener);
+ }
}
private class RebootEscrowCallbacks implements RebootEscrowManager.Callbacks {
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 46e7041..e43cbef 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -47,6 +47,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 +55,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,6 +79,7 @@
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;
@@ -96,6 +99,7 @@
import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED;
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;
@@ -202,12 +206,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;
@@ -243,6 +247,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;
@@ -458,6 +463,12 @@
*/
private static final int MSG_UIDS_BLOCKED_REASONS_CHANGED = 23;
+ /**
+ * 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;
+
private static final int UID_MSG_STATE_CHANGED = 100;
private static final int UID_MSG_GONE = 101;
@@ -476,7 +487,7 @@
private ConnectivityManager mConnManager;
private PowerManagerInternal mPowerManagerInternal;
- private PowerWhitelistManager mPowerWhitelistManager;
+ private PowerExemptionManager mPowerExemptionManager;
@NonNull
private final Dependencies mDeps;
@@ -491,6 +502,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();
@@ -515,6 +532,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<>();
@@ -546,6 +572,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();
@@ -625,6 +653,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();
@@ -824,7 +860,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);
@@ -860,15 +896,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);
}
}
@@ -1018,6 +1054,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();
@@ -1028,17 +1072,22 @@
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;
+ // TODO (b/319728914): Filter out the unnecessary changes when using no cutpoint.
+
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);
@@ -1189,12 +1238,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();
}
@@ -3914,6 +3966,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);
@@ -4055,6 +4112,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) {
@@ -4176,6 +4249,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
@@ -4201,6 +4280,8 @@
// state changed, push updated rules
mUidState.put(uid, newUidState);
updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, newUidState);
+
+ boolean updatePowerRestrictionRules = false;
boolean allowedWhileIdleOrPowerSaveModeChanged =
isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
!= isProcStateAllowedWhileIdleOrPowerSaveMode(newUidState);
@@ -4212,19 +4293,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 {
@@ -4247,6 +4353,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);
@@ -4454,11 +4566,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);
}
@@ -4517,12 +4659,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;
}
/**
@@ -4611,6 +4753,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.
*/
@@ -4657,6 +4831,9 @@
"updateRulesForGlobalChangeAL: " + (restrictedNetworksChanged ? "R" : "-"));
}
try {
+ if (mBackgroundNetworkRestricted) {
+ updateRulesForBackgroundChainUL();
+ }
updateRulesForAppIdleUL();
updateRulesForRestrictPowerUL();
updateRulesForRestrictBackgroundUL();
@@ -4816,6 +4993,9 @@
updateRuleForAppIdleUL(uid, PROCESS_STATE_UNKNOWN);
updateRuleForDeviceIdleUL(uid);
updateRuleForRestrictPowerUL(uid);
+ if (mBackgroundNetworkRestricted) {
+ updateRuleForBackgroundUL(uid);
+ }
// Update internal rules.
updateRulesForPowerRestrictionsUL(uid);
}
@@ -4953,6 +5133,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);
@@ -4986,6 +5168,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.
@@ -5170,7 +5355,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")
@@ -5216,6 +5400,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);
@@ -5228,6 +5413,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;
@@ -5249,7 +5437,7 @@
oldEffectiveBlockedReasons = previousUidBlockedState.effectiveBlockedReasons;
newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
- uidRules = oldEffectiveBlockedReasons == newEffectiveBlockedReasons
+ uidRules = (oldEffectiveBlockedReasons == newEffectiveBlockedReasons)
? RULE_NONE
: uidBlockedState.deriveUidRules();
}
@@ -5442,6 +5630,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;
@@ -5853,6 +6063,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 {
@@ -5909,6 +6121,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);
@@ -6435,10 +6649,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;
@@ -6449,19 +6665,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
@@ -6486,6 +6707,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,
@@ -6499,6 +6721,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,
@@ -6518,6 +6741,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:
@@ -6548,6 +6773,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:
@@ -6615,7 +6842,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/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/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/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index 7d87d1b..cef3244 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 c48eccf..0e87396 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -5131,7 +5131,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/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 671e031..3afba39 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -3291,7 +3291,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()) {
@@ -3386,7 +3386,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.");
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index 375ef61..c2e2dad 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -523,6 +523,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/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 8d93408..13f1141 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -1279,8 +1279,8 @@
ipw.println();
}
- PackageWatchdog.getInstance(mContext).dump(ipw);
});
+ PackageWatchdog.getInstance(mContext).dump(ipw);
}
@AnyThread
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 9a85c42..e5a8a6d 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;
@@ -74,6 +77,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;
@@ -154,6 +158,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 {
@@ -291,6 +297,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);
@@ -892,7 +900,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
@@ -1442,6 +1462,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
@@ -1758,6 +1828,11 @@
}
};
+ @VisibleForTesting
+ void waitForIdle() {
+ mHandler.runWithScissors(() -> {}, 0);
+ }
+
private boolean isTrustUsuallyManagedInternal(int userId) {
synchronized (mTrustUsuallyManagedForUser) {
int i = mTrustUsuallyManagedForUser.indexOfKey(userId);
@@ -1878,7 +1953,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..ed04e5f 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 com.android.net.flags.FeatureFlags mCoreNetFeatureFlags;
private final boolean mIsInTestMode;
public VcnContext(
@@ -48,6 +49,7 @@
// Auto-generated class
mFeatureFlags = new FeatureFlagsImpl();
+ mCoreNetFeatureFlags = new com.android.net.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..5f4852f
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
@@ -0,0 +1,387 @@
+/*
+ * 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()
+ .getIpSecTransformState(
+ 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.getTimestamp() - mLastIpSecTransformState.getTimestamp())
+ + "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..a79f188
--- /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 getIpSecTransformState(
+ @NonNull Executor executor,
+ @NonNull OutcomeReceiver<IpSecTransformState, RuntimeException> callback) {
+ ipSecTransform.getIpSecTransformState(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/Task.java b/services/core/java/com/android/server/wm/Task.java
index 671acfc..3ef0048 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4785,6 +4785,7 @@
}
if (top.isAttached()) {
top.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+ top.mWaitForEnteringPinnedMode = false;
}
}
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 061fe0f..cc08488 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -31,5 +31,5 @@
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
+# 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 7b08413..4403bce 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -571,8 +571,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/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a490013..c95deb1 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;
@@ -484,6 +485,7 @@
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.net.module.util.ProxyUtils;
+import com.android.net.thread.flags.Flags;
import com.android.server.AlarmManagerInternal;
import com.android.server.LocalManagerRegistry;
import com.android.server.LocalServices;
@@ -13345,6 +13347,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 (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/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/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 4007672..582b712 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -41,12 +41,15 @@
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;
+import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -261,6 +264,7 @@
BackgroundThread.get().getThreadHandler().post(
() -> {
registerAppLaunchObserver();
+ registerDex2oatObserver();
registerOTAObserver();
});
}
@@ -304,6 +308,44 @@
}
}
+ private void registerDex2oatObserver() {
+ ArtManagerLocal aml = LocalManagerRegistry.getManager(ArtManagerLocal.class);
+ if (aml == null) {
+ Log.w(LOG_TAG, "Couldn't get ArtManagerLocal");
+ return;
+ }
+ aml.setBatchDexoptStartCallback(ForkJoinPool.commonPool(),
+ (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", 10);
+ 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 8b9efb3..569786b 100644
--- a/services/robotests/backup/Android.bp
+++ b/services/robotests/backup/Android.bp
@@ -57,6 +57,8 @@
// Include the testing libraries
libs: [
"mockito-robolectric-prebuilt",
+ "Settings-robo-testutils",
+ "SettingsLib-robo-testutils",
"platform-test-annotations",
"testng",
"truth",
@@ -64,4 +66,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/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/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 113511e..321d945 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -73,6 +73,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/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 9b84190..fad8115 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -80,6 +80,7 @@
"securebox",
"flag-junit",
"ravenwood-junit",
+ "net_flags_lib",
],
libs: [
diff --git a/services/tests/servicestests/src/com/android/server/OWNERS b/services/tests/servicestests/src/com/android/server/OWNERS
index 2d36ff3..d49bc43 100644
--- a/services/tests/servicestests/src/com/android/server/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/OWNERS
@@ -7,3 +7,4 @@
per-file BatteryServiceTest.java = file:platform/hardware/interfaces:/health/OWNERS
per-file GestureLauncherServiceTest.java = file:platform/packages/apps/EmergencyInfo:/OWNERS
per-file PinnerServiceTest.java = file:/apct-tests/perftests/OWNERS
+per-file SecurityStateTest.java = file:/SECURITY_STATE_OWNERS
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 77b1455..26934d8 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -763,8 +763,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/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..5081198 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,25 +32,30 @@
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;
import static org.mockito.Mockito.when;
import android.app.PropertyInvalidatedCache;
+import android.os.IBinder;
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;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.widget.ILockSettingsStateListener;
import com.android.internal.widget.LockPatternUtils;
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 +66,7 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Before
public void setUp() {
@@ -399,6 +407,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 ILockSettingsStateListener listener = mockLockSettingsStateListener();
+ 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 ILockSettingsStateListener listener = mockLockSettingsStateListener();
+ 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 ILockSettingsStateListener listener = mockLockSettingsStateListener();
+
+ 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);
@@ -537,4 +599,12 @@
assertNotEquals(0, mGateKeeperService.getSecureUserId(userId));
}
}
+
+ private ILockSettingsStateListener mockLockSettingsStateListener() {
+ ILockSettingsStateListener listener = mock(ILockSettingsStateListener.Stub.class);
+ IBinder binder = mock(IBinder.class);
+ when(binder.isBinderAlive()).thenReturn(true);
+ when(listener.asBinder()).thenReturn(binder);
+ return listener;
+ }
}
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..4451cae 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -26,12 +26,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,8 +50,13 @@
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.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
@@ -64,6 +71,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;
@@ -146,6 +154,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 +163,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 +182,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;
@@ -243,6 +257,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 +302,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 +320,7 @@
private NetworkPolicyManagerService mService;
private final ArraySet<BroadcastReceiver> mRegisteredReceivers = new ArraySet<>();
+ private BroadcastReceiver mPowerAllowlistReceiver;
/**
* In some of the tests while initializing NetworkPolicyManagerService,
@@ -446,6 +465,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 +502,8 @@
return mUserManager;
case Context.NETWORK_STATS_SERVICE:
return mStatsManager;
+ case Context.POWER_EXEMPTION_SERVICE:
+ return mPowerExemptionManager;
default:
return super.getSystemService(name);
}
@@ -495,6 +517,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);
}
@@ -2066,6 +2091,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 +2144,111 @@
}
@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));
+ }
+
+ @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 +2335,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();
@@ -2529,7 +2678,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 +2685,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/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 1dc5dcf..3a0a6ab 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -35,4 +35,7 @@
"android.hardware.usb-V1.3-java",
"android.hardware.usb-V3-java",
],
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ },
}
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 2ff7413..f37d2d1 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -77,12 +77,13 @@
auto_gen_config: true,
}
-// 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/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/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..9daba6a
--- /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)
+ .getIpSecTransformState(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).getIpSecTransformState(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..6015e931
--- /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 com.android.net.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/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 45dd02c..642a561 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"
@@ -1987,6 +1988,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);
@@ -2283,7 +2299,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;
}
}
@@ -2531,7 +2552,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 7096f5c..6cc42f1 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/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