diff options
777 files changed, 5495 insertions, 2717 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index 451175f62183..fdd050538ecc 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -15,6 +15,7 @@ aconfig_srcjars = [ ":android.content.pm.flags-aconfig-java{.generated_srcjars}", ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}", + ":android.net.vcn.flags-aconfig-java{.generated_srcjars}", ":android.nfc.flags-aconfig-java{.generated_srcjars}", ":android.os.flags-aconfig-java{.generated_srcjars}", ":android.security.flags-aconfig-java{.generated_srcjars}", @@ -120,6 +121,18 @@ aconfig_declarations { srcs: ["core/java/android/nfc/*.aconfig"], } +cc_aconfig_library { + name: "android_nfc_flags_aconfig_c_lib", + vendor_available: true, + aconfig_declarations: "android.nfc.flags-aconfig", + apex_available: [ + "//apex_available:platform", + "com.android.nfcservices", + "nfc_nci.st21nfc.default", + ], + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + java_aconfig_library { name: "android.nfc.flags-aconfig-java", aconfig_declarations: "android.nfc.flags-aconfig", @@ -148,7 +161,7 @@ java_aconfig_library { name: "android.security.flags-aconfig-java-host", aconfig_declarations: "android.security.flags-aconfig", host_supported: true, - test: true, + mode: "test", defaults: ["framework-minus-apex-aconfig-java-defaults"], } @@ -197,3 +210,34 @@ java_aconfig_library { aconfig_declarations: "com.android.net.flags-aconfig", defaults: ["framework-minus-apex-aconfig-java-defaults"], } + +// Media +aconfig_declarations { + name: "android.media.playback.flags-aconfig", + package: "com.android.media.playback.flags", + srcs: ["media/jni/playback_flags.aconfig"], +} + +cc_aconfig_library { + name: "android.media.playback.flags-aconfig-cc", + aconfig_declarations: "android.media.playback.flags-aconfig", +} + +java_aconfig_library { + name: "android.media.playback.flags-aconfig-java", + aconfig_declarations: "android.media.playback.flags-aconfig", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + +// VCN +aconfig_declarations { + name: "android.net.vcn.flags-aconfig", + package: "android.net.vcn", + srcs: ["core/java/android/net/vcn/*.aconfig"], +} + +java_aconfig_library { + name: "android.net.vcn.flags-aconfig-java", + aconfig_declarations: "android.net.vcn.flags-aconfig", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} diff --git a/Android.bp b/Android.bp index 0c0811906b5c..f5c0b6d416b8 100644 --- a/Android.bp +++ b/Android.bp @@ -136,6 +136,9 @@ filegroup { // For the generated R.java and Manifest.java ":framework-res{.aapt.srcjar}", + // Java/AIDL sources to be moved out to CrashRecovery module + ":framework-crashrecovery-sources", + // etc. ":framework-javastream-protos", ":statslog-framework-java-gen", // FrameworkStatsLog.java @@ -396,6 +399,7 @@ java_defaults { "soundtrigger_middleware-aidl-java", "modules-utils-binary-xml", "modules-utils-build", + "modules-utils-fastxmlserializer", "modules-utils-preconditions", "modules-utils-statemachine", "modules-utils-synchronous-result-receiver", @@ -409,13 +413,25 @@ java_defaults { ], } +// Collection of non updatable unbundled jars. The list here should match +// |non_updatable_modules| variable in frameworks/base/api/api.go. +java_library { + name: "framework-non-updatable-unbundled-impl-libs", + static_libs: [ + "framework-location.impl", + "framework-nfc.impl", + ], + sdk_version: "core_platform", + installable: false, +} + // Separated so framework-minus-apex-defaults can be used without the libs dependency java_defaults { name: "framework-minus-apex-with-libs-defaults", defaults: ["framework-minus-apex-defaults"], libs: [ "framework-virtualization.stubs.module_lib", - "framework-location.impl", + "framework-non-updatable-unbundled-impl-libs", ], } @@ -446,7 +462,7 @@ java_library { stem: "framework", apex_available: ["//apex_available:platform"], visibility: [ - "//frameworks/base/location", + "//frameworks/base:__subpackages__", ], compile_dex: false, headers_only: true, @@ -509,8 +525,8 @@ java_library { installable: false, // this lib is a build-only library static_libs: [ "app-compat-annotations", - "framework-location.impl", "framework-minus-apex", + "framework-non-updatable-unbundled-impl-libs", "framework-updatable-stubs-module_libs_api", ], sdk_version: "core_platform", @@ -603,23 +619,11 @@ java_library { ], } -packages_to_document = [ - "android", - "dalvik", - "java", - "javax", - "junit", - "org.apache.http", - "org.json", - "org.w3c.dom", - "org.xml.sax", - "org.xmlpull", -] - filegroup { name: "android-non-updatable-stub-sources", srcs: [ ":framework-mime-sources", // mimemap builds separately but has no separate droidstubs. + ":framework-minus-apex-aconfig-srcjars", ":framework-non-updatable-sources", ":opt-telephony-srcs", ":opt-net-voip-srcs", @@ -629,200 +633,6 @@ filegroup { visibility: ["//frameworks/base/api"], } -// Defaults for all stubs that include the non-updatable framework. These defaults do not include -// module symbols, so will not compile correctly on their own. Users must add module APIs to the -// classpath (or sources) somehow. -stubs_defaults { - name: "android-non-updatable-stubs-defaults", - srcs: [":android-non-updatable-stub-sources"], - sdk_version: "none", - system_modules: "none", - java_version: "1.8", - arg_files: [":frameworks-base-core-AndroidManifest.xml"], - aidl: { - include_dirs: [ - "frameworks/av/aidl", - "frameworks/base/media/aidl", - "frameworks/base/telephony/java", - "frameworks/native/libs/permission/aidl", - "packages/modules/Bluetooth/framework/aidl-export", - "packages/modules/Connectivity/framework/aidl-export", - "packages/modules/Media/apex/aidl/stable", - "hardware/interfaces/biometrics/common/aidl", - "hardware/interfaces/biometrics/fingerprint/aidl", - "hardware/interfaces/graphics/common/aidl", - "hardware/interfaces/keymaster/aidl", - "system/hardware/interfaces/media/aidl", - ], - }, - // These are libs from framework-internal-utils that are required (i.e. being referenced) - // from framework-non-updatable-sources. Add more here when there's a need. - // DO NOT add the entire framework-internal-utils. It might cause unnecessary circular - // dependencies gets bigger. - libs: [ - "android.hardware.cas-V1.2-java", - "android.hardware.health-V1.0-java-constants", - "android.hardware.radio-V1.5-java", - "android.hardware.radio-V1.6-java", - "android.hardware.thermal-V1.0-java-constants", - "android.hardware.thermal-V2.0-java", - "android.hardware.tv.input-V1.0-java-constants", - "android.hardware.usb-V1.0-java-constants", - "android.hardware.usb-V1.1-java-constants", - "android.hardware.usb.gadget-V1.0-java", - "android.hardware.vibrator-V1.3-java", - "framework-protos", - ], - flags: [ - "--api-lint-ignore-prefix android.icu.", - "--api-lint-ignore-prefix java.", - "--api-lint-ignore-prefix junit.", - "--api-lint-ignore-prefix org.", - "--error NoSettingsProvider", - "--error UnhiddenSystemApi", - "--error UnflaggedApi", - "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*", - "--hide BroadcastBehavior", - "--hide CallbackInterface", - "--hide DeprecationMismatch", - "--hide HiddenSuperclass", - "--hide HiddenTypeParameter", - "--hide MissingPermission", - "--hide RequiresPermission", - "--hide SdkConstant", - "--hide Todo", - "--hide UnavailableSymbol", - "--hide-package android.audio.policy.configuration.V7_0", - "--hide-package com.android.server", - "--manifest $(location :frameworks-base-core-AndroidManifest.xml)", - ], - filter_packages: packages_to_document, - high_mem: true, // Lots of sources => high memory use, see b/170701554 - installable: false, - annotations_enabled: true, - previous_api: ":android.api.public.latest", - merge_annotations_dirs: ["metalava-manual"], - defaults_visibility: ["//frameworks/base/api"], - visibility: ["//frameworks/base/api"], -} - -// Defaults with module APIs in the classpath (mostly from prebuilts). -// Suitable for compiling android-non-updatable. -stubs_defaults { - name: "module-classpath-stubs-defaults", - aidl: { - include_dirs: [ - "packages/modules/Bluetooth/framework/aidl-export", - "packages/modules/Connectivity/framework/aidl-export", - "packages/modules/Media/apex/aidl/stable", - ], - }, - libs: [ - "art.module.public.api", - "sdk_module-lib_current_framework-tethering", - "sdk_module-lib_current_framework-connectivity-t", - "sdk_public_current_framework-bluetooth", - // There are a few classes from modules used by the core that - // need to be resolved by metalava. We use a prebuilt stub of the - // full sdk to ensure we can resolve them. If a new class gets added, - // the prebuilts/sdk/current needs to be updated. - "sdk_system_current_android", - // NOTE: The below can be removed once the prebuilt stub contains IKE. - "sdk_system_current_android.net.ipsec.ike", - ], -} - -// Defaults for the java_sdk_libraries of unbundled jars from framework. -// java_sdk_libraries using these defaults should also add themselves to the -// non_updatable_modules list in frameworks/base/api/api.go -java_defaults { - name: "framework-non-updatable-unbundled-defaults", - defaults: ["framework-non-updatable-lint-defaults"], - - sdk_version: "core_platform", - - // Api scope settings - public: { - enabled: true, - sdk_version: "module_current", - libs: ["android_module_lib_stubs_current"], - }, - system: { - enabled: true, - sdk_version: "module_current", - libs: ["android_module_lib_stubs_current"], - }, - module_lib: { - enabled: true, - sdk_version: "module_current", - libs: ["android_module_lib_stubs_current"], - }, - test: { - enabled: true, - sdk_version: "test_frameworks_core_current", - libs: ["android_test_frameworks_core_stubs_current"], - }, - - stub_only_libs: [ - "framework-protos", - ], - impl_only_libs: [ - "framework-minus-apex-headers", // full access to framework-minus-apex including hidden API - "framework-annotations-lib", - ], - visibility: ["//visibility:public"], - stubs_library_visibility: ["//visibility:public"], - stubs_source_visibility: ["//visibility:private"], - impl_library_visibility: [ - ":__pkg__", - "//frameworks/base", - "//frameworks/base/api", // For framework-all - ], - defaults_visibility: [ - "//frameworks/base/location", - ], - plugins: [ - "error_prone_android_framework", - ], - errorprone: { - javacflags: [ - "-Xep:AndroidFrameworkCompatChange:ERROR", - "-Xep:AndroidFrameworkUid:ERROR", - ], - }, - - // Include manual annotations in API txt files - merge_annotations_dirs: ["metalava-manual"], - - // Use the source of annotations that affect metalava doc generation, since - // the relevant generation instructions are themselves in javadoc, which is - // not present in class files. - api_srcs: [":framework-metalava-annotations"], - - // Framework modules are not generally shared libraries, i.e. they are not - // intended, and must not be allowed, to be used in a <uses-library> manifest - // entry. - shared_library: false, - - // Prevent dependencies that do not specify an sdk_version from accessing the - // implementation library by default and force them to use stubs instead. - default_to_stubs: true, - - // Subdirectory for the artifacts that are copied to the dist directory - dist_group: "android", - - droiddoc_options: [ - "--error UnhiddenSystemApi " + - "--hide CallbackInterface " + - "--hide HiddenTypedefConstant " + - "--hide RequiresPermission " + - "--enhance-documentation " + - "--hide-package com.android.server ", - ], - - annotations_enabled: true, -} - build = [ "AconfigFlags.bp", "ProtoLibraries.bp", diff --git a/BAL_OWNERS b/BAL_OWNERS new file mode 100644 index 000000000000..d56a1d4634df --- /dev/null +++ b/BAL_OWNERS @@ -0,0 +1,5 @@ +brufino@google.com +achim@google.com +topjohnwu@google.com +lus@google.com + diff --git a/INPUT_OWNERS b/INPUT_OWNERS index e02ba770cdf8..44b2f3805495 100644 --- a/INPUT_OWNERS +++ b/INPUT_OWNERS @@ -5,3 +5,5 @@ michaelwr@google.com prabirmsp@google.com svv@google.com vdevmurari@google.com + +per-file Virtual*=file:/services/companion/java/com/android/server/companion/virtual/OWNERS @@ -37,3 +37,5 @@ per-file SQLITE_OWNERS = file:/SQLITE_OWNERS per-file *ravenwood* = file:ravenwood/OWNERS per-file *Ravenwood* = file:ravenwood/OWNERS + +per-file PERFORMANCE_OWNERS = file:/PERFORMANCE_OWNERS diff --git a/PERFORMANCE_OWNERS b/PERFORMANCE_OWNERS index 9452ea35f3e4..48a020130445 100644 --- a/PERFORMANCE_OWNERS +++ b/PERFORMANCE_OWNERS @@ -3,3 +3,6 @@ edgararriaga@google.com dualli@google.com carmenjackson@google.com philipcuadra@google.com +shayba@google.com +jdduke@google.com +shombert@google.com diff --git a/THERMAL_OWNERS b/THERMAL_OWNERS new file mode 100644 index 000000000000..b95b7e84191c --- /dev/null +++ b/THERMAL_OWNERS @@ -0,0 +1,3 @@ +lpy@google.com +wvw@google.com +xwxw@google.com diff --git a/apct-tests/perftests/OWNERS b/apct-tests/perftests/OWNERS index 4c57e640c141..8ff3f9bc6620 100644 --- a/apct-tests/perftests/OWNERS +++ b/apct-tests/perftests/OWNERS @@ -1,12 +1,11 @@ -balejs@google.com carmenjackson@google.com -cfijalkovich@google.com dualli@google.com edgararriaga@google.com -jpakaravoor@google.com +jdduke@google.com jreck@google.com #{LAST_RESORT_SUGGESTION} kevinjeon@google.com philipcuadra@google.com +shayba@google.com shombert@google.com timmurray@google.com wessam@google.com diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp index 9366ff2d81a9..e1b3241e051e 100644 --- a/apct-tests/perftests/core/Android.bp +++ b/apct-tests/perftests/core/Android.bp @@ -66,6 +66,7 @@ android_test { errorprone: { javacflags: [ "-Xep:ReturnValueIgnored:WARN", + "-Xep:UnnecessaryStringBuilder:OFF", ], }, } diff --git a/tests/SilkFX/assets/gainmaps/fountain_night.jpg b/apct-tests/perftests/core/res/drawable-nodpi/fountain_night.jpg Binary files differindex d8b2d759e4c0..d8b2d759e4c0 100644 --- a/tests/SilkFX/assets/gainmaps/fountain_night.jpg +++ b/apct-tests/perftests/core/res/drawable-nodpi/fountain_night.jpg diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java index f84a0d037ca5..e5a06c9bd146 100644 --- a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java +++ b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java @@ -16,20 +16,29 @@ package android.graphics.perftests; +import static org.junit.Assert.assertTrue; + +import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Color; +import android.graphics.ImageDecoder; import android.graphics.Paint; import android.graphics.RecordingCanvas; import android.graphics.RenderNode; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; +import androidx.test.InstrumentationRegistry; import androidx.test.filters.LargeTest; +import com.android.perftests.core.R; + import org.junit.Rule; import org.junit.Test; +import java.io.IOException; + @LargeTest public class CanvasPerfTest { @Rule @@ -93,4 +102,38 @@ public class CanvasPerfTest { node.end(canvas); } } + + @Test + public void testCreateScaledBitmap() throws IOException { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final Context context = InstrumentationRegistry.getContext(); + Bitmap source = ImageDecoder.decodeBitmap( + ImageDecoder.createSource(context.getResources(), R.drawable.fountain_night), + (decoder, info, source1) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); + }); + source.setGainmap(null); + + while (state.keepRunning()) { + Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true) + .recycle(); + } + } + + @Test + public void testCreateScaledBitmapWithGainmap() throws IOException { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final Context context = InstrumentationRegistry.getContext(); + Bitmap source = ImageDecoder.decodeBitmap( + ImageDecoder.createSource(context.getResources(), R.drawable.fountain_night), + (decoder, info, source1) -> { + decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE); + }); + assertTrue(source.hasGainmap()); + + while (state.keepRunning()) { + Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true) + .recycle(); + } + } } diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp index a4a0b4b29200..83ad736023b0 100644 --- a/apex/jobscheduler/service/Android.bp +++ b/apex/jobscheduler/service/Android.bp @@ -26,6 +26,10 @@ java_library { "unsupportedappusage", ], + static_libs: [ + "modules-utils-fastxmlserializer", + ], + // Rename classes shared with the framework jarjar_rules: "jarjar-rules.txt", diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java index 4d646de2e529..10764651cdfb 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java @@ -21,7 +21,7 @@ import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; import static android.app.AlarmManager.RTC; import static android.app.AlarmManager.RTC_WAKEUP; -import static com.android.server.alarm.AlarmManagerService.clampPositive; +import static com.android.server.alarm.AlarmManagerService.addClampPositive; import android.app.AlarmManager; import android.app.IAlarmListener; @@ -146,7 +146,7 @@ class Alarm { mPolicyWhenElapsed[REQUESTER_POLICY_INDEX] = requestedWhenElapsed; mWhenElapsed = requestedWhenElapsed; this.windowLength = windowLength; - mMaxWhenElapsed = clampPositive(requestedWhenElapsed + windowLength); + mMaxWhenElapsed = addClampPositive(requestedWhenElapsed, windowLength); repeatInterval = interval; operation = op; listener = rec; @@ -241,8 +241,8 @@ class Alarm { final long oldMaxWhenElapsed = mMaxWhenElapsed; // windowLength should always be >= 0 here. - final long maxRequestedElapsed = clampPositive( - mPolicyWhenElapsed[REQUESTER_POLICY_INDEX] + windowLength); + final long maxRequestedElapsed = addClampPositive( + mPolicyWhenElapsed[REQUESTER_POLICY_INDEX], windowLength); mMaxWhenElapsed = Math.max(maxRequestedElapsed, mWhenElapsed); return (oldWhenElapsed != mWhenElapsed) || (oldMaxWhenElapsed != mMaxWhenElapsed); diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index b96354c396a7..8cc31342ddda 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -1498,15 +1498,15 @@ public class AlarmManagerService extends SystemService { if (futurity < MIN_FUZZABLE_INTERVAL) { futurity = 0; } - long maxElapsed = triggerAtTime + (long) (0.75 * futurity); + long maxElapsed = addClampPositive(triggerAtTime, (long) (0.75 * futurity)); // For non-repeating alarms, window is capped at a maximum of one hour from the requested // delivery time. This allows for inexact-while-idle alarms to be slightly more reliable. // In practice, the delivery window should generally be much smaller than that // when the device is not idling. if (interval == 0) { - maxElapsed = Math.min(maxElapsed, triggerAtTime + INTERVAL_HOUR); + maxElapsed = Math.min(maxElapsed, addClampPositive(triggerAtTime, INTERVAL_HOUR)); } - return clampPositive(maxElapsed); + return maxElapsed; } // The RTC clock has moved arbitrarily, so we need to recalculate all the RTC alarm deliveries. @@ -1593,6 +1593,18 @@ public class AlarmManagerService extends SystemService { return (val >= 0) ? val : Long.MAX_VALUE; } + static long addClampPositive(long val1, long val2) { + long val = val1 + val2; + if (val >= 0) { + return val; + } else if (val1 >= 0 && val2 >= 0) { + /* Both are +ve, so overflow happened. */ + return Long.MAX_VALUE; + } else { + return 0; + } + } + /** * Sends alarms that were blocked due to user applied background restrictions - either because * the user lifted those or the uid came to foreground. diff --git a/api/Android.bp b/api/Android.bp index 6986ac09f89e..68babc3660d9 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -83,14 +83,15 @@ combined_apis { "framework-configinfrastructure", "framework-connectivity", "framework-connectivity-t", - "framework-crashrecovery", "framework-devicelock", "framework-graphics", "framework-healthfitness", "framework-location", "framework-media", "framework-mediaprovider", + "framework-nfc", "framework-ondevicepersonalization", + "framework-pdf", "framework-permission", "framework-permission-s", "framework-scheduling", @@ -106,7 +107,6 @@ combined_apis { system_server_classpath: [ "service-art", "service-configinfrastructure", - "service-crashrecovery", "service-healthfitness", "service-media-s", "service-permission", @@ -262,7 +262,205 @@ java_genrule { cmd: "cat $(in) | md5sum | cut -d' ' -f1 > $(out)", } +packages_to_document = [ + "android", + "dalvik", + "java", + "javax", + "junit", + "org.apache.http", + "org.json", + "org.w3c.dom", + "org.xml.sax", + "org.xmlpull", +] + +// Defaults for all stubs that include the non-updatable framework. These defaults do not include +// module symbols, so will not compile correctly on their own. Users must add module APIs to the +// classpath (or sources) somehow. +stubs_defaults { + name: "android-non-updatable-stubs-defaults", + srcs: [":android-non-updatable-stub-sources"], + sdk_version: "none", + system_modules: "none", + java_version: "1.8", + arg_files: [":frameworks-base-core-AndroidManifest.xml"], + aidl: { + include_dirs: [ + "frameworks/av/aidl", + "frameworks/base/media/aidl", + "frameworks/base/telephony/java", + "frameworks/native/libs/permission/aidl", + "packages/modules/Bluetooth/framework/aidl-export", + "packages/modules/Connectivity/framework/aidl-export", + "packages/modules/Media/apex/aidl/stable", + "hardware/interfaces/biometrics/common/aidl", + "hardware/interfaces/biometrics/fingerprint/aidl", + "hardware/interfaces/graphics/common/aidl", + "hardware/interfaces/keymaster/aidl", + "system/hardware/interfaces/media/aidl", + ], + }, + // These are libs from framework-internal-utils that are required (i.e. being referenced) + // from framework-non-updatable-sources. Add more here when there's a need. + // DO NOT add the entire framework-internal-utils. It might cause unnecessary circular + // dependencies gets bigger. + libs: [ + "android.hardware.cas-V1.2-java", + "android.hardware.health-V1.0-java-constants", + "android.hardware.radio-V1.5-java", + "android.hardware.radio-V1.6-java", + "android.hardware.thermal-V1.0-java-constants", + "android.hardware.thermal-V2.0-java", + "android.hardware.tv.input-V1.0-java-constants", + "android.hardware.usb-V1.0-java-constants", + "android.hardware.usb-V1.1-java-constants", + "android.hardware.usb.gadget-V1.0-java", + "android.hardware.vibrator-V1.3-java", + "framework-protos", + ], + flags: [ + "--api-lint-ignore-prefix android.icu.", + "--api-lint-ignore-prefix java.", + "--api-lint-ignore-prefix junit.", + "--api-lint-ignore-prefix org.", + "--error NoSettingsProvider", + "--error UnhiddenSystemApi", + "--error UnflaggedApi", + "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*", + "--hide BroadcastBehavior", + "--hide CallbackInterface", + "--hide DeprecationMismatch", + "--hide HiddenSuperclass", + "--hide MissingPermission", + "--hide RequiresPermission", + "--hide SdkConstant", + "--hide Todo", + "--hide-package android.audio.policy.configuration.V7_0", + "--hide-package com.android.server", + "--manifest $(location :frameworks-base-core-AndroidManifest.xml)", + ], + filter_packages: packages_to_document, + high_mem: true, // Lots of sources => high memory use, see b/170701554 + installable: false, + annotations_enabled: true, + previous_api: ":android.api.public.latest", + merge_annotations_dirs: ["metalava-manual"], + defaults_visibility: ["//frameworks/base/api"], + visibility: ["//frameworks/base/api"], +} + +// We resolve dependencies on APIs in modules by depending on a prebuilt of the whole +// platform (sdk_system_current_android). That prebuilt does not include module-lib APIs, +// so use the prebuilt module-lib stubs for modules that export module-lib stubs that the +// non-updatable part depends on. +non_updatable_api_deps_on_modules = [ + "sdk_module-lib_current_framework-tethering", + "sdk_module-lib_current_framework-connectivity-t", + "sdk_system_current_android", +] + +// Defaults with module APIs in the classpath (mostly from prebuilts). +// Suitable for compiling android-non-updatable. +stubs_defaults { + name: "module-classpath-stubs-defaults", + aidl: { + include_dirs: [ + "packages/modules/Bluetooth/framework/aidl-export", + "packages/modules/Connectivity/framework/aidl-export", + "packages/modules/Media/apex/aidl/stable", + ], + }, + libs: non_updatable_api_deps_on_modules, +} + +// Defaults for the java_sdk_libraries of unbundled jars from framework. +// java_sdk_libraries using these defaults should also add themselves to the +// non_updatable_modules list in frameworks/base/api/api.go +java_defaults { + name: "framework-non-updatable-unbundled-defaults", + defaults: [ + "framework-non-updatable-lint-defaults", + "non-updatable-framework-module-defaults", + ], + public: { + libs: ["android_module_lib_stubs_current"], + }, + system: { + libs: ["android_module_lib_stubs_current"], + }, + module_lib: { + libs: ["android_module_lib_stubs_current"], + }, + test: { + libs: ["android_test_frameworks_core_stubs_current"], + }, + sdk_version: "core_platform", + stub_only_libs: ["framework-protos"], + impl_only_libs: ["framework-minus-apex-headers"], // the framework, including hidden API + impl_library_visibility: ["//frameworks/base"], + defaults_visibility: [ + "//frameworks/base/location", + "//frameworks/base/nfc", + ], + plugins: ["error_prone_android_framework"], + errorprone: { + javacflags: [ + "-Xep:AndroidFrameworkCompatChange:ERROR", + "-Xep:AndroidFrameworkUid:ERROR", + ], + }, + // Include manual annotations in API txt files + merge_annotations_dirs: ["metalava-manual"], +} + build = [ "ApiDocs.bp", "StubLibraries.bp", ] + +genrule_defaults { + name: "flag-api-mapping-generation-defaults", + cmd: "$(location extract-flagged-apis) $(in) $(out)", + tools: ["extract-flagged-apis"], +} + +genrule { + name: "flag-api-mapping-PublicApi", + defaults: ["flag-api-mapping-generation-defaults"], + srcs: [":frameworks-base-api-current.txt"], + out: ["flag_api_map.textproto"], + dist: { + targets: ["droid"], + }, +} + +genrule { + name: "flag-api-mapping-SystemApi", + defaults: ["flag-api-mapping-generation-defaults"], + srcs: [":frameworks-base-api-system-current.txt"], + out: ["system_flag_api_map.textproto"], + dist: { + targets: ["droid"], + }, +} + +genrule { + name: "flag-api-mapping-ModuleLibApi", + defaults: ["flag-api-mapping-generation-defaults"], + srcs: [":frameworks-base-api-module-lib-current.txt"], + out: ["module_lib_flag_api_map.textproto"], + dist: { + targets: ["droid"], + }, +} + +genrule { + name: "flag-api-mapping-SystemServerApi", + defaults: ["flag-api-mapping-generation-defaults"], + srcs: [":frameworks-base-api-system-server-current.txt"], + out: ["system_server_flag_api_map.textproto"], + dist: { + targets: ["droid"], + }, +} diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index d566552333cb..28b2d4b5e3ee 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -29,9 +29,6 @@ droidstubs { name: "api-stubs-docs-non-updatable", - srcs: [ - ":framework-minus-apex-aconfig-srcjars", - ], defaults: [ "android-non-updatable-stubs-defaults", "module-classpath-stubs-defaults", @@ -91,9 +88,6 @@ module_libs = [ droidstubs { name: "system-api-stubs-docs-non-updatable", - srcs: [ - ":framework-minus-apex-aconfig-srcjars", - ], defaults: [ "android-non-updatable-stubs-defaults", "module-classpath-stubs-defaults", @@ -134,9 +128,6 @@ droidstubs { droidstubs { name: "test-api-stubs-docs-non-updatable", - srcs: [ - ":framework-minus-apex-aconfig-srcjars", - ], defaults: [ "android-non-updatable-stubs-defaults", "module-classpath-stubs-defaults", @@ -184,9 +175,6 @@ droidstubs { droidstubs { name: "module-lib-api-stubs-docs-non-updatable", - srcs: [ - ":framework-minus-apex-aconfig-srcjars", - ], defaults: [ "android-non-updatable-stubs-defaults", "module-classpath-stubs-defaults", @@ -363,17 +351,7 @@ java_library { "android-non-updatable_from_source_defaults", ], srcs: [":module-lib-api-stubs-docs-non-updatable"], - libs: [ - // We cannot depend on all-modules-module-lib-stubs, because the module-lib stubs - // depend on this stub. We resolve dependencies on APIs in modules by depending - // on a prebuilt of the whole platform (sdk_system_current_android). - // That prebuilt does not include module-lib APIs, so use the prebuilt module-lib - // stubs for modules that export module-lib stubs that the non-updatable part - // depends on. - "sdk_module-lib_current_framework-tethering", - "sdk_module-lib_current_framework-connectivity-t", - "sdk_system_current_android", - ], + libs: non_updatable_api_deps_on_modules, dist: { dir: "apistubs/android/module-lib", }, @@ -657,6 +635,7 @@ java_defaults { api_contributions: [ "framework-virtualization.stubs.source.test.api.contribution", "framework-location.stubs.source.test.api.contribution", + "framework-nfc.stubs.source.test.api.contribution", ], } diff --git a/api/api.go b/api/api.go index 8df6dab715ef..71b1e10d2f47 100644 --- a/api/api.go +++ b/api/api.go @@ -32,6 +32,7 @@ const conscrypt = "conscrypt.module.public.api" const i18n = "i18n.module.public.api" const virtualization = "framework-virtualization" const location = "framework-location" +const nfc = "framework-nfc" var core_libraries_modules = []string{art, conscrypt, i18n} @@ -43,7 +44,7 @@ var core_libraries_modules = []string{art, conscrypt, i18n} // APIs. // In addition, the modules in this list are allowed to contribute to test APIs // stubs. -var non_updatable_modules = []string{virtualization, location} +var non_updatable_modules = []string{virtualization, location, nfc} // The intention behind this soong plugin is to generate a number of "merged" // API-related modules that would otherwise require a large amount of very diff --git a/api/coverage/tools/Android.bp b/api/coverage/tools/Android.bp new file mode 100644 index 000000000000..3e169120dc48 --- /dev/null +++ b/api/coverage/tools/Android.bp @@ -0,0 +1,32 @@ +// 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. + +java_binary_host { + name: "extract-flagged-apis", + srcs: ["ExtractFlaggedApis.kt"], + main_class: "android.platform.coverage.ExtractFlaggedApisKt", + static_libs: [ + "metalava-signature-reader", + "extract_flagged_apis_proto", + ], +} + +java_library_host { + name: "extract_flagged_apis_proto", + srcs: ["extract_flagged_apis.proto"], + static_libs: ["libprotobuf-java-full"], + proto: { + type: "full", + }, +} diff --git a/api/coverage/tools/ExtractFlaggedApis.kt b/api/coverage/tools/ExtractFlaggedApis.kt new file mode 100644 index 000000000000..9ffb70496c59 --- /dev/null +++ b/api/coverage/tools/ExtractFlaggedApis.kt @@ -0,0 +1,58 @@ +/* + * 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.platform.coverage + +import com.android.tools.metalava.model.text.ApiFile +import java.io.File +import java.io.FileWriter + +/** Usage: extract-flagged-apis <api text file> <output .pb file> */ +fun main(args: Array<String>) { + var cb = ApiFile.parseApi(listOf(File(args[0]))) + val flagToApi = mutableMapOf<String, MutableList<String>>() + cb.getPackages() + .allClasses() + .filter { it.methods().size > 0 } + .forEach { + for (method in it.methods()) { + val flagValue = + method.modifiers + .findAnnotation("android.annotation.FlaggedApi") + ?.findAttribute("value") + ?.value + ?.value() + if (flagValue != null && flagValue is String) { + val methodQualifiedName = "${it.qualifiedName()}.${method.name()}" + if (flagToApi.containsKey(flagValue)) { + flagToApi.get(flagValue)?.add(methodQualifiedName) + } else { + flagToApi.put(flagValue, mutableListOf(methodQualifiedName)) + } + } + } + } + var builder = FlagApiMap.newBuilder() + for (flag in flagToApi.keys) { + var flaggedApis = FlaggedApis.newBuilder() + for (method in flagToApi.get(flag).orEmpty()) { + flaggedApis.addFlaggedApi(FlaggedApi.newBuilder().setQualifiedName(method)) + } + builder.putFlagToApi(flag, flaggedApis.build()) + } + val flagApiMap = builder.build() + FileWriter(args[1]).use { it.write(flagApiMap.toString()) } +} diff --git a/services/core/java/com/android/server/BrickReceiver.java b/api/coverage/tools/extract_flagged_apis.proto index cff3805b68d2..a858108a27b2 100644 --- a/services/core/java/com/android/server/BrickReceiver.java +++ b/api/coverage/tools/extract_flagged_apis.proto @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * 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. @@ -14,18 +14,21 @@ * limitations under the License. */ -package com.android.server; +syntax = "proto3"; -import android.content.Context; -import android.content.Intent; -import android.content.BroadcastReceiver; -import android.os.SystemService; -import android.util.Slog; +package android.platform.coverage; -public class BrickReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Slog.w("BrickReceiver", "!!! BRICKING DEVICE !!!"); - SystemService.start("brick"); - } +option java_multiple_files = true; + +message FlagApiMap { + map<string, FlaggedApis> flag_to_api = 1; +} + +message FlaggedApis { + repeated FlaggedApi flagged_api = 1; } + +message FlaggedApi { + string qualified_name = 1; +} + diff --git a/api/gen_combined_removed_dex.sh b/api/gen_combined_removed_dex.sh index 71f366a6aae2..e0153f7c1091 100755 --- a/api/gen_combined_removed_dex.sh +++ b/api/gen_combined_removed_dex.sh @@ -6,6 +6,6 @@ shift 2 # Convert each removed.txt to the "dex format" equivalent, and print all output. for f in "$@"; do - "$metalava_path" "$f" --dex-api "${tmp_dir}/tmp" + "$metalava_path" signature-to-dex "$f" "${tmp_dir}/tmp" cat "${tmp_dir}/tmp" done diff --git a/boot/Android.bp b/boot/Android.bp index b33fab6e1a9f..8a3d35e2d0eb 100644 --- a/boot/Android.bp +++ b/boot/Android.bp @@ -84,10 +84,6 @@ custom_platform_bootclasspath { module: "com.android.conscrypt-bootclasspath-fragment", }, { - apex: "com.android.crashrecovery", - module: "com.android.crashrecovery-bootclasspath-fragment", - }, - { apex: "com.android.devicelock", module: "com.android.devicelock-bootclasspath-fragment", }, diff --git a/core/api/current.txt b/core/api/current.txt index fd4da0da5b54..f0c01eea9307 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -4456,6 +4456,7 @@ package android.app { method public boolean onPreparePanel(int, @Nullable android.view.View, @NonNull android.view.Menu); method public void onProvideAssistContent(android.app.assist.AssistContent); method public void onProvideAssistData(android.os.Bundle); + method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu, int); method public android.net.Uri onProvideReferrer(); method public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[]); method @CallSuper protected void onRestart(); @@ -13770,6 +13771,7 @@ package android.database { method public String getColumnName(int); method public android.os.Bundle getExtras(); method public android.net.Uri getNotificationUri(); + method public java.util.List<android.net.Uri> getNotificationUris(); method public final int getPosition(); method public int getType(int); method @Deprecated protected Object getUpdatedField(int); @@ -13795,6 +13797,7 @@ package android.database { method public android.os.Bundle respond(android.os.Bundle); method public void setExtras(android.os.Bundle); method public void setNotificationUri(android.content.ContentResolver, android.net.Uri); + method public void setNotificationUris(@NonNull android.content.ContentResolver, @NonNull java.util.List<android.net.Uri>); method public void unregisterContentObserver(android.database.ContentObserver); method public void unregisterDataSetObserver(android.database.DataSetObserver); field @Deprecated protected boolean mClosed; @@ -13926,6 +13929,7 @@ package android.database { method public boolean hasNext(); method public java.util.Iterator<android.database.CursorJoiner.Result> iterator(); method public android.database.CursorJoiner.Result next(); + method public void remove(); } public enum CursorJoiner.Result { @@ -13993,6 +13997,7 @@ package android.database { method public int getInt(int); method public long getLong(int); method public android.net.Uri getNotificationUri(); + method public java.util.List<android.net.Uri> getNotificationUris(); method public int getPosition(); method public short getShort(int); method public String getString(int); @@ -14017,6 +14022,7 @@ package android.database { method public android.os.Bundle respond(android.os.Bundle); method public void setExtras(android.os.Bundle); method public void setNotificationUri(android.content.ContentResolver, android.net.Uri); + method public void setNotificationUris(android.content.ContentResolver, java.util.List<android.net.Uri>); method public void unregisterContentObserver(android.database.ContentObserver); method public void unregisterDataSetObserver(android.database.DataSetObserver); } @@ -18291,11 +18297,13 @@ package android.hardware.biometrics { public class BiometricManager { method @Deprecated @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public int canAuthenticate(); method @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public int canAuthenticate(int); + method @FlaggedApi("android.hardware.biometrics.last_authentication_time") @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public long getLastAuthenticationTime(int); method @NonNull @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public android.hardware.biometrics.BiometricManager.Strings getStrings(int); field public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE = 1; // 0x1 field public static final int BIOMETRIC_ERROR_NONE_ENROLLED = 11; // 0xb field public static final int BIOMETRIC_ERROR_NO_HARDWARE = 12; // 0xc field public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15; // 0xf + field @FlaggedApi("android.hardware.biometrics.last_authentication_time") public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL field public static final int BIOMETRIC_SUCCESS = 0; // 0x0 } @@ -18341,6 +18349,7 @@ package android.hardware.biometrics { field public static final int BIOMETRIC_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 field public static final int BIOMETRIC_ERROR_USER_CANCELED = 10; // 0xa field public static final int BIOMETRIC_ERROR_VENDOR = 8; // 0x8 + field @FlaggedApi("android.hardware.biometrics.last_authentication_time") public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL } public abstract static class BiometricPrompt.AuthenticationCallback { @@ -22641,6 +22650,9 @@ package android.media { ctor public MediaCodec.CryptoException(int, @Nullable String); method @Nullable public android.media.MediaCodec.CryptoInfo getCryptoInfo(); method public int getErrorCode(); + method public int getErrorContext(); + method public int getOemError(); + method public int getVendorError(); field @Deprecated public static final int ERROR_FRAME_TOO_LARGE = 8; // 0x8 field @Deprecated public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4 field @Deprecated public static final int ERROR_INSUFFICIENT_SECURITY = 7; // 0x7 @@ -23153,6 +23165,9 @@ package android.media { public final class MediaCryptoException extends java.lang.Exception implements android.media.MediaDrmThrowable { ctor public MediaCryptoException(@Nullable String); + method public int getErrorContext(); + method public int getOemError(); + method public int getVendorError(); } public abstract class MediaDataSource implements java.io.Closeable { @@ -23377,6 +23392,9 @@ package android.media { public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException implements android.media.MediaDrmThrowable { method @NonNull public String getDiagnosticInfo(); method public int getErrorCode(); + method public int getErrorContext(); + method public int getOemError(); + method public int getVendorError(); method public boolean isTransient(); } @@ -23450,6 +23468,9 @@ package android.media { public static final class MediaDrm.SessionException extends java.lang.RuntimeException implements android.media.MediaDrmThrowable { ctor public MediaDrm.SessionException(int, @Nullable String); method @Deprecated public int getErrorCode(); + method public int getErrorContext(); + method public int getOemError(); + method public int getVendorError(); method public boolean isTransient(); field @Deprecated public static final int ERROR_RESOURCE_CONTENTION = 1; // 0x1 field @Deprecated public static final int ERROR_UNKNOWN = 0; // 0x0 @@ -23457,6 +23478,9 @@ package android.media { public class MediaDrmException extends java.lang.Exception implements android.media.MediaDrmThrowable { ctor public MediaDrmException(String); + method public int getErrorContext(); + method public int getOemError(); + method public int getVendorError(); } public class MediaDrmResetException extends java.lang.IllegalStateException implements android.media.MediaDrmThrowable { @@ -28951,6 +28975,7 @@ package android.net.vcn { method @NonNull public long[] getRetryIntervalsMillis(); method @NonNull public java.util.List<android.net.vcn.VcnUnderlyingNetworkTemplate> getVcnUnderlyingNetworkPriorities(); method public boolean hasGatewayOption(int); + method @FlaggedApi("android.net.vcn.safe_mode_config") public boolean isSafeModeEnabled(); field public static final int VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY = 0; // 0x0 } @@ -28964,6 +28989,7 @@ package android.net.vcn { method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMaxMtu(@IntRange(from=0x500) int); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMinUdpPort4500NatTimeoutSeconds(@IntRange(from=0x78) int); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setRetryIntervalsMillis(@NonNull long[]); + method @FlaggedApi("android.net.vcn.safe_mode_config") @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setSafeModeEnabled(boolean); method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setVcnUnderlyingNetworkPriorities(@NonNull java.util.List<android.net.vcn.VcnUnderlyingNetworkTemplate>); } @@ -29079,14 +29105,17 @@ package android.nfc { } public final class NfcAdapter { + method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean allowTransaction(); method public void disableForegroundDispatch(android.app.Activity); method public void disableReaderMode(android.app.Activity); + method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean disallowTransaction(); method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]); method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle); method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context); method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo(); method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler); method public boolean isEnabled(); + method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean isObserveModeSupported(); method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionEnabled(); method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported(); method public boolean isSecureNfcEnabled(); @@ -29194,6 +29223,7 @@ package android.nfc.cardemulation { method public boolean removeAidsForService(android.content.ComponentName, String); method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String); method public boolean setPreferredService(android.app.Activity, android.content.ComponentName); + method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setServiceObserveModeDefault(@NonNull android.content.ComponentName, boolean); method public boolean supportsAidPrefixRegistration(); method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean unsetOffHostForService(@NonNull android.content.ComponentName); method public boolean unsetPreferredService(android.app.Activity); @@ -29213,9 +29243,20 @@ package android.nfc.cardemulation { method public final android.os.IBinder onBind(android.content.Intent); method public abstract void onDeactivated(int); method public abstract byte[] processCommandApdu(byte[], android.os.Bundle); + method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void processPollingFrames(@NonNull java.util.List<android.os.Bundle>); method public final void sendResponseApdu(byte[]); field public static final int DEACTIVATION_DESELECTED = 1; // 0x1 field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0 + field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_DATA_KEY = "android.nfc.cardemulation.DATA"; + field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_GAIN_KEY = "android.nfc.cardemulation.GAIN"; + field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_TIMESTAMP_KEY = "android.nfc.cardemulation.TIMESTAMP"; + field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_A = 65; // 0x0041 'A' + field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_B = 66; // 0x0042 'B' + field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_F = 70; // 0x0046 'F' + field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_TYPE_KEY = "android.nfc.cardemulation.TYPE"; + field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_OFF = 88; // 0x0058 'X' + field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_ON = 79; // 0x004f 'O' + field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_UNKNOWN = 85; // 0x0055 'U' field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE"; field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service"; } @@ -32322,6 +32363,7 @@ package android.opengl { method public void surfaceCreated(android.view.SurfaceHolder); method public void surfaceDestroyed(android.view.SurfaceHolder); method @Deprecated public void surfaceRedrawNeeded(android.view.SurfaceHolder); + method public void surfaceRedrawNeededAsync(android.view.SurfaceHolder, Runnable); field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1 field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2 field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1 @@ -32662,7 +32704,7 @@ package android.os { field public static final int S_V2 = 32; // 0x20 field public static final int TIRAMISU = 33; // 0x21 field public static final int UPSIDE_DOWN_CAKE = 34; // 0x22 - field public static final int VANILLA_ICE_CREAM = 10000; // 0x2710 + field @FlaggedApi("android.os.android_os_build_vanilla_ice_cream") public static final int VANILLA_ICE_CREAM = 10000; // 0x2710 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -33194,7 +33236,7 @@ package android.os { method public static android.os.Message obtain(android.os.Handler, int, Object); method public static android.os.Message obtain(android.os.Handler, int, int, int); method public static android.os.Message obtain(android.os.Handler, int, int, int, Object); - method public android.os.Bundle peekData(); + method @Nullable public android.os.Bundle peekData(); method public void recycle(); method public void sendToTarget(); method public void setAsynchronous(boolean); @@ -39536,7 +39578,7 @@ package android.security.keystore { method @Nullable public java.util.Date getKeyValidityStart(); method @NonNull public String getKeystoreAlias(); method public int getMaxUsageCount(); - method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests(); + method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests(); method public int getPurposes(); method @NonNull public String[] getSignaturePaddings(); method public int getUserAuthenticationType(); @@ -39544,7 +39586,7 @@ package android.security.keystore { method public boolean isDevicePropertiesAttestationIncluded(); method @NonNull public boolean isDigestsSpecified(); method public boolean isInvalidatedByBiometricEnrollment(); - method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified(); + method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified(); method public boolean isRandomizedEncryptionRequired(); method public boolean isStrongBoxBacked(); method public boolean isUnlockedDeviceRequired(); @@ -39576,7 +39618,7 @@ package android.security.keystore { method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForOriginationEnd(java.util.Date); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityStart(java.util.Date); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMaxUsageCount(int); - method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@Nullable java.lang.String...); + method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...); method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean); @@ -39681,14 +39723,14 @@ package android.security.keystore { method @Nullable public java.util.Date getKeyValidityForOriginationEnd(); method @Nullable public java.util.Date getKeyValidityStart(); method public int getMaxUsageCount(); - method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests(); + method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests(); method public int getPurposes(); method @NonNull public String[] getSignaturePaddings(); method public int getUserAuthenticationType(); method public int getUserAuthenticationValidityDurationSeconds(); method public boolean isDigestsSpecified(); method public boolean isInvalidatedByBiometricEnrollment(); - method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified(); + method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified(); method public boolean isRandomizedEncryptionRequired(); method public boolean isUnlockedDeviceRequired(); method public boolean isUserAuthenticationRequired(); @@ -39710,7 +39752,7 @@ package android.security.keystore { method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date); method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date); method @NonNull public android.security.keystore.KeyProtection.Builder setMaxUsageCount(int); - method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...); + method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...); method @NonNull public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean); method @NonNull public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...); method @NonNull public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean); @@ -47781,6 +47823,7 @@ package android.text { method public boolean hasNext(); method public java.util.Iterator<java.lang.String> iterator(); method public String next(); + method public void remove(); method public void setString(String); } @@ -49235,6 +49278,7 @@ package android.util { method public void ensureCapacity(int); method public java.util.Set<java.util.Map.Entry<K,V>> entrySet(); method public boolean equals(@Nullable Object); + method public void forEach(java.util.function.BiConsumer<? super K,? super V>); method public V get(Object); method public int hashCode(); method public int indexOfKey(Object); @@ -49248,6 +49292,7 @@ package android.util { method public V remove(Object); method public boolean removeAll(java.util.Collection<?>); method public V removeAt(int); + method public void replaceAll(java.util.function.BiFunction<? super K,? super V,? extends V>); method public boolean retainAll(java.util.Collection<?>); method public V setValueAt(int, V); method public int size(); @@ -49278,6 +49323,7 @@ package android.util { method public boolean removeAll(android.util.ArraySet<? extends E>); method public boolean removeAll(java.util.Collection<?>); method public E removeAt(int); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public boolean retainAll(java.util.Collection<?>); method public int size(); method public Object[] toArray(); @@ -53132,6 +53178,7 @@ package android.view { method protected void dispatchThawSelfOnly(android.util.SparseArray<android.os.Parcelable>); method protected boolean drawChild(@NonNull android.graphics.Canvas, android.view.View, long); method public void endViewTransition(android.view.View); + method @Nullable public android.window.OnBackInvokedDispatcher findOnBackInvokedDispatcherForChild(@NonNull android.view.View, @NonNull android.view.View); method public android.view.View focusSearch(android.view.View, int); method public void focusableViewAvailable(android.view.View); method protected android.view.ViewGroup.LayoutParams generateDefaultLayoutParams(); @@ -53173,6 +53220,7 @@ package android.view { method public void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int); method public final void offsetDescendantRectToMyCoords(android.view.View, android.graphics.Rect); method public final void offsetRectIntoDescendantCoords(android.view.View, android.graphics.Rect); + method @CallSuper public void onDescendantInvalidated(@NonNull android.view.View, @NonNull android.view.View); method public boolean onInterceptHoverEvent(android.view.MotionEvent); method public boolean onInterceptTouchEvent(android.view.MotionEvent); method protected abstract void onLayout(boolean, int, int, int, int); @@ -55332,12 +55380,14 @@ package android.view.inputmethod { method @Nullable public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int); method @Nullable public android.os.Handler getHandler(); method @Nullable public CharSequence getSelectedText(int); + method @Nullable public android.view.inputmethod.SurroundingText getSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int); method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int); method @Nullable public CharSequence getTextBeforeCursor(@IntRange(from=0) int, int); method public boolean performContextMenuAction(int); method public boolean performEditorAction(int); method public boolean performPrivateCommand(String, android.os.Bundle); method public static final void removeComposingSpans(@NonNull android.text.Spannable); + method public boolean replaceText(@IntRange(from=0) int, @IntRange(from=0) int, @NonNull CharSequence, int, @Nullable android.view.inputmethod.TextAttribute); method public boolean reportFullscreenMode(boolean); method public boolean requestCursorUpdates(int); method public boolean sendKeyEvent(android.view.KeyEvent); @@ -55345,6 +55395,7 @@ package android.view.inputmethod { method public static void setComposingSpans(@NonNull android.text.Spannable); method public boolean setComposingText(CharSequence, int); method public boolean setSelection(int, int); + method @Nullable public android.view.inputmethod.TextSnapshot takeSnapshot(); } public final class CompletionInfo implements android.os.Parcelable { @@ -55679,6 +55730,7 @@ package android.view.inputmethod { method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle); method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo); method public boolean commitText(CharSequence, int); + method public boolean commitText(@NonNull CharSequence, int, @Nullable android.view.inputmethod.TextAttribute); method public boolean deleteSurroundingText(int, int); method public boolean deleteSurroundingTextInCodePoints(int, int); method public boolean endBatchEdit(); @@ -55687,18 +55739,29 @@ package android.view.inputmethod { method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int); method public android.os.Handler getHandler(); method public CharSequence getSelectedText(int); + method @Nullable public android.view.inputmethod.SurroundingText getSurroundingText(int, int, int); method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int); method @Nullable public CharSequence getTextBeforeCursor(@IntRange(from=0) int, int); method public boolean performContextMenuAction(int); method public boolean performEditorAction(int); + method public void performHandwritingGesture(@NonNull android.view.inputmethod.HandwritingGesture, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.IntConsumer); method public boolean performPrivateCommand(String, android.os.Bundle); + method public boolean performSpellCheck(); + method public boolean previewHandwritingGesture(@NonNull android.view.inputmethod.PreviewableHandwritingGesture, @Nullable android.os.CancellationSignal); + method public boolean replaceText(@IntRange(from=0) int, @IntRange(from=0) int, @NonNull CharSequence, int, @Nullable android.view.inputmethod.TextAttribute); method public boolean reportFullscreenMode(boolean); method public boolean requestCursorUpdates(int); + method public boolean requestCursorUpdates(int, int); + method public void requestTextBoundsInfo(@NonNull android.graphics.RectF, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.inputmethod.TextBoundsInfoResult>); method public boolean sendKeyEvent(android.view.KeyEvent); method public boolean setComposingRegion(int, int); + method public boolean setComposingRegion(int, int, @Nullable android.view.inputmethod.TextAttribute); method public boolean setComposingText(CharSequence, int); + method public boolean setComposingText(@NonNull CharSequence, int, @Nullable android.view.inputmethod.TextAttribute); + method public boolean setImeConsumesInput(boolean); method public boolean setSelection(int, int); method public void setTarget(android.view.inputmethod.InputConnection); + method @Nullable public android.view.inputmethod.TextSnapshot takeSnapshot(); } public final class InputContentInfo implements android.os.Parcelable { @@ -58265,6 +58328,7 @@ package android.widget { public abstract class BaseAdapter implements android.widget.ListAdapter android.widget.SpinnerAdapter { ctor public BaseAdapter(); method public boolean areAllItemsEnabled(); + method public CharSequence[] getAutofillOptions(); method public android.view.View getDropDownView(int, android.view.View, android.view.ViewGroup); method public int getItemViewType(int); method public int getViewTypeCount(); diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 7cfa1e377933..1a22e9b10ad1 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -14,7 +14,7 @@ package android.app { @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback { method public final boolean addDumpable(@NonNull android.util.Dumpable); - method public final boolean isResumed(); + method @FlaggedApi("android.nfc.enable_nfc_mainline") public final boolean isResumed(); } public class ActivityManager { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index b6c9678f6cae..95dc07fe04eb 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -298,7 +298,7 @@ package android { field public static final String RECOVER_KEYSTORE = "android.permission.RECOVER_KEYSTORE"; field public static final String REGISTER_CALL_PROVIDER = "android.permission.REGISTER_CALL_PROVIDER"; field public static final String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER"; - field public static final String REGISTER_NSD_OFFLOAD_ENGINE = "android.permission.REGISTER_NSD_OFFLOAD_ENGINE"; + field @FlaggedApi("com.android.net.flags.register_nsd_offload_engine") public static final String REGISTER_NSD_OFFLOAD_ENGINE = "android.permission.REGISTER_NSD_OFFLOAD_ENGINE"; field public static final String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION"; field public static final String REGISTER_STATS_PULL_ATOM = "android.permission.REGISTER_STATS_PULL_ATOM"; field public static final String REMOTE_DISPLAY_PROVIDER = "android.permission.REMOTE_DISPLAY_PROVIDER"; @@ -357,6 +357,7 @@ package android { field public static final String SYSTEM_APPLICATION_OVERLAY = "android.permission.SYSTEM_APPLICATION_OVERLAY"; field public static final String SYSTEM_CAMERA = "android.permission.SYSTEM_CAMERA"; field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED"; + field @FlaggedApi("com.android.net.thread.flags.thread_enabled") public static final String THREAD_NETWORK_PRIVILEGED = "android.permission.THREAD_NETWORK_PRIVILEGED"; field public static final String TIS_EXTENSION_INTERFACE = "android.permission.TIS_EXTENSION_INTERFACE"; field public static final String TOGGLE_AUTOMOTIVE_PROJECTION = "android.permission.TOGGLE_AUTOMOTIVE_PROJECTION"; field public static final String TRIGGER_LOST_MODE = "android.permission.TRIGGER_LOST_MODE"; @@ -10244,6 +10245,7 @@ package android.nfc { method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable(); method @FlaggedApi("android.nfc.enable_nfc_reader_option") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableReaderOption(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean); + method @FlaggedApi("android.nfc.enable_nfc_mainline") public int getAdapterState(); method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn(); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported(); @@ -10254,6 +10256,7 @@ package android.nfc { method @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setReaderMode(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setTagIntentAppPreferenceForUser(int, @NonNull String, boolean); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener); + field @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC = "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC"; field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff field public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0; // 0x0 field public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2; // 0xfffffffe @@ -10301,6 +10304,7 @@ package android.nfc.cardemulation { 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 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); @@ -10311,10 +10315,15 @@ package android.nfc.cardemulation { method @FlaggedApi("android.nfc.enable_nfc_mainline") public void resetOffHostSecureElement(); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setDynamicAidGroup(@NonNull android.nfc.cardemulation.AidGroup); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setOffHostSecureElement(@NonNull String); + method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setOtherServiceEnabled(boolean); method @FlaggedApi("android.nfc.enable_nfc_mainline") public void writeToParcel(@NonNull android.os.Parcel, int); field @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public static final android.os.Parcelable.Creator<android.nfc.cardemulation.ApduServiceInfo> CREATOR; } + public final class CardEmulation { + method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int); + } + @FlaggedApi("android.nfc.enable_nfc_mainline") public final class NfcFServiceInfo implements android.os.Parcelable { ctor @FlaggedApi("android.nfc.enable_nfc_mainline") public NfcFServiceInfo(@NonNull android.content.pm.PackageManager, @NonNull android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method @FlaggedApi("android.nfc.enable_nfc_mainline") public int describeContents(); @@ -10789,6 +10798,7 @@ package android.os { ctor public ParcelableHolder(int); method public int describeContents(); method @Nullable public <T extends android.os.Parcelable> T getParcelable(@NonNull Class<T>); + method public int getStability(); method public void readFromParcel(@NonNull android.os.Parcel); method public void setParcelable(@Nullable android.os.Parcelable); method public void writeToParcel(@NonNull android.os.Parcel, int); diff --git a/core/java/Android.bp b/core/java/Android.bp index 26b758189996..d5acf4228a6b 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -226,7 +226,6 @@ filegroup { "com/android/internal/util/ConcurrentUtils.java", "com/android/internal/util/DumpUtils.java", "com/android/internal/util/FastPrintWriter.java", - "com/android/internal/util/FastXmlSerializer.java", "com/android/internal/util/FunctionalUtils.java", "com/android/internal/util/ParseUtils.java", "com/android/internal/util/RingBufferIndices.java", @@ -414,6 +413,10 @@ aidl_interface { backend: { rust: { enabled: true, + apex_available: [ + "//apex_available:platform", + "com.android.virt", + ], }, }, } @@ -455,7 +458,6 @@ filegroup { "com/android/internal/util/AsyncChannel.java", "com/android/internal/util/AsyncService.java", "com/android/internal/util/BitwiseInputStream.java", - "com/android/internal/util/FastXmlSerializer.java", "com/android/internal/util/HexDump.java", "com/android/internal/util/IndentingPrintWriter.java", "com/android/internal/util/UserIcons.java", @@ -505,7 +507,6 @@ filegroup { "android/net/InterfaceConfiguration.java", "android/util/BackupUtils.java", "android/util/Rational.java", - "com/android/internal/util/FastXmlSerializer.java", "com/android/internal/util/HexDump.java", "com/android/internal/util/MessageUtils.java", "com/android/internal/util/WakeupMessage.java", diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 259086932465..06c139f444ef 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -31,6 +31,7 @@ import android.annotation.CallSuper; import android.annotation.CallbackExecutor; import android.annotation.ColorInt; import android.annotation.DrawableRes; +import android.annotation.FlaggedApi; import android.annotation.IdRes; import android.annotation.IntDef; import android.annotation.LayoutRes; @@ -79,6 +80,7 @@ import android.graphics.drawable.Icon; import android.media.AudioManager; import android.media.session.MediaController; import android.net.Uri; +import android.nfc.Flags; import android.os.BadParcelableException; import android.os.Build; import android.os.Bundle; @@ -8915,6 +8917,7 @@ public class Activity extends ContextThemeWrapper * @hide */ @UnsupportedAppUsage + @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public final boolean isResumed() { return mResumed; diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index 2d554031ab48..c072feb5b46e 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -679,10 +679,11 @@ public class KeyguardManager { * <p> * Specifically, this returns {@code true} if at least one of the following is true: * <ul> - * <li>The {@link Context}'s user has a secure lock screen. A full user has a secure lock - * screen if its lock screen is set to PIN, pattern, or password, as opposed to swipe or none. - * A profile that uses a unified challenge is considered to have a secure lock screen if and - * only if its parent user has a secure lock screen.</li> + * <li>The {@link Context}'s user has a secure lock screen. A full user or a profile that uses + * a separate challenge has a secure lock screen if its lock screen is set to PIN, pattern, or + * password, as opposed to swipe or none. A profile that uses a unified challenge is + * considered to have a secure lock screen if and only if its parent user has a secure lock + * screen.</li> * <li>At least one SIM card is currently locked and requires a PIN.</li> * </ul> * <p> @@ -729,8 +730,15 @@ public class KeyguardManager { * <p> * For a user that is not the current user but can be switched to (usually this means "another * full user"), and that has a PIN, pattern, or password, the device is always considered - * locked. For a profile with a unified challenge, the device is considered locked if and only - * if the device is locked for the parent user. + * locked. + * <p> + * For a profile with a unified challenge, the device locked state is the same as that of the + * parent user. + * <p> + * For a profile with a separate challenge, the device becomes unlocked when the profile's PIN, + * pattern, password, or biometric is verified. It becomes locked when the parent user becomes + * locked, the screen turns off, the device reboots, the device policy controller locks the + * profile, or the timeout set by the device policy controller expires. * * @return {@code true} if the device is currently locked for the user * @see #isKeyguardLocked() @@ -757,9 +765,10 @@ public class KeyguardManager { * Returns whether the user has a secure lock screen. * <p> * This returns {@code true} if the {@link Context}'s user has a secure lock screen. A full user - * has a secure lock screen if its lock screen is set to PIN, pattern, or password, as opposed - * to swipe or none. A profile that uses a unified challenge is considered to have a secure lock - * screen if and only if its parent user has a secure lock screen. + * or a profile that uses a separate challenge has a secure lock screen if its lock screen is + * set to PIN, pattern, or password, as opposed to swipe or none. A profile that uses a unified + * challenge is considered to have a secure lock screen if and only if its parent user has a + * secure lock screen. * <p> * This method does not consider whether the lock screen is currently showing or not. * <p> diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS index e1c45d98e678..164bdbe9f516 100644 --- a/core/java/android/app/OWNERS +++ b/core/java/android/app/OWNERS @@ -36,6 +36,7 @@ per-file GameMode* = file:/GAME_MANAGER_OWNERS per-file GameState* = file:/GAME_MANAGER_OWNERS per-file IGameManager* = file:/GAME_MANAGER_OWNERS per-file IGameMode* = file:/GAME_MANAGER_OWNERS +per-file BackgroundStartPrivileges.java = file:/BAL_OWNERS # ActivityThread per-file ActivityThread.java = file:/services/core/java/com/android/server/am/OWNERS diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 4f5da99d539a..325758b58a3b 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -113,6 +113,7 @@ import android.hardware.iris.IrisManager; import android.hardware.lights.LightsManager; import android.hardware.lights.SystemLightsManager; import android.hardware.location.ContextHubManager; +import android.hardware.location.IContextHubService; import android.hardware.radio.RadioManager; import android.hardware.usb.IUsbManager; import android.hardware.usb.UsbManager; @@ -1125,8 +1126,12 @@ public final class SystemServiceRegistry { new CachedServiceFetcher<ContextHubManager>() { @Override public ContextHubManager createService(ContextImpl ctx) throws ServiceNotFoundException { - return new ContextHubManager(ctx.getOuterContext(), - ctx.mMainThread.getHandler().getLooper()); + IBinder b = ServiceManager.getService(Context.CONTEXTHUB_SERVICE); + if (b == null) { + return null; + } + return new ContextHubManager(IContextHubService.Stub.asInterface(b), + ctx.mMainThread.getHandler().getLooper()); }}); registerService(Context.INCIDENT_SERVICE, IncidentManager.class, diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java index cd45f4df3d50..b4f4a7efad98 100644 --- a/core/java/android/content/AttributionSource.java +++ b/core/java/android/content/AttributionSource.java @@ -212,6 +212,11 @@ public final class AttributionSource implements Parcelable { } /** @hide */ + public AttributionSource withDefaultToken() { + return withToken(sDefaultToken); + } + + /** @hide */ public AttributionSource withPid(int pid) { return new AttributionSource(getUid(), pid, getPackageName(), getAttributionTag(), getToken(), mAttributionSourceState.renouncedPermissions, getNext()); @@ -520,16 +525,28 @@ public final class AttributionSource implements Parcelable { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AttributionSource that = (AttributionSource) o; - return mAttributionSourceState.uid == that.mAttributionSourceState.uid + return equalsExceptToken(that) && Objects.equals( + mAttributionSourceState.token, that.mAttributionSourceState.token); + } + + /** + * We store trusted attribution sources without their token (the token is the key to the map) + * to avoid having a strong reference to the token. This means, when checking the equality of a + * supplied AttributionSource in PermissionManagerService.isTrustedAttributionSource, we want to + * compare everything except the token. + * + * @hide + */ + public boolean equalsExceptToken(@Nullable AttributionSource o) { + if (o == null) return false; + return mAttributionSourceState.uid == o.mAttributionSourceState.uid && Objects.equals(mAttributionSourceState.packageName, - that.mAttributionSourceState.packageName) + o.mAttributionSourceState.packageName) && Objects.equals(mAttributionSourceState.attributionTag, - that.mAttributionSourceState.attributionTag) - && Objects.equals(mAttributionSourceState.token, - that.mAttributionSourceState.token) + o.mAttributionSourceState.attributionTag) && Arrays.equals(mAttributionSourceState.renouncedPermissions, - that.mAttributionSourceState.renouncedPermissions) - && Objects.equals(getNext(), that.getNext()); + o.mAttributionSourceState.renouncedPermissions) + && Objects.equals(getNext(), o.getNext()); } @Override diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index c3fd744469e9..0fd0e1531771 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1161,6 +1161,11 @@ public class Intent implements Parcelable, Cloneable { * numbers. Applications can <strong>dial</strong> emergency numbers using * {@link #ACTION_DIAL}, however. * + * <p>Note: This Intent can only be used to dial call forwarding MMI codes if the application + * using this intent is set as the default or system dialer. The system will treat any other + * application using this Intent for the purpose of dialing call forwarding MMI codes as if the + * {@link #ACTION_DIAL} Intent was used instead. + * * <p>Note: An app filling the {@link android.app.role.RoleManager#ROLE_DIALER} role should use * {@link android.telecom.TelecomManager#placeCall(Uri, Bundle)} to place calls rather than * relying on this intent. diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java index 943eee461809..61d87026b6e9 100644 --- a/core/java/android/hardware/biometrics/BiometricConstants.java +++ b/core/java/android/hardware/biometrics/BiometricConstants.java @@ -18,6 +18,7 @@ package android.hardware.biometrics; import static android.hardware.biometrics.BiometricManager.Authenticators; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; @@ -296,4 +297,15 @@ public interface BiometricConstants { @Retention(RetentionPolicy.SOURCE) @IntDef({BIOMETRIC_LOCKOUT_NONE, BIOMETRIC_LOCKOUT_TIMED, BIOMETRIC_LOCKOUT_PERMANENT}) @interface LockoutMode {} + + // + // Other miscellaneous constants + // + + /** + * Returned from {@link BiometricManager#getLastAuthenticationTime(int)} when there has + * been no successful authentication for the given authenticator since boot. + */ + @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME) + long BIOMETRIC_NO_AUTHENTICATION = -1; } diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java index 82694ee3463b..90bbca8336e1 100644 --- a/core/java/android/hardware/biometrics/BiometricManager.java +++ b/core/java/android/hardware/biometrics/BiometricManager.java @@ -23,6 +23,8 @@ import static android.Manifest.permission.WRITE_DEVICE_CONFIG; import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_BIOMETRIC_MANAGER_CAN_AUTHENTICATE; +import android.annotation.ElapsedRealtimeLong; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -30,6 +32,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.app.KeyguardManager; import android.content.Context; import android.os.IBinder; import android.os.RemoteException; @@ -86,6 +89,17 @@ public class BiometricManager { BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED; /** + * Returned from {@link BiometricManager#getLastAuthenticationTime(int)} when no matching + * successful authentication has been performed since boot. + */ + @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME) + public static final long BIOMETRIC_NO_AUTHENTICATION = + BiometricConstants.BIOMETRIC_NO_AUTHENTICATION; + + private static final int GET_LAST_AUTH_TIME_ALLOWED_AUTHENTICATORS = + Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG; + + /** * @hide */ @IntDef({BIOMETRIC_SUCCESS, @@ -637,5 +651,58 @@ public class BiometricManager { } } + + /** + * Gets the last time the user successfully authenticated using one of the given authenticators. + * The returned value is time in + * {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()} (time since + * boot, including sleep). + * <p> + * {@link BiometricManager#BIOMETRIC_NO_AUTHENTICATION} is returned in the case where there + * has been no successful authentication using any of the given authenticators since boot. + * <p> + * Currently, only {@link Authenticators#DEVICE_CREDENTIAL} and + * {@link Authenticators#BIOMETRIC_STRONG} are accepted. {@link IllegalArgumentException} will + * be thrown if {@code authenticators} contains other authenticator types. + * <p> + * Note that this may return successful authentication times even if the device is currently + * locked. You may use {@link KeyguardManager#isDeviceLocked()} to determine if the device + * is unlocked or not. Additionally, this method may return valid times for an authentication + * method that is no longer available. For instance, if the user unlocked the device with a + * {@link Authenticators#BIOMETRIC_STRONG} authenticator but then deleted that authenticator + * (e.g., fingerprint data), this method will still return the time of that unlock for + * {@link Authenticators#BIOMETRIC_STRONG} if it is the most recent successful event. The caveat + * is that {@link BiometricManager#BIOMETRIC_NO_AUTHENTICATION} will be returned if the device + * no longer has a secure lock screen at all, even if there were successful authentications + * performed before the lock screen was made insecure. + * + * @param authenticators bit field consisting of constants defined in {@link Authenticators}. + * @return the time of last authentication or + * {@link BiometricManager#BIOMETRIC_NO_AUTHENTICATION} + * @throws IllegalArgumentException if {@code authenticators} contains values other than + * {@link Authenticators#DEVICE_CREDENTIAL} and {@link Authenticators#BIOMETRIC_STRONG} or is + * 0. + */ + @RequiresPermission(USE_BIOMETRIC) + @ElapsedRealtimeLong + @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME) + public long getLastAuthenticationTime( + @BiometricManager.Authenticators.Types int authenticators) { + if (authenticators == 0 + || (GET_LAST_AUTH_TIME_ALLOWED_AUTHENTICATORS & authenticators) != authenticators) { + throw new IllegalArgumentException( + "Only BIOMETRIC_STRONG and DEVICE_CREDENTIAL authenticators may be used."); + } + + if (mService != null) { + try { + return mService.getLastAuthenticationTime(UserHandle.myUserId(), authenticators); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } else { + return BIOMETRIC_NO_AUTHENTICATION; + } + } } diff --git a/core/java/android/hardware/biometrics/IAuthService.aidl b/core/java/android/hardware/biometrics/IAuthService.aidl index c2e5c0b6d519..5bdbe2b573b2 100644 --- a/core/java/android/hardware/biometrics/IAuthService.aidl +++ b/core/java/android/hardware/biometrics/IAuthService.aidl @@ -57,6 +57,9 @@ interface IAuthService { // Checks if biometrics can be used. int canAuthenticate(String opPackageName, int userId, int authenticators); + // Gets the time of last authentication for the given user and authenticators. + long getLastAuthenticationTime(int userId, int authenticators); + // Checks if any biometrics are enrolled. boolean hasEnrolledBiometrics(int userId, String opPackageName); diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl index 18c8d1bd3a1e..058f302af62b 100644 --- a/core/java/android/hardware/biometrics/IBiometricService.aidl +++ b/core/java/android/hardware/biometrics/IBiometricService.aidl @@ -53,6 +53,10 @@ interface IBiometricService { @EnforcePermission("USE_BIOMETRIC_INTERNAL") int canAuthenticate(String opPackageName, int userId, int callingUserId, int authenticators); + // Gets the time of last authentication for the given user and authenticators. + @EnforcePermission("USE_BIOMETRIC_INTERNAL") + long getLastAuthenticationTime(int userId, int authenticators); + // Checks if any biometrics are enrolled. @EnforcePermission("USE_BIOMETRIC_INTERNAL") boolean hasEnrolledBiometrics(int userId, String opPackageName); diff --git a/core/java/android/hardware/biometrics/flags.aconfig b/core/java/android/hardware/biometrics/flags.aconfig index 0924e0d12bd3..c370ad658c3b 100644 --- a/core/java/android/hardware/biometrics/flags.aconfig +++ b/core/java/android/hardware/biometrics/flags.aconfig @@ -1,6 +1,13 @@ package: "android.hardware.biometrics" flag { + name: "last_authentication_time" + namespace: "wallet_integration" + description: "Feature flag for adding getLastAuthenticationTime API to BiometricManager" + bug: "301979982" +} + +flag { name: "add_key_agreement_crypto_object" namespace: "biometrics" description: "Feature flag for adding KeyAgreement api to CryptoObject." diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index 01ce7b9c0731..481ec7207c8a 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -15,6 +15,8 @@ */ package android.hardware.location; +import static java.util.Objects.requireNonNull; + import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; @@ -1111,12 +1113,12 @@ public final class ContextHubManager { } }; - /** @throws ServiceNotFoundException - * @hide */ - public ContextHubManager(Context context, Looper mainLooper) throws ServiceNotFoundException { + /** @hide */ + public ContextHubManager(@NonNull IContextHubService service, @NonNull Looper mainLooper) { + requireNonNull(service, "service cannot be null"); + requireNonNull(mainLooper, "mainLooper cannot be null"); + mService = service; mMainLooper = mainLooper; - mService = IContextHubService.Stub.asInterface( - ServiceManager.getServiceOrThrow(Context.CONTEXTHUB_SERVICE)); try { mService.registerCallback(mClientCallback); } catch (RemoteException e) { diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl index 0a6be20226b8..eda80c861698 100644 --- a/core/java/android/net/INetworkManagementEventObserver.aidl +++ b/core/java/android/net/INetworkManagementEventObserver.aidl @@ -85,14 +85,14 @@ oneway interface INetworkManagementEventObserver { /** * Interface data activity status is changed. * - * @param transportType The transport type of the data activity change. + * @param label label of the data activity change. * @param active True if the interface is actively transmitting data, false if it is idle. * @param tsNanos Elapsed realtime in nanos when the state of the network interface changed. * @param uid Uid of this event. It represents the uid that was responsible for waking the * radio. For those events that are reported by system itself, not from specific uid, * use -1 for the events which means no uid. */ - void interfaceClassDataActivityChanged(int transportType, boolean active, long tsNanos, int uid); + void interfaceClassDataActivityChanged(int label, boolean active, long tsNanos, int uid); /** * Information about available DNS servers has been received. diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java index a40fb154c256..6f11d3ae661c 100644 --- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java +++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java @@ -16,10 +16,12 @@ package android.net.vcn; import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE; +import static android.net.vcn.Flags.FLAG_SAFE_MODE_CONFIG; import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED; import static com.android.internal.annotations.VisibleForTesting.Visibility; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; @@ -235,6 +237,9 @@ public final class VcnGatewayConnectionConfig { "mMinUdpPort4500NatTimeoutSeconds"; private final int mMinUdpPort4500NatTimeoutSeconds; + private static final String IS_SAFE_MODE_DISABLED_KEY = "mIsSafeModeDisabled"; + private final boolean mIsSafeModeDisabled; + private static final String GATEWAY_OPTIONS_KEY = "mGatewayOptions"; @NonNull private final Set<Integer> mGatewayOptions; @@ -247,6 +252,7 @@ public final class VcnGatewayConnectionConfig { @NonNull long[] retryIntervalsMs, @IntRange(from = MIN_MTU_V6) int maxMtu, @NonNull int minUdpPort4500NatTimeoutSeconds, + boolean isSafeModeDisabled, @NonNull Set<Integer> gatewayOptions) { mGatewayConnectionName = gatewayConnectionName; mTunnelConnectionParams = tunnelConnectionParams; @@ -255,6 +261,7 @@ public final class VcnGatewayConnectionConfig { mMaxMtu = maxMtu; mMinUdpPort4500NatTimeoutSeconds = minUdpPort4500NatTimeoutSeconds; mGatewayOptions = Collections.unmodifiableSet(new ArraySet(gatewayOptions)); + mIsSafeModeDisabled = isSafeModeDisabled; mUnderlyingNetworkTemplates = new ArrayList<>(underlyingNetworkTemplates); if (mUnderlyingNetworkTemplates.isEmpty()) { @@ -317,6 +324,7 @@ public final class VcnGatewayConnectionConfig { in.getInt( MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS_KEY, MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET); + mIsSafeModeDisabled = in.getBoolean(IS_SAFE_MODE_DISABLED_KEY); validate(); } @@ -483,6 +491,16 @@ public final class VcnGatewayConnectionConfig { } /** + * Check whether safe mode is enabled + * + * @see Builder#setSafeModeEnabled(boolean) + */ + @FlaggedApi(FLAG_SAFE_MODE_CONFIG) + public boolean isSafeModeEnabled() { + return !mIsSafeModeDisabled; + } + + /** * Checks if the given VCN gateway option is enabled. * * @param option the option to check. @@ -528,6 +546,7 @@ public final class VcnGatewayConnectionConfig { result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs); result.putInt(MAX_MTU_KEY, mMaxMtu); result.putInt(MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS_KEY, mMinUdpPort4500NatTimeoutSeconds); + result.putBoolean(IS_SAFE_MODE_DISABLED_KEY, mIsSafeModeDisabled); return result; } @@ -542,6 +561,7 @@ public final class VcnGatewayConnectionConfig { Arrays.hashCode(mRetryIntervalsMs), mMaxMtu, mMinUdpPort4500NatTimeoutSeconds, + mIsSafeModeDisabled, mGatewayOptions); } @@ -559,6 +579,7 @@ public final class VcnGatewayConnectionConfig { && Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs) && mMaxMtu == rhs.mMaxMtu && mMinUdpPort4500NatTimeoutSeconds == rhs.mMinUdpPort4500NatTimeoutSeconds + && mIsSafeModeDisabled == rhs.mIsSafeModeDisabled && mGatewayOptions.equals(rhs.mGatewayOptions); } @@ -577,6 +598,7 @@ public final class VcnGatewayConnectionConfig { @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS; private int mMaxMtu = DEFAULT_MAX_MTU; private int mMinUdpPort4500NatTimeoutSeconds = MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET; + private boolean mIsSafeModeDisabled = false; @NonNull private final Set<Integer> mGatewayOptions = new ArraySet<>(); @@ -789,6 +811,27 @@ public final class VcnGatewayConnectionConfig { } /** + * Enable/disable safe mode + * + * <p>If a VCN fails to provide connectivity within a system-provided timeout, it will enter + * safe mode. In safe mode, the VCN Network will be torn down and the system will restore + * connectivity by allowing underlying cellular or WiFi networks to be used as default. At + * the same time, VCN will continue to retry until it succeeds. + * + * <p>When safe mode is disabled and VCN connection fails to provide connectivity, end users + * might not have connectivity, and may not have access to carrier-owned underlying + * networks. + * + * @param enabled whether safe mode should be enabled. Defaults to {@code true} + */ + @FlaggedApi(FLAG_SAFE_MODE_CONFIG) + @NonNull + public Builder setSafeModeEnabled(boolean enabled) { + mIsSafeModeDisabled = !enabled; + return this; + } + + /** * Builds and validates the VcnGatewayConnectionConfig. * * @return an immutable VcnGatewayConnectionConfig instance @@ -803,6 +846,7 @@ public final class VcnGatewayConnectionConfig { mRetryIntervalsMs, mMaxMtu, mMinUdpPort4500NatTimeoutSeconds, + mIsSafeModeDisabled, mGatewayOptions); } } diff --git a/core/java/android/net/vcn/flags.aconfig b/core/java/android/net/vcn/flags.aconfig new file mode 100644 index 000000000000..6956916af0f1 --- /dev/null +++ b/core/java/android/net/vcn/flags.aconfig @@ -0,0 +1,8 @@ +package: "android.net.vcn" + +flag { + name: "safe_mode_config" + namespace: "vcn" + description: "Feature flag for safe mode configurability" + bug: "276358140" +}
\ No newline at end of file diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 0c95c2ec7a7a..f6beec179d57 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -84,4 +84,6 @@ interface INfcAdapter boolean isReaderOptionSupported(); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)") boolean enableReaderOption(boolean enable); + boolean isObserveModeSupported(); + boolean setObserveMode(boolean enabled); } diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl index 53843fe73d33..191385a3c13d 100644 --- a/core/java/android/nfc/INfcCardEmulation.aidl +++ b/core/java/android/nfc/INfcCardEmulation.aidl @@ -30,6 +30,7 @@ interface INfcCardEmulation boolean isDefaultServiceForAid(int userHandle, in ComponentName service, String aid); boolean setDefaultServiceForCategory(int userHandle, in ComponentName service, String category); boolean setDefaultForNextTap(int userHandle, in ComponentName service); + boolean setServiceObserveModeDefault(int userId, in android.content.ComponentName service, boolean enable); boolean registerAidGroupForService(int userHandle, in ComponentName service, in AidGroup aidGroup); boolean setOffHostForService(int userHandle, in ComponentName service, in String offHostSecureElement); boolean unsetOffHostForService(int userHandle, in ComponentName service); @@ -40,5 +41,6 @@ interface INfcCardEmulation boolean unsetPreferredService(); boolean supportsAidPrefixRegistration(); ApduServiceInfo getPreferredPaymentService(int userHandle); + boolean setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status); boolean isDefaultPaymentRegistered(); } diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 4a7bd3f29458..98a980f5e7f8 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -378,6 +378,8 @@ public final class NfcAdapter { * <p>An external NFC field detected when device locked and SecureNfc enabled. * @hide */ + @SystemApi + @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC = "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC"; @@ -944,7 +946,8 @@ public final class NfcAdapter { * * @hide */ - @UnsupportedAppUsage + @SystemApi + @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public int getAdapterState() { try { return sService.getState(); @@ -1078,6 +1081,61 @@ public final class NfcAdapter { } } + + /** + * Returns whether the device supports observer mode or not. When observe + * mode is enabled, the NFC hardware will listen for NFC readers, but not + * respond to them. When observe mode is disabled, the NFC hardware will + * resoond to the reader and proceed with the transaction. + * @return true if the mode is supported, false otherwise. + */ + @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE) + public boolean isObserveModeSupported() { + try { + return sService.isObserveModeSupported(); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + return false; + } + } + + /** + * Disables observe mode to allow the transaction to proceed. See + * {@link #isObserveModeSupported()} for a description of observe mode and + * use {@link #disallowTransaction()} to enable observe mode and block + * transactions again. + * + * @return boolean indicating success or failure. + */ + @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE) + public boolean allowTransaction() { + try { + return sService.setObserveMode(false); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + return false; + } + } + + /** + * Signals that the transaction has completed and observe mode may be + * reenabled. See {@link #isObserveModeSupported()} for a description of + * observe mode and use {@link #allowTransaction()} to disable observe + * mode and allow transactions to proceed. + * + * @return boolean indicating success or failure. + */ + + @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE) + public boolean disallowTransaction() { + try { + return sService.setObserveMode(true); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + return false; + } + } + /** * Resumes default polling for the current device state if polling is paused. Calling * this while polling is not paused is a no-op. diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java index 665b7531d3ce..e331c95288d9 100644 --- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java +++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java @@ -21,6 +21,7 @@ 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; @@ -127,15 +128,34 @@ public final class ApduServiceInfo implements Parcelable { private final String mSettingsActivityName; /** + * State of the service for CATEGORY_OTHER selection + */ + private boolean mOtherServiceEnabled; + + /** * @hide */ + @UnsupportedAppUsage public ApduServiceInfo(ResolveInfo info, boolean onHost, String description, - List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups, + ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups, boolean requiresUnlock, int bannerResource, int uid, String settingsActivityName, String offHost, String staticOffHost) { this(info, onHost, description, staticAidGroups, dynamicAidGroups, + requiresUnlock, bannerResource, uid, settingsActivityName, + offHost, staticOffHost, false); + } + + /** + * @hide + */ + public ApduServiceInfo(ResolveInfo info, boolean onHost, String description, + ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups, + boolean requiresUnlock, int bannerResource, int uid, + String settingsActivityName, String offHost, String staticOffHost, + boolean isEnabled) { + this(info, onHost, description, staticAidGroups, dynamicAidGroups, requiresUnlock, onHost ? true : false, bannerResource, uid, - settingsActivityName, offHost, staticOffHost); + settingsActivityName, offHost, staticOffHost, isEnabled); } /** @@ -144,7 +164,7 @@ public final class ApduServiceInfo implements Parcelable { public ApduServiceInfo(ResolveInfo info, boolean onHost, String description, List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups, boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid, - String settingsActivityName, String offHost, String staticOffHost) { + String settingsActivityName, String offHost, String staticOffHost, boolean isEnabled) { this.mService = info; this.mDescription = description; this.mStaticAidGroups = new HashMap<String, AidGroup>(); @@ -163,6 +183,8 @@ public final class ApduServiceInfo implements Parcelable { this.mBannerResourceId = bannerResource; this.mUid = uid; this.mSettingsActivityName = settingsActivityName; + this.mOtherServiceEnabled = isEnabled; + } /** @@ -351,6 +373,9 @@ public final class ApduServiceInfo implements Parcelable { } // Set uid mUid = si.applicationInfo.uid; + + mOtherServiceEnabled = false; // support other category + } /** @@ -720,43 +745,47 @@ public final class ApduServiceInfo implements Parcelable { dest.writeInt(mBannerResourceId); dest.writeInt(mUid); dest.writeString(mSettingsActivityName); + + dest.writeInt(mOtherServiceEnabled ? 1 : 0); }; @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public static final @NonNull Parcelable.Creator<ApduServiceInfo> CREATOR = new Parcelable.Creator<ApduServiceInfo>() { - @Override - public ApduServiceInfo createFromParcel(Parcel source) { - ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source); - String description = source.readString(); - boolean onHost = source.readInt() != 0; - String offHostName = source.readString(); - String staticOffHostName = source.readString(); - ArrayList<AidGroup> staticAidGroups = new ArrayList<AidGroup>(); - int numStaticGroups = source.readInt(); - if (numStaticGroups > 0) { - source.readTypedList(staticAidGroups, AidGroup.CREATOR); - } - ArrayList<AidGroup> dynamicAidGroups = new ArrayList<AidGroup>(); - int numDynamicGroups = source.readInt(); - if (numDynamicGroups > 0) { - source.readTypedList(dynamicAidGroups, AidGroup.CREATOR); - } - boolean requiresUnlock = source.readInt() != 0; - boolean requiresScreenOn = source.readInt() != 0; - int bannerResource = source.readInt(); - int uid = source.readInt(); - String settingsActivityName = source.readString(); - return new ApduServiceInfo(info, onHost, description, staticAidGroups, - dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid, - settingsActivityName, offHostName, staticOffHostName); - } + @Override + public ApduServiceInfo createFromParcel(Parcel source) { + ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source); + String description = source.readString(); + boolean onHost = source.readInt() != 0; + String offHostName = source.readString(); + String staticOffHostName = source.readString(); + ArrayList<AidGroup> staticAidGroups = new ArrayList<AidGroup>(); + int numStaticGroups = source.readInt(); + if (numStaticGroups > 0) { + source.readTypedList(staticAidGroups, AidGroup.CREATOR); + } + ArrayList<AidGroup> dynamicAidGroups = new ArrayList<AidGroup>(); + int numDynamicGroups = source.readInt(); + if (numDynamicGroups > 0) { + source.readTypedList(dynamicAidGroups, AidGroup.CREATOR); + } + boolean requiresUnlock = source.readInt() != 0; + boolean requiresScreenOn = source.readInt() != 0; + int bannerResource = source.readInt(); + int uid = source.readInt(); + String settingsActivityName = source.readString(); + boolean isEnabled = source.readInt() != 0; + return new ApduServiceInfo(info, onHost, description, staticAidGroups, + dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid, + settingsActivityName, offHostName, staticOffHostName, + isEnabled); + } - @Override - public ApduServiceInfo[] newArray(int size) { - return new ApduServiceInfo[size]; - } - }; + @Override + public ApduServiceInfo[] newArray(int size) { + return new ApduServiceInfo[size]; + } + }; /** * Dump contents for debugging. @@ -779,14 +808,16 @@ public final class ApduServiceInfo implements Parcelable { } pw.println(" Static AID groups:"); for (AidGroup group : mStaticAidGroups.values()) { - pw.println(" Category: " + group.getCategory()); + pw.println(" Category: " + group.getCategory() + + "(enabled: " + mOtherServiceEnabled + ")"); for (String aid : group.getAids()) { pw.println(" AID: " + aid); } } pw.println(" Dynamic AID groups:"); for (AidGroup group : mDynamicAidGroups.values()) { - pw.println(" Category: " + group.getCategory()); + pw.println(" Category: " + group.getCategory() + + "(enabled: " + mOtherServiceEnabled + ")"); for (String aid : group.getAids()) { pw.println(" AID: " + aid); } @@ -796,6 +827,28 @@ public final class ApduServiceInfo implements Parcelable { pw.println(" Requires Device ScreenOn: " + mRequiresDeviceScreenOn); } + + /** + * Enable or disable this CATEGORY_OTHER service. + * + * @param enabled true to indicate if user has enabled this service + */ + @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) + public void setOtherServiceEnabled(boolean enabled) { + mOtherServiceEnabled = enabled; + } + + + /** + * Returns whether this CATEGORY_OTHER service is enabled or not. + * + * @return true to indicate if user has enabled this service + */ + @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) + public boolean isOtherServiceEnabled() { + return mOtherServiceEnabled; + } + /** * Dump debugging info as ApduServiceInfoProto. * diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java index 32c2a1b40530..58b6179691e9 100644 --- a/core/java/android/nfc/cardemulation/CardEmulation.java +++ b/core/java/android/nfc/cardemulation/CardEmulation.java @@ -16,17 +16,21 @@ package android.nfc.cardemulation; +import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; +import android.annotation.UserIdInt; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.nfc.Constants; +import android.nfc.Flags; import android.nfc.INfcCardEmulation; import android.nfc.NfcAdapter; import android.os.RemoteException; @@ -324,6 +328,24 @@ public final class CardEmulation { return SELECTION_MODE_ASK_IF_CONFLICT; } } + /** + * Sets whether the system should default to observe mode or not when + * the service is in the foreground or the default payment service. + * + * @param service The component name of the service + * @param enable Whether the servic should default to observe mode or not + * @return whether the change was successful. + */ + @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE) + public boolean setServiceObserveModeDefault(@NonNull ComponentName service, boolean enable) { + try { + return sService.setServiceObserveModeDefault(mContext.getUser().getIdentifier(), + service, enable); + } catch (RemoteException e) { + Log.e(TAG, "Failed to reach CardEmulationService."); + } + return false; + } /** * Registers a list of AIDs for a specific category for the @@ -877,9 +899,16 @@ public final class CardEmulation { } /** + * Retrieves list of services registered of the provided category for the provided user. + * + * @param category Category string, one of {@link #CATEGORY_PAYMENT} or {@link #CATEGORY_OTHER} + * @param userId the user handle of the user whose information is being requested. * @hide */ - public List<ApduServiceInfo> getServices(String category, int userId) { + @SystemApi + @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) + @NonNull + public List<ApduServiceInfo> getServices(@NonNull String category, @UserIdInt int userId) { try { return sService.getServices(userId, category); } catch (RemoteException e) { @@ -936,6 +965,39 @@ public final class CardEmulation { return true; } + /** + * Allows to set or unset preferred service (category other) to avoid AID Collision. + * + * @param service The ComponentName of the service + * @param status true to enable, false to disable + * @return set service for the category and true if service is already set return false. + * + * @hide + */ + public boolean setServiceEnabledForCategoryOther(ComponentName service, boolean status) { + if (service == null) { + throw new NullPointerException("activity or service or category is null"); + } + int userId = mContext.getUser().getIdentifier(); + + try { + return sService.setServiceEnabledForCategoryOther(userId, service, status); + } catch (RemoteException e) { + // Try one more time + recoverService(); + if (sService == null) { + Log.e(TAG, "Failed to recover CardEmulationService."); + return false; + } + try { + return sService.setServiceEnabledForCategoryOther(userId, service, status); + } catch (RemoteException ee) { + Log.e(TAG, "Failed to reach CardEmulationService."); + return false; + } + } + } + void recoverService() { NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); sService = adapter.getCardEmulationService(); diff --git a/core/java/android/nfc/cardemulation/HostApduService.java b/core/java/android/nfc/cardemulation/HostApduService.java index 55d0e73780a2..7cd2533a7dbf 100644 --- a/core/java/android/nfc/cardemulation/HostApduService.java +++ b/core/java/android/nfc/cardemulation/HostApduService.java @@ -16,11 +16,14 @@ package android.nfc.cardemulation; +import android.annotation.FlaggedApi; +import android.annotation.NonNull; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; import android.content.Intent; import android.content.pm.PackageManager; +import android.nfc.NfcAdapter; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -29,6 +32,9 @@ import android.os.Messenger; import android.os.RemoteException; import android.util.Log; +import java.util.ArrayList; +import java.util.List; + /** * <p>HostApduService is a convenience {@link Service} class that can be * extended to emulate an NFC card inside an Android @@ -230,9 +236,99 @@ public abstract class HostApduService extends Service { /** * @hide */ + public static final int MSG_POLLING_LOOP = 4; + + /** + * @hide + */ public static final String KEY_DATA = "data"; /** + * POLLING_LOOP_TYPE_KEY is the Bundle key for the type of + * polling loop frame in the Bundle passed to {@link #processPollingFrames(List)} + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public static final String POLLING_LOOP_TYPE_KEY = "android.nfc.cardemulation.TYPE"; + + /** + * POLLING_LOOP_TYPE_A is the value associated with the key + * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)} + * when the polling loop is for NFC-A. + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public static final char POLLING_LOOP_TYPE_A = 'A'; + + /** + * POLLING_LOOP_TYPE_B is the value associated with the key + * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)} + * when the polling loop is for NFC-B. + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public static final char POLLING_LOOP_TYPE_B = 'B'; + + /** + * POLLING_LOOP_TYPE_F is the value associated with the key + * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)} + * when the polling loop is for NFC-F. + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public static final char POLLING_LOOP_TYPE_F = 'F'; + + /** + * POLLING_LOOP_TYPE_ON is the value associated with the key + * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)} + * when the polling loop turns on. + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public static final char POLLING_LOOP_TYPE_ON = 'O'; + + /** + * POLLING_LOOP_TYPE_OFF is the value associated with the key + * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)} + * when the polling loop turns off. + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public static final char POLLING_LOOP_TYPE_OFF = 'X'; + + /** + * POLLING_LOOP_TYPE_UNKNOWN is the value associated with the key + * POLLING_LOOP_TYPE in the Bundle passed to {@link #processPollingFrames(List)} + * when the polling loop frame isn't recognized. + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public static final char POLLING_LOOP_TYPE_UNKNOWN = 'U'; + + /** + * POLLING_LOOP_DATA is the Bundle key for the raw data of captured from + * the polling loop frame in the Bundle passed to {@link #processPollingFrames(List)} + * when the frame type isn't recognized. + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public static final String POLLING_LOOP_DATA_KEY = "android.nfc.cardemulation.DATA"; + + /** + * POLLING_LOOP_GAIN_KEY is the Bundle key for the field strength of + * the polling loop frame in the Bundle passed to {@link #processPollingFrames(List)} + * when the frame type isn't recognized. + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public static final String POLLING_LOOP_GAIN_KEY = "android.nfc.cardemulation.GAIN"; + + /** + * POLLING_LOOP_TIMESTAMP_KEY is the Bundle key for the timestamp of + * the polling loop frame in the Bundle passed to {@link #processPollingFrames(List)} + * when the frame type isn't recognized. + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public static final String POLLING_LOOP_TIMESTAMP_KEY = "android.nfc.cardemulation.TIMESTAMP"; + + /** + * @hide + */ + public static final String POLLING_LOOP_FRAMES_BUNDLE_KEY = + "android.nfc.cardemulation.POLLING_FRAMES"; + + /** * Messenger interface to NfcService for sending responses. * Only accessed on main thread by the message handler. * @@ -255,6 +351,7 @@ public abstract class HostApduService extends Service { byte[] apdu = dataBundle.getByteArray(KEY_DATA); if (apdu != null) { + HostApduService has = HostApduService.this; byte[] responseApdu = processCommandApdu(apdu, null); if (responseApdu != null) { if (mNfcService == null) { @@ -306,6 +403,12 @@ public abstract class HostApduService extends Service { Log.e(TAG, "RemoteException calling into NfcService."); } break; + case MSG_POLLING_LOOP: + ArrayList<Bundle> frames = + msg.getData().getParcelableArrayList(POLLING_LOOP_FRAMES_BUNDLE_KEY, + Bundle.class); + processPollingFrames(frames); + break; default: super.handleMessage(msg); } @@ -366,6 +469,21 @@ public abstract class HostApduService extends Service { } } + /** + * This method is called when a polling frame has been received from a + * remote device. If the device is in observe mode, the service should + * call {@link NfcAdapter#allowTransaction()} once it is ready to proceed + * with the transaction. If the device is not in observe mode, the service + * can use this polling frame information to determine how to proceed if it + * subsequently has {@link #processCommandApdu(byte[], Bundle)} called. The + * service must override this method inorder to receive polling frames, + * otherwise the base implementation drops the frame. + * + * @param frame A description of the polling frame. + */ + @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) + public void processPollingFrames(@NonNull List<Bundle> frame) { + } /** * <p>This method will be called when a command APDU has been received diff --git a/core/java/android/nfc/flags.aconfig b/core/java/android/nfc/flags.aconfig index cd50ace036de..17e042761dbe 100644 --- a/core/java/android/nfc/flags.aconfig +++ b/core/java/android/nfc/flags.aconfig @@ -20,3 +20,31 @@ flag { description: "Flag for NFC user restriction" bug: "291187960" } + +flag { + name: "nfc_observe_mode" + namespace: "nfc" + description: "Enable NFC Observe Mode" + bug: "294217286" +} + +flag { + name: "nfc_read_polling_loop" + namespace: "nfc" + description: "Enable NFC Polling Loop Notifications" + bug: "294217286" +} + +flag { + name: "nfc_observe_mode_st_shim" + namespace: "nfc" + description: "Enable NFC Observe Mode ST shim" + bug: "294217286" +} + +flag { + name: "nfc_read_polling_loop_st_shim" + namespace: "nfc" + description: "Enable NFC Polling Loop Notifications ST shim" + bug: "294217286" +} diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java index 6a4ec9b7605a..25fba60b9bb5 100644 --- a/core/java/android/os/BatteryManager.java +++ b/core/java/android/os/BatteryManager.java @@ -21,6 +21,7 @@ import static android.os.Flags.FLAG_STATE_OF_HEALTH_PUBLIC; import android.Manifest.permission; import android.annotation.FlaggedApi; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; @@ -236,6 +237,7 @@ public class BatteryManager { OsProtoEnums.CHARGING_POLICY_ADAPTIVE_LONGLIFE; // = 4 /** @hide */ + @SuppressLint("UnflaggedApi") // TestApi without associated feature. @TestApi public static final int BATTERY_PLUGGED_ANY = BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 509c3b88441e..a9b7257a5406 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -17,6 +17,7 @@ package android.os; import android.Manifest; +import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -1227,6 +1228,7 @@ public class Build { /** * Vanilla Ice Cream. */ + @FlaggedApi(Flags.FLAG_ANDROID_OS_BUILD_VANILLA_ICE_CREAM) public static final int VANILLA_ICE_CREAM = CUR_DEVELOPMENT; } diff --git a/core/java/android/os/DeadObjectException.java b/core/java/android/os/DeadObjectException.java index e06b0f9f4bc2..61aa222ef482 100644 --- a/core/java/android/os/DeadObjectException.java +++ b/core/java/android/os/DeadObjectException.java @@ -19,7 +19,29 @@ import android.os.RemoteException; /** * The object you are calling has died, because its hosting process - * no longer exists. + * no longer exists, or there has been a low-level binder error. + * + * If you get this exception from a system service, the error is + * usually nonrecoverable as the framework will restart. If you + * receive this error from an app, at a minimum, you should + * recover by resetting the connection. For instance, you should + * drop the binder, clean up associated state, and reset your + * connection to the service which through this error. In order + * to simplify your error recovery paths, you may also want to + * "simply" restart your process. However, this may not be an + * option if the service you are talking to is unreliable or + * crashes frequently. + * + * If this isn't from a service death and is instead from a + * low-level binder error, it will be from: + * - a oneway call queue filling up (too many oneway calls) + * - from the binder buffer being filled up, so that the transaction + * is rejected. + * + * In these cases, more information about the error will be + * logged. However, there isn't a good way to differentiate + * this information at runtime. So, you should handle the + * error, as if the service died. */ public class DeadObjectException extends RemoteException { public DeadObjectException() { diff --git a/core/java/android/os/DeadSystemRuntimeException.java b/core/java/android/os/DeadSystemRuntimeException.java index 1e869249eb9d..3b107984cebf 100644 --- a/core/java/android/os/DeadSystemRuntimeException.java +++ b/core/java/android/os/DeadSystemRuntimeException.java @@ -18,9 +18,12 @@ package android.os; /** * Exception thrown when a call into system_server resulted in a - * DeadObjectException, meaning that the system_server has died. There's - * nothing apps can do at this point - the system will automatically restart - - * so there's no point in catching this. + * DeadObjectException, meaning that the system_server has died or + * experienced a low-level binder error. There's nothing apps can + * do at this point - the system will automatically restart - so + * there's no point in catching this. + * + * See {@link android.os.DeadObjectException}. * * @hide */ diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index a07735e7540e..8fcff78fb025 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -117,8 +117,6 @@ public class GraphicsEnvironment { private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native"; private static final String SYSTEM_ANGLE_STRING = "system"; - private static final String PROPERTY_RO_ANGLE_SUPPORTED = "ro.gfx.angle.supported"; - private ClassLoader mClassLoader; private String mLibrarySearchPaths; private String mLibraryPermittedPaths; @@ -620,8 +618,7 @@ public class GraphicsEnvironment { } /** - * Attempt to set up ANGLE from system, if the apk can be found, pass ANGLE details to - * the C++ GraphicsEnv class. + * Set up ANGLE from system. * * @param context - Context of the application. * @param bundle - Bundle of the application. @@ -630,14 +627,8 @@ public class GraphicsEnvironment { * false: can not set up to use system ANGLE because it doesn't exist. */ private boolean setupAngleFromSystem(Context context, Bundle bundle, String packageName) { - final boolean systemAngleSupported = SystemProperties - .getBoolean(PROPERTY_RO_ANGLE_SUPPORTED, false); - if (!systemAngleSupported) { - return false; - } - - // If we make it to here, system ANGLE will be used. Call nativeSetAngleInfo() with - // the application package name and ANGLE features to use. + // System ANGLE always exists, call nativeSetAngleInfo() with the application package + // name and ANGLE features to use. final String[] features = getAngleEglFeatures(context, bundle); nativeSetAngleInfo(SYSTEM_ANGLE_STRING, false, packageName, features); return true; diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java index 72fb4ae03a63..cc184828cc33 100644 --- a/core/java/android/os/Message.java +++ b/core/java/android/os/Message.java @@ -16,6 +16,7 @@ package android.os; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; @@ -436,6 +437,7 @@ public final class Message implements Parcelable { * @see #getData() * @see #setData(Bundle) */ + @Nullable public Bundle peekData() { return data; } diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index d9a9266cfddc..463be37b1253 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -83,3 +83,8 @@ per-file ArtModuleServiceManager.java = file:platform/art:/OWNERS # PerformanceHintManager per-file PerformanceHintManager.java = file:/ADPF_OWNERS + +# IThermal interfaces +per-file IThermal* = file:/THERMAL_OWNERS +per-file CoolingDevice.java = file:/THERMAL_OWNERS +per-file Temperature.java = file:/THERMAL_OWNERS diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 90a40717eada..d12e3b2431d5 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -2023,9 +2023,13 @@ public final class StrictMode { return; } + // Temporarily disable checks so that explicit GC is allowed. + final int oldMask = getThreadPolicyMask(); + setThreadPolicyMask(0); System.gc(); System.runFinalization(); System.gc(); + setThreadPolicyMask(oldMask); // Note: classInstanceLimit is immutable, so this is lock-free // Create the classes array. diff --git a/core/java/android/os/TEST_MAPPING b/core/java/android/os/TEST_MAPPING index cc5426631a7b..5c4aa4a233fc 100644 --- a/core/java/android/os/TEST_MAPPING +++ b/core/java/android/os/TEST_MAPPING @@ -52,8 +52,20 @@ ], "name": "FrameworksServicesTests", "options": [ - { "include-filter": "com.android.server.am.BatteryStatsServiceTest" }, - { "include-filter": "com.android.server.power.stats.BatteryStatsTests" } + { "include-filter": "com.android.server.am.BatteryStatsServiceTest" } + ] + }, + { + "file_patterns": [ + "BatteryStats[^/]*\\.java", + "BatteryUsageStats[^/]*\\.java", + "PowerComponents\\.java", + "[^/]*BatteryConsumer[^/]*\\.java" + ], + "name": "FrameworksServicesTests", + "options": [ + { "include-filter": "com.android.server.power.stats" }, + { "exclude-filter": "com.android.server.power.stats.BatteryStatsTests" } ] }, { diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig index 77229c44cc8d..40311535fc1e 100644 --- a/core/java/android/os/flags.aconfig +++ b/core/java/android/os/flags.aconfig @@ -1,6 +1,13 @@ package: "android.os" flag { + name: "android_os_build_vanilla_ice_cream" + namespace: "build" + description: "Feature flag for adding the VANILLA_ICE_CREAM constant." + bug: "264658905" +} + +flag { name: "state_of_health_public" namespace: "system_sw_battery" description: "Feature flag for making state_of_health a public api." diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS index e5b76f6c1c15..bf22dccce9d4 100644 --- a/core/java/android/os/storage/OWNERS +++ b/core/java/android/os/storage/OWNERS @@ -4,14 +4,16 @@ # Android Storage Team alukin@google.com -corinac@google.com +ankitavyas@google.com dipankarb@google.com +gargshivam@google.com krishang@google.com +riyaghai@google.com sahanas@google.com sergeynv@google.com +shikhamalhotra@google.com shubhisaxena@google.com tylersaunders@google.com maco@google.com nandana@google.com -narayan@google.com diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 8e72e13051b0..fa42fed75e56 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1729,23 +1729,6 @@ public class StorageManager { return RoSystemProperties.CRYPTO_FILE_ENCRYPTED; } - /** {@hide} - * @deprecated Use {@link #isFileEncrypted} instead, since emulated FBE is no longer supported. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Deprecated - public static boolean isFileEncryptedNativeOnly() { - return isFileEncrypted(); - } - - /** {@hide} - * @deprecated Use {@link #isFileEncrypted} instead, since emulated FBE is no longer supported. - */ - @Deprecated - public static boolean isFileEncryptedNativeOrEmulated() { - return isFileEncrypted(); - } - /** {@hide} */ public static boolean hasAdoptable() { switch (SystemProperties.get(PROP_ADOPTABLE)) { diff --git a/core/java/android/preference/OWNERS b/core/java/android/preference/OWNERS index 827134e8fc9d..b4cb9ec7ceda 100644 --- a/core/java/android/preference/OWNERS +++ b/core/java/android/preference/OWNERS @@ -1,3 +1,5 @@ lpf@google.com pavlis@google.com clarabayarri@google.com + +per-file SeekBarVolumizer.java = jmtrivi@google.com
\ No newline at end of file diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2f86efec7086..e5169562f076 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3445,7 +3445,6 @@ public final class Settings { public ArrayMap<String, String> getStringsForPrefix(ContentResolver cr, String prefix, List<String> names) { String namespace = prefix.substring(0, prefix.length() - 1); - Config.enforceReadPermission(namespace); ArrayMap<String, String> keyValues = new ArrayMap<>(); int currentGeneration = -1; boolean needsGenerationTracker = false; @@ -19288,21 +19287,6 @@ public final class Settings { .getApplicationContext().checkCallingOrSelfPermission(permission); } - /** - * Enforces READ_DEVICE_CONFIG permission if namespace is not one of public namespaces. - * @hide - */ - public static void enforceReadPermission(String namespace) { - if (ActivityThread.currentApplication().getApplicationContext() - .checkCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG) - != PackageManager.PERMISSION_GRANTED) { - if (!DeviceConfig.getPublicNamespaces().contains(namespace)) { - throw new SecurityException("Permission denial: reading from settings requires:" - + Manifest.permission.READ_DEVICE_CONFIG); - } - } - } - private static void setMonitorCallbackAsUser( @NonNull @CallbackExecutor Executor executor, @NonNull ContentResolver resolver, @UserIdInt int userHandle, diff --git a/core/java/android/security/OWNERS b/core/java/android/security/OWNERS index 96c0be7f803e..533d459e532b 100644 --- a/core/java/android/security/OWNERS +++ b/core/java/android/security/OWNERS @@ -8,3 +8,4 @@ per-file *NetworkSecurityPolicy.java = file:net/OWNERS per-file Confirmation*.java = file:/keystore/OWNERS per-file FileIntegrityManager.java = file:platform/system/security:/fsverity/OWNERS per-file IFileIntegrityService.aidl = file:platform/system/security:/fsverity/OWNERS +per-file *.aconfig = victorhsieh@google.com,eranm@google.com diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index 5aa309753cc4..13612f60bf4b 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -8,7 +8,14 @@ flag { } flag { - name: "fix_unlocked_device_required_keys" + name: "mgf1_digest_setter" + namespace: "hardware_backed_security" + description: "Feature flag for mgf1 digest setter in key generation and import parameters." + bug: "308378912" +} + +flag { + name: "fix_unlocked_device_required_keys_v2" namespace: "hardware_backed_security" description: "Fix bugs in behavior of UnlockedDeviceRequired keystore keys" bug: "296464083" diff --git a/core/java/android/service/notification/OWNERS b/core/java/android/service/notification/OWNERS index bb0e6aba436b..cb0b5fa6a029 100644 --- a/core/java/android/service/notification/OWNERS +++ b/core/java/android/service/notification/OWNERS @@ -2,6 +2,7 @@ juliacr@google.com yurilin@google.com +matiashe@google.com jeffdq@google.com dsandler@android.com dsandler@google.com diff --git a/core/java/android/tracing/OWNERS b/core/java/android/tracing/OWNERS index 079d4c545f25..2ebe2e9e2761 100644 --- a/core/java/android/tracing/OWNERS +++ b/core/java/android/tracing/OWNERS @@ -1,3 +1,6 @@ carmenjackson@google.com kevinjeon@google.com +pablogamito@google.com +natanieljr@google.com +keanmariotti@google.com include platform/external/perfetto:/OWNERS diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS index 42ac74ce7353..ad326e41a146 100644 --- a/core/java/android/view/OWNERS +++ b/core/java/android/view/OWNERS @@ -11,6 +11,7 @@ jjaggi@google.com roosa@google.com jreck@google.com siyamed@google.com +mount@google.com # Autofill per-file ViewStructure.java = file:/core/java/android/service/autofill/OWNERS diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 03a6a00e6af4..73d18f91f46c 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -22444,6 +22444,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Configure the {@link android.graphics.RenderEffect} to apply to the backdrop contents of this + * View. This will apply a visual effect to the result of the backdrop contents of this View + * before it is drawn. For example if + * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)} + * is provided, the previous content behind this View will be blurred before this View is drawn. + * @param renderEffect to be applied to the View. Passing null clears the previously configured + * {@link RenderEffect} + * @hide + */ + public void setBackdropRenderEffect(@Nullable RenderEffect renderEffect) { + if (mRenderNode.setBackdropRenderEffect(renderEffect)) { + invalidateViewProperty(true, true); + } + } + + /** * Updates the {@link Paint} object used with the current layer (used only if the current * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 3160057e062f..14c53489ba3a 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -1367,7 +1367,10 @@ public abstract class WebSettings { * the system default value will be used. * * <p>If the user-agent is overridden in this way, the values of the User-Agent Client Hints - * headers and {@code navigator.userAgentData} for this WebView will be empty. + * headers and {@code navigator.userAgentData} for this WebView could be changed. + * <p> See <a href="{@docRoot}reference/androidx/webkit/WebSettingsCompat + * #setUserAgentMetadata(WebSettings,UserAgentMetadata)">androidx.webkit.WebSettingsCompat + * #setUserAgentMetadata(WebSettings,UserAgentMetadata)</a> for details. * * <p>Note that starting from {@link android.os.Build.VERSION_CODES#KITKAT} Android * version, changing the user-agent while loading a web page causes WebView diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS index 7f0a651c6420..e20357fa2dd9 100644 --- a/core/java/android/widget/OWNERS +++ b/core/java/android/widget/OWNERS @@ -12,6 +12,6 @@ per-file TextView*,Edit*,Selection* = file:../text/OWNERS per-file SpellChecker.java = file:../view/inputmethod/OWNERS -per-file RemoteViews* = file:../appwidget/OWNERS +per-file Remote* = file:../appwidget/OWNERS per-file Toast.java = juliacr@google.com, jeffdq@google.com diff --git a/core/java/android/window/WindowInfosListenerForTest.java b/core/java/android/window/WindowInfosListenerForTest.java index 25bf85cfaa58..ec792197a329 100644 --- a/core/java/android/window/WindowInfosListenerForTest.java +++ b/core/java/android/window/WindowInfosListenerForTest.java @@ -21,11 +21,13 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.TestApi; import android.graphics.Rect; +import android.graphics.RectF; import android.os.IBinder; import android.os.InputConfig; import android.util.ArrayMap; import android.util.Log; import android.util.Pair; +import android.util.SparseArray; import android.view.InputWindowHandle; import java.util.ArrayList; @@ -119,13 +121,13 @@ public class WindowInfosListenerForTest { "Exception thrown while waiting for listener to be called with " + "initial state"); } - consumer.accept(buildWindowInfos(windowHandles)); + consumer.accept(buildWindowInfos(windowHandles, displayInfos)); } }; mListeners.put(consumer, listener); Pair<InputWindowHandle[], WindowInfosListener.DisplayInfo[]> initialState = listener.register(); - consumer.accept(buildWindowInfos(initialState.first)); + consumer.accept(buildWindowInfos(initialState.first, initialState.second)); calledWithInitialState.countDown(); } @@ -140,11 +142,28 @@ public class WindowInfosListenerForTest { listener.unregister(); } - private static List<WindowInfo> buildWindowInfos(InputWindowHandle[] windowHandles) { + private static List<WindowInfo> buildWindowInfos( + InputWindowHandle[] windowHandles, WindowInfosListener.DisplayInfo[] displayInfos) { var windowInfos = new ArrayList<WindowInfo>(windowHandles.length); + + var displayInfoById = new SparseArray<WindowInfosListener.DisplayInfo>(displayInfos.length); + for (var displayInfo : displayInfos) { + displayInfoById.put(displayInfo.mDisplayId, displayInfo); + } + + var tmp = new RectF(); for (var handle : windowHandles) { var bounds = new Rect(handle.frameLeft, handle.frameTop, handle.frameRight, handle.frameBottom); + + // Transform bounds from physical display coordinates to logical display coordinates. + var display = displayInfoById.get(handle.displayId); + if (display != null) { + tmp.set(bounds); + display.mTransform.mapRect(tmp); + tmp.round(bounds); + } + windowInfos.add(new WindowInfo(handle.getWindowToken(), handle.name, handle.displayId, bounds, handle.inputConfig)); } diff --git a/core/java/android/window/flags/OWNERS b/core/java/android/window/flags/OWNERS new file mode 100644 index 000000000000..fa81ee3905c3 --- /dev/null +++ b/core/java/android/window/flags/OWNERS @@ -0,0 +1 @@ +per-file responsible_apis.aconfig = file:/BAL_OWNERS
\ No newline at end of file diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java index a5e775a461a9..389576da86b7 100644 --- a/core/java/com/android/internal/app/SuspendedAppActivity.java +++ b/core/java/com/android/internal/app/SuspendedAppActivity.java @@ -80,7 +80,8 @@ public class SuspendedAppActivity extends AlertActivity // Suspension conditions were modified, dismiss any related visible dialogs. final String[] modified = intent.getStringArrayExtra( Intent.EXTRA_CHANGED_PACKAGE_LIST); - if (ArrayUtils.contains(modified, mSuspendedPackage)) { + if (ArrayUtils.contains(modified, mSuspendedPackage) + && !isPackageSuspended(mSuspendedPackage)) { if (!isFinishing()) { Slog.w(TAG, "Package " + mSuspendedPackage + " has modified" + " suspension conditions while dialog was visible. Finishing."); @@ -92,6 +93,15 @@ public class SuspendedAppActivity extends AlertActivity } }; + private boolean isPackageSuspended(String packageName) { + try { + return mPm.isPackageSuspended(packageName); + } catch (PackageManager.NameNotFoundException ne) { + Slog.e(TAG, "Package " + packageName + " not found", ne); + } + return false; + } + private CharSequence getAppLabel(String packageName) { try { return mPm.getApplicationInfoAsUser(packageName, 0, mUserId).loadLabel(mPm); diff --git a/core/java/com/android/internal/net/TEST_MAPPING b/core/java/com/android/internal/net/TEST_MAPPING new file mode 100644 index 000000000000..971ad36eecba --- /dev/null +++ b/core/java/com/android/internal/net/TEST_MAPPING @@ -0,0 +1,12 @@ +{ + "postsubmit": [ + { + "name": "FrameworksNetTests", + "options": [ + { + "exclude-annotation": "com.android.testutils.SkipPresubmit" + } + ] + } + ] +} diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java index 0947ec178c77..f62094d231ef 100644 --- a/core/java/com/android/internal/net/VpnProfile.java +++ b/core/java/com/android/internal/net/VpnProfile.java @@ -618,4 +618,14 @@ public final class VpnProfile implements Cloneable, Parcelable { public int describeContents() { return 0; } + + @Override + public VpnProfile clone() { + try { + return (VpnProfile) super.clone(); + } catch (CloneNotSupportedException e) { + Log.wtf(TAG, e); + return null; + } + } } diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java index 70514c30d90d..01c91bae72cd 100644 --- a/core/java/com/android/internal/os/ProcessCpuTracker.java +++ b/core/java/com/android/internal/os/ProcessCpuTracker.java @@ -337,6 +337,12 @@ public class ProcessCpuTracker { @UnsupportedAppUsage public void update() { + synchronized (this) { + updateLocked(); + } + } + + private void updateLocked() { if (DEBUG) Slog.v(TAG, "Update: " + this); final long nowUptime = SystemClock.uptimeMillis(); diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 965277c4635e..1c5f4f0f1369 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -868,6 +868,11 @@ public final class Zygote { args.mPkgDataInfoList, args.mAllowlistedDataInfoList, args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs); + // While `specializeAppProcess` sets the thread name on the process's main thread, this + // is distinct from the app process name which appears in stack traces, as the latter is + // sourced from the argument buffer of the Process class. Set the app process name here. + Zygote.setAppProcessName(args, TAG); + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); return ZygoteInit.zygoteInit(args.mTargetSdkVersion, diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 993e4e7b4b3d..5fe086da8c6a 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -296,7 +296,6 @@ class ZygoteConnection { } else { // child; result is a Runnable. zygoteServer.setForkChild(); - Zygote.setAppProcessName(parsedArgs, TAG); // ??? Necessary? return result; } } diff --git a/core/java/com/android/internal/pm/OWNERS b/core/java/com/android/internal/pm/OWNERS new file mode 100644 index 000000000000..6ef34e2e5d4b --- /dev/null +++ b/core/java/com/android/internal/pm/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 36137 + +file:/PACKAGE_MANAGER_OWNERS + diff --git a/core/java/com/android/internal/util/FastXmlSerializer.java b/core/java/com/android/internal/util/FastXmlSerializer.java deleted file mode 100644 index 929c9e8bb8c1..000000000000 --- a/core/java/com/android/internal/util/FastXmlSerializer.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.util; - -import android.compat.annotation.UnsupportedAppUsage; - -import org.xmlpull.v1.XmlSerializer; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CodingErrorAction; -import java.nio.charset.IllegalCharsetNameException; -import java.nio.charset.UnsupportedCharsetException; - -/** - * This is a quick and dirty implementation of XmlSerializer that isn't horribly - * painfully slow like the normal one. It only does what is needed for the - * specific XML files being written with it. - */ -public class FastXmlSerializer implements XmlSerializer { - private static final String ESCAPE_TABLE[] = new String[] { - "�", "", "", "", "", "", "", "", // 0-7 - "", "	", " ", "", "", " ", "", "", // 8-15 - "", "", "", "", "", "", "", "", // 16-23 - "", "", "", "", "", "", "", "", // 24-31 - null, null, """, null, null, null, "&", null, // 32-39 - null, null, null, null, null, null, null, null, // 40-47 - null, null, null, null, null, null, null, null, // 48-55 - null, null, null, null, "<", null, ">", null, // 56-63 - }; - - private static final int DEFAULT_BUFFER_LEN = 32*1024; - - private static String sSpace = " "; - - private final int mBufferLen; - private final char[] mText; - private int mPos; - - private Writer mWriter; - - private OutputStream mOutputStream; - private CharsetEncoder mCharset; - private ByteBuffer mBytes; - - private boolean mIndent = false; - private boolean mInTag; - - private int mNesting = 0; - private boolean mLineStart = true; - - @UnsupportedAppUsage - public FastXmlSerializer() { - this(DEFAULT_BUFFER_LEN); - } - - /** - * Allocate a FastXmlSerializer with the given internal output buffer size. If the - * size is zero or negative, then the default buffer size will be used. - * - * @param bufferSize Size in bytes of the in-memory output buffer that the writer will use. - */ - public FastXmlSerializer(int bufferSize) { - mBufferLen = (bufferSize > 0) ? bufferSize : DEFAULT_BUFFER_LEN; - mText = new char[mBufferLen]; - mBytes = ByteBuffer.allocate(mBufferLen); - } - - private void append(char c) throws IOException { - int pos = mPos; - if (pos >= (mBufferLen-1)) { - flush(); - pos = mPos; - } - mText[pos] = c; - mPos = pos+1; - } - - private void append(String str, int i, final int length) throws IOException { - if (length > mBufferLen) { - final int end = i + length; - while (i < end) { - int next = i + mBufferLen; - append(str, i, next<end ? mBufferLen : (end-i)); - i = next; - } - return; - } - int pos = mPos; - if ((pos+length) > mBufferLen) { - flush(); - pos = mPos; - } - str.getChars(i, i+length, mText, pos); - mPos = pos + length; - } - - private void append(char[] buf, int i, final int length) throws IOException { - if (length > mBufferLen) { - final int end = i + length; - while (i < end) { - int next = i + mBufferLen; - append(buf, i, next<end ? mBufferLen : (end-i)); - i = next; - } - return; - } - int pos = mPos; - if ((pos+length) > mBufferLen) { - flush(); - pos = mPos; - } - System.arraycopy(buf, i, mText, pos, length); - mPos = pos + length; - } - - private void append(String str) throws IOException { - append(str, 0, str.length()); - } - - private void appendIndent(int indent) throws IOException { - indent *= 4; - if (indent > sSpace.length()) { - indent = sSpace.length(); - } - append(sSpace, 0, indent); - } - - private void escapeAndAppendString(final String string) throws IOException { - final int N = string.length(); - final char NE = (char)ESCAPE_TABLE.length; - final String[] escapes = ESCAPE_TABLE; - int lastPos = 0; - int pos; - for (pos=0; pos<N; pos++) { - char c = string.charAt(pos); - if (c >= NE) continue; - String escape = escapes[c]; - if (escape == null) continue; - if (lastPos < pos) append(string, lastPos, pos-lastPos); - lastPos = pos + 1; - append(escape); - } - if (lastPos < pos) append(string, lastPos, pos-lastPos); - } - - private void escapeAndAppendString(char[] buf, int start, int len) throws IOException { - final char NE = (char)ESCAPE_TABLE.length; - final String[] escapes = ESCAPE_TABLE; - int end = start+len; - int lastPos = start; - int pos; - for (pos=start; pos<end; pos++) { - char c = buf[pos]; - if (c >= NE) continue; - String escape = escapes[c]; - if (escape == null) continue; - if (lastPos < pos) append(buf, lastPos, pos-lastPos); - lastPos = pos + 1; - append(escape); - } - if (lastPos < pos) append(buf, lastPos, pos-lastPos); - } - - public XmlSerializer attribute(String namespace, String name, String value) throws IOException, - IllegalArgumentException, IllegalStateException { - append(' '); - if (namespace != null) { - append(namespace); - append(':'); - } - append(name); - append("=\""); - - escapeAndAppendString(value); - append('"'); - mLineStart = false; - return this; - } - - public void cdsect(String text) throws IOException, IllegalArgumentException, - IllegalStateException { - throw new UnsupportedOperationException(); - } - - public void comment(String text) throws IOException, IllegalArgumentException, - IllegalStateException { - throw new UnsupportedOperationException(); - } - - public void docdecl(String text) throws IOException, IllegalArgumentException, - IllegalStateException { - throw new UnsupportedOperationException(); - } - - public void endDocument() throws IOException, IllegalArgumentException, IllegalStateException { - flush(); - } - - public XmlSerializer endTag(String namespace, String name) throws IOException, - IllegalArgumentException, IllegalStateException { - mNesting--; - if (mInTag) { - append(" />\n"); - } else { - if (mIndent && mLineStart) { - appendIndent(mNesting); - } - append("</"); - if (namespace != null) { - append(namespace); - append(':'); - } - append(name); - append(">\n"); - } - mLineStart = true; - mInTag = false; - return this; - } - - public void entityRef(String text) throws IOException, IllegalArgumentException, - IllegalStateException { - throw new UnsupportedOperationException(); - } - - private void flushBytes() throws IOException { - int position; - if ((position = mBytes.position()) > 0) { - mBytes.flip(); - mOutputStream.write(mBytes.array(), 0, position); - mBytes.clear(); - } - } - - public void flush() throws IOException { - //Log.i("PackageManager", "flush mPos=" + mPos); - if (mPos > 0) { - if (mOutputStream != null) { - CharBuffer charBuffer = CharBuffer.wrap(mText, 0, mPos); - CoderResult result = mCharset.encode(charBuffer, mBytes, true); - while (true) { - if (result.isError()) { - throw new IOException(result.toString()); - } else if (result.isOverflow()) { - flushBytes(); - result = mCharset.encode(charBuffer, mBytes, true); - continue; - } - break; - } - flushBytes(); - mOutputStream.flush(); - } else { - mWriter.write(mText, 0, mPos); - mWriter.flush(); - } - mPos = 0; - } - } - - public int getDepth() { - throw new UnsupportedOperationException(); - } - - public boolean getFeature(String name) { - throw new UnsupportedOperationException(); - } - - public String getName() { - throw new UnsupportedOperationException(); - } - - public String getNamespace() { - throw new UnsupportedOperationException(); - } - - public String getPrefix(String namespace, boolean generatePrefix) - throws IllegalArgumentException { - throw new UnsupportedOperationException(); - } - - public Object getProperty(String name) { - throw new UnsupportedOperationException(); - } - - public void ignorableWhitespace(String text) throws IOException, IllegalArgumentException, - IllegalStateException { - throw new UnsupportedOperationException(); - } - - public void processingInstruction(String text) throws IOException, IllegalArgumentException, - IllegalStateException { - throw new UnsupportedOperationException(); - } - - public void setFeature(String name, boolean state) throws IllegalArgumentException, - IllegalStateException { - if (name.equals("http://xmlpull.org/v1/doc/features.html#indent-output")) { - mIndent = true; - return; - } - throw new UnsupportedOperationException(); - } - - public void setOutput(OutputStream os, String encoding) throws IOException, - IllegalArgumentException, IllegalStateException { - if (os == null) - throw new IllegalArgumentException(); - if (true) { - try { - mCharset = Charset.forName(encoding).newEncoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); - } catch (IllegalCharsetNameException e) { - throw (UnsupportedEncodingException) (new UnsupportedEncodingException( - encoding).initCause(e)); - } catch (UnsupportedCharsetException e) { - throw (UnsupportedEncodingException) (new UnsupportedEncodingException( - encoding).initCause(e)); - } - mOutputStream = os; - } else { - setOutput( - encoding == null - ? new OutputStreamWriter(os) - : new OutputStreamWriter(os, encoding)); - } - } - - public void setOutput(Writer writer) throws IOException, IllegalArgumentException, - IllegalStateException { - mWriter = writer; - } - - public void setPrefix(String prefix, String namespace) throws IOException, - IllegalArgumentException, IllegalStateException { - throw new UnsupportedOperationException(); - } - - public void setProperty(String name, Object value) throws IllegalArgumentException, - IllegalStateException { - throw new UnsupportedOperationException(); - } - - public void startDocument(String encoding, Boolean standalone) throws IOException, - IllegalArgumentException, IllegalStateException { - append("<?xml version='1.0' encoding='utf-8'"); - if (standalone != null) { - append(" standalone='" + (standalone ? "yes" : "no") + "'"); - } - append(" ?>\n"); - mLineStart = true; - } - - public XmlSerializer startTag(String namespace, String name) throws IOException, - IllegalArgumentException, IllegalStateException { - if (mInTag) { - append(">\n"); - } - if (mIndent) { - appendIndent(mNesting); - } - mNesting++; - append('<'); - if (namespace != null) { - append(namespace); - append(':'); - } - append(name); - mInTag = true; - mLineStart = false; - return this; - } - - public XmlSerializer text(char[] buf, int start, int len) throws IOException, - IllegalArgumentException, IllegalStateException { - if (mInTag) { - append(">"); - mInTag = false; - } - escapeAndAppendString(buf, start, len); - if (mIndent) { - mLineStart = buf[start+len-1] == '\n'; - } - return this; - } - - public XmlSerializer text(String text) throws IOException, IllegalArgumentException, - IllegalStateException { - if (mInTag) { - append(">"); - mInTag = false; - } - escapeAndAppendString(text); - if (mIndent) { - mLineStart = text.length() > 0 && (text.charAt(text.length()-1) == '\n'); - } - return this; - } - -} diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 8d11672144b2..28fd2b488426 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -1105,10 +1105,9 @@ public class LockPatternUtils { @UnsupportedAppUsage public long setLockoutAttemptDeadline(int userId, int timeoutMs) { final long deadline = SystemClock.elapsedRealtime() + timeoutMs; - if (isSpecialUserId(userId)) { - // For secure password storage (that is required for special users such as FRP), the - // underlying storage also enforces the deadline. Since we cannot store settings - // for special users, don't. + if (userId == USER_FRP) { + // For secure password storage (that is required for FRP), the underlying storage also + // enforces the deadline. Since we cannot store settings for the FRP user, don't. return deadline; } mLockoutDeadlines.put(userId, deadline); @@ -1937,7 +1936,8 @@ public class LockPatternUtils { * If the user is not secured, ie doesn't have an LSKF, then decrypt the user's synthetic * password and use it to unlock various cryptographic keys associated with the user. This * primarily includes unlocking the user's credential-encrypted (CE) storage. It also includes - * deriving or decrypting the vendor auth secret and sending it to the AuthSecret HAL. + * unlocking the user's Keystore super keys, and deriving or decrypting the vendor auth secret + * and sending it to the AuthSecret HAL in order to unlock Secure Element firmware updates. * <p> * These tasks would normally be done when the LSKF is verified. This method is where these * tasks are done when the user doesn't have an LSKF. It's called when the user is started. diff --git a/core/java/com/android/server/net/BaseNetworkObserver.java b/core/java/com/android/server/net/BaseNetworkObserver.java index 139b88b108c5..61e017d3443f 100644 --- a/core/java/com/android/server/net/BaseNetworkObserver.java +++ b/core/java/com/android/server/net/BaseNetworkObserver.java @@ -64,7 +64,7 @@ public class BaseNetworkObserver extends INetworkManagementEventObserver.Stub { } @Override - public void interfaceClassDataActivityChanged(int transportType, boolean active, long tsNanos, + public void interfaceClassDataActivityChanged(int label, boolean active, long tsNanos, int uid) { // default no-op } diff --git a/core/java/com/android/server/pm/OWNERS b/core/java/com/android/server/pm/OWNERS new file mode 100644 index 000000000000..6ef34e2e5d4b --- /dev/null +++ b/core/java/com/android/server/pm/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 36137 + +file:/PACKAGE_MANAGER_OWNERS + diff --git a/core/jni/Android.bp b/core/jni/Android.bp index cc2d2e2aa55c..05117ce5fbff 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -457,9 +457,4 @@ cc_library_shared_for_libandroid_runtime { ], }, }, - - // Workaround Clang LTO crash. - lto: { - never: true, - }, } diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index b1dab85d2e27..f9d00edce3fa 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -212,14 +212,11 @@ static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject w return (jint) AUDIORECORD_ERROR_SETUP_INVALIDFORMAT; } - size_t bytesPerSample = audio_bytes_per_sample(format); - if (buffSizeInBytes == 0) { ALOGE("Error creating AudioRecord: frameCount is 0."); return (jint) AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT; } - size_t frameSize = channelCount * bytesPerSample; - size_t frameCount = buffSizeInBytes / frameSize; + size_t frameCount = buffSizeInBytes / audio_bytes_per_frame(channelCount, format); // create an uninitialized AudioRecord object Parcel* parcel = parcelForJavaObject(env, jAttributionSource); @@ -574,7 +571,7 @@ static jint android_media_AudioRecord_get_min_buff_size(JNIEnv *env, jobject th if (result != NO_ERROR) { return -1; } - return frameCount * channelCount * audio_bytes_per_sample(format); + return frameCount * audio_bytes_per_frame(channelCount, format); } static jboolean android_media_AudioRecord_setInputDevice( diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index edb95dd04872..43e0c34ab0f3 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -1245,7 +1245,7 @@ jboolean android_os_Process_sendSignalToProcessGroup(JNIEnv* env, jobject clazz, void android_os_Process_removeAllProcessGroups(JNIEnv* env, jobject clazz) { - return removeAllProcessGroups(); + return removeAllEmptyProcessGroups(); } static jint android_os_Process_nativePidFdOpen(JNIEnv* env, jobject, jint pid, jint flags) { diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index 0f41229dd0c1..efdfce9ba46d 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -184,11 +184,11 @@ status_t NativeInputEventReceiver::reportTimeline(int32_t inputEventId, nsecs_t void NativeInputEventReceiver::setFdEvents(int events) { if (mFdEvents != events) { mFdEvents = events; - int fd = mInputConsumer.getChannel()->getFd(); + auto&& fd = mInputConsumer.getChannel()->getFd(); if (events) { - mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr); + mMessageQueue->getLooper()->addFd(fd.get(), 0, events, this, nullptr); } else { - mMessageQueue->getLooper()->removeFd(fd); + mMessageQueue->getLooper()->removeFd(fd.get()); } } } diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp index 8d39ddfa0406..694b28beeb9e 100644 --- a/core/jni/android_view_InputEventSender.cpp +++ b/core/jni/android_view_InputEventSender.cpp @@ -101,8 +101,8 @@ NativeInputEventSender::~NativeInputEventSender() { } status_t NativeInputEventSender::initialize() { - int receiveFd = mInputPublisher.getChannel()->getFd(); - mMessageQueue->getLooper()->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, this, NULL); + auto&& receiveFd = mInputPublisher.getChannel()->getFd(); + mMessageQueue->getLooper()->addFd(receiveFd.get(), 0, ALOOPER_EVENT_INPUT, this, NULL); return OK; } @@ -111,7 +111,7 @@ void NativeInputEventSender::dispose() { ALOGD("channel '%s' ~ Disposing input event sender.", getInputChannelName().c_str()); } - mMessageQueue->getLooper()->removeFd(mInputPublisher.getChannel()->getFd()); + mMessageQueue->getLooper()->removeFd(mInputPublisher.getChannel()->getFd().get()); } status_t NativeInputEventSender::sendKeyEvent(uint32_t seq, const KeyEvent* event) { diff --git a/core/res/Android.bp b/core/res/Android.bp index b71995f899c5..6fa70d840d07 100644 --- a/core/res/Android.bp +++ b/core/res/Android.bp @@ -151,6 +151,8 @@ android_app { "simulated_device_launcher", ], }, + + generate_product_characteristics_rro: true, } java_genrule { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7d9d99113663..f7b6a7b6b81c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2225,6 +2225,13 @@ <permission android:name="android.permission.MANAGE_LOWPAN_INTERFACES" android:protectionLevel="signature|privileged" /> + <!-- @SystemApi @hide Allows changing Thread network state and access to Thread network + credentials such as Network Key and PSKc. + <p>Not for use by third-party applications. + @FlaggedApi("com.android.net.thread.flags.thread_enabled") --> + <permission android:name="android.permission.THREAD_NETWORK_PRIVILEGED" + android:protectionLevel="signature|privileged" /> + <!-- #SystemApi @hide Allows an app to bypass Private DNS. <p>Not for use by third-party applications. TODO: publish as system API in next API release. --> @@ -2271,6 +2278,7 @@ <!-- Allows system apps to call methods to register itself as a mDNS offload engine. <p>Not for use by third-party or privileged applications. @SystemApi + @FlaggedApi("com.android.net.flags.register_nsd_offload_engine") @hide This should only be used by system apps. --> <permission android:name="android.permission.REGISTER_NSD_OFFLOAD_ENGINE" diff --git a/core/res/OWNERS b/core/res/OWNERS index 0df7c2047bc1..f24c3f59155a 100644 --- a/core/res/OWNERS +++ b/core/res/OWNERS @@ -1,5 +1,6 @@ adamp@google.com asc@google.com +austindelgado@google.com cinek@google.com dsandler@android.com dsandler@google.com @@ -8,6 +9,7 @@ hackbod@android.com hackbod@google.com ilyamaty@google.com jaggies@google.com +jbolinger@google.com jsharkey@android.com jsharkey@google.com juliacr@google.com diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 6f7bc53e891c..3413282351ff 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -4303,6 +4303,9 @@ <!-- Whether the device must be screen on before routing data to this service. The default is true.--> <attr name="requireDeviceScreenOn" format="boolean"/> + <!-- Whether the device should default to observe mode when this service is + default or in the foreground. --> + <attr name="defaultToObserveMode" format="boolean"/> </declare-styleable> <!-- Use <code>offhost-apdu-service</code> as the root tag of the XML resource that @@ -4327,6 +4330,9 @@ <!-- Whether the device must be screen on before routing data to this service. The default is false.--> <attr name="requireDeviceScreenOn"/> + <!-- Whether the device should default to observe mode when this service is + default or in the foreground. --> + <attr name="defaultToObserveMode"/> </declare-styleable> <!-- Specify one or more <code>aid-group</code> elements inside a diff --git a/core/tests/GameManagerTests/src/android/app/GameManagerTests.java b/core/tests/GameManagerTests/src/android/app/GameManagerTests.java index fac3a0ecdec2..d34c91ee48ba 100644 --- a/core/tests/GameManagerTests/src/android/app/GameManagerTests.java +++ b/core/tests/GameManagerTests/src/android/app/GameManagerTests.java @@ -86,16 +86,6 @@ public final class GameManagerTests { GameModeInfo gameModeInfo = mGameManager.getGameModeInfo(mPackageName); assertNotNull(gameModeInfo); assertNull(gameModeInfo.getGameModeConfiguration(GameManager.GAME_MODE_CUSTOM)); - GameModeConfiguration unsupportedFpsConfig = - new GameModeConfiguration.Builder().setFpsOverride( - 70).setScalingFactor(0.5f).build(); - mGameManager.updateCustomGameModeConfiguration(mPackageName, unsupportedFpsConfig); - gameModeInfo = mGameManager.getGameModeInfo(mPackageName); - assertNotNull(gameModeInfo); - // TODO(b/243448953): update to non-zero FPS when matching is implemented - assertEquals(new GameModeConfiguration.Builder().setFpsOverride( - GameModeConfiguration.FPS_OVERRIDE_NONE).setScalingFactor(0.5f).build(), - gameModeInfo.getGameModeConfiguration(GameManager.GAME_MODE_CUSTOM)); GameModeConfiguration supportedFpsConfig = new GameModeConfiguration.Builder().setFpsOverride( diff --git a/core/tests/coretests/src/android/app/OWNERS b/core/tests/coretests/src/android/app/OWNERS index 64f5e6c68a95..5636f9bc436c 100644 --- a/core/tests/coretests/src/android/app/OWNERS +++ b/core/tests/coretests/src/android/app/OWNERS @@ -10,3 +10,7 @@ per-file *UiAutomation* = file:/services/accessibility/OWNERS # KeyguardManagerTest per-file KeyguardManagerTest.java = file:/services/core/java/com/android/server/locksettings/OWNERS + +# Files related to background activity launches +per-file Background*Start* = file:/BAL_OWNERS + diff --git a/core/tests/coretests/src/android/content/BrickDeniedTest.java b/core/tests/coretests/src/android/content/BrickDeniedTest.java deleted file mode 100644 index d8c9baa8df5b..000000000000 --- a/core/tests/coretests/src/android/content/BrickDeniedTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content; - -import android.test.AndroidTestCase; - -import androidx.test.filters.SmallTest; - -/** Test to make sure brick intents <b>don't</b> work without permission. */ -public class BrickDeniedTest extends AndroidTestCase { - @SmallTest - public void testBrick() { - // Try both the old and new brick intent names. Neither should work, - // since this test application doesn't have the required permission. - // If it does work, well, the test certainly won't pass. - getContext().sendBroadcast(new Intent("SHES_A_BRICK_HOUSE")); - getContext().sendBroadcast(new Intent("android.intent.action.BRICK")); - } -} diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index b05507e7e128..c1018f59ffb5 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -438,6 +438,8 @@ applications that come with the platform <permission name="android.permission.MANAGE_WIFI_NETWORK_SELECTION" /> <!-- Permission needed for CTS test - ConcurrencyTest#testP2pSetWfdInfo --> <permission name="android.permission.CONFIGURE_WIFI_DISPLAY" /> + <!-- Permission required for CTS test - CtsThreadNetworkTestCases --> + <permission name="android.permission.THREAD_NETWORK_PRIVILEGED"/> <!-- Permission required for CTS test CarrierMessagingServiceWrapperTest --> <permission name="android.permission.BIND_CARRIER_SERVICES"/> <!-- Permission required for CTS test - MusicRecognitionManagerTest --> diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java index 07f1d4a09006..8dc9579e6b52 100644 --- a/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java +++ b/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java @@ -63,7 +63,7 @@ public class HideInCommentsChecker extends BugChecker implements @Override public Description matchCompilationUnit(CompilationUnitTree tree, VisitorState state) { - final Map<Integer, Tree> javadocableTrees = findJavadocableTrees(tree); + final Map<Integer, Tree> javadocableTrees = findJavadocableTrees(tree, state); final String sourceCode = state.getSourceCode().toString(); for (ErrorProneToken token : ErrorProneTokens.getTokens(sourceCode, state.context)) { for (Tokens.Comment comment : token.comments()) { @@ -112,9 +112,9 @@ public class HideInCommentsChecker extends BugChecker implements } - private Map<Integer, Tree> findJavadocableTrees(CompilationUnitTree tree) { + private Map<Integer, Tree> findJavadocableTrees(CompilationUnitTree tree, VisitorState state) { Map<Integer, Tree> javadoccableTrees = new HashMap<>(); - new SuppressibleTreePathScanner<Void, Void>() { + new SuppressibleTreePathScanner<Void, Void>(state) { @Override public Void visitClass(ClassTree classTree, Void unused) { javadoccableTrees.put(getStartPosition(classTree), classTree); diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java index 2ec4524e1241..d659ddd75f72 100644 --- a/graphics/java/android/graphics/BaseRecordingCanvas.java +++ b/graphics/java/android/graphics/BaseRecordingCanvas.java @@ -402,8 +402,8 @@ public class BaseRecordingCanvas extends Canvas { } @Override - public final void drawDoubleRoundRect(@NonNull RectF outer, float[] outerRadii, - @NonNull RectF inner, float[] innerRadii, @NonNull Paint paint) { + public final void drawDoubleRoundRect(@NonNull RectF outer, @NonNull float[] outerRadii, + @NonNull RectF inner, @NonNull float[] innerRadii, @NonNull Paint paint) { nDrawDoubleRoundRect(mNativeCanvasWrapper, outer.left, outer.top, outer.right, outer.bottom, outerRadii, inner.left, inner.top, inner.right, inner.bottom, innerRadii, diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index 2e91c240d71b..15d26ebe66f6 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -971,6 +971,23 @@ public final class RenderNode { } /** + * Configure the {@link android.graphics.RenderEffect} to apply to the backdrop contents of + * this RenderNode. This will apply a visual effect to the result of the backdrop contents + * of this RenderNode before the RenderNode is drawn into the destination. For example if + * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)} + * is provided, the previous content behind this RenderNode will be blurred before the + * RenderNode is drawn in to the destination. + * @param renderEffect to be applied to the backdrop contents of this RenderNode. Passing + * null clears all previously configured RenderEffects + * @return True if the value changed, false if the new value was the same as the previous value. + * @hide + */ + public boolean setBackdropRenderEffect(@Nullable RenderEffect renderEffect) { + return nSetBackdropRenderEffect(mNativeRenderNode, + renderEffect != null ? renderEffect.getNativeInstance() : 0); + } + + /** * Returns the translucency level of this display list. * * @return A value between 0.0f and 1.0f @@ -1797,6 +1814,9 @@ public final class RenderNode { private static native boolean nSetRenderEffect(long renderNode, long renderEffect); @CriticalNative + private static native boolean nSetBackdropRenderEffect(long renderNode, long renderEffect); + + @CriticalNative private static native boolean nSetHasOverlappingRendering(long renderNode, boolean hasOverlappingRendering); diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java index b7ea04fdfe07..2beb434566e5 100644 --- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java +++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java @@ -51,7 +51,7 @@ public class AndroidKeyStoreMaintenance { * @return 0 if successful or a {@code ResponseCode} * @hide */ - public static int onUserAdded(@NonNull int userId) { + public static int onUserAdded(int userId) { StrictMode.noteDiskWrite(); try { getService().onUserAdded(userId); @@ -66,6 +66,30 @@ public class AndroidKeyStoreMaintenance { } /** + * Tells Keystore to create a user's super keys and store them encrypted by the given secret. + * + * @param userId - Android user id of the user + * @param password - a secret derived from the user's synthetic password + * @param allowExisting - true if the keys already existing should not be considered an error + * @return 0 if successful or a {@code ResponseCode} + * @hide + */ + public static int initUserSuperKeys(int userId, @NonNull byte[] password, + boolean allowExisting) { + StrictMode.noteDiskWrite(); + try { + getService().initUserSuperKeys(userId, password, allowExisting); + return 0; + } catch (ServiceSpecificException e) { + Log.e(TAG, "initUserSuperKeys failed", e); + return e.errorCode; + } catch (Exception e) { + Log.e(TAG, "Can not connect to keystore", e); + return SYSTEM_ERROR; + } + } + + /** * Informs Keystore 2.0 about removing a user * * @param userId - Android user id of the user being removed @@ -110,6 +134,28 @@ public class AndroidKeyStoreMaintenance { } /** + * Tells Keystore that a user's LSKF is being removed, ie the user's lock screen is changing to + * Swipe or None. Keystore uses this notification to delete the user's auth-bound keys. + * + * @param userId - Android user id of the user + * @return 0 if successful or a {@code ResponseCode} + * @hide + */ + public static int onUserLskfRemoved(int userId) { + StrictMode.noteDiskWrite(); + try { + getService().onUserLskfRemoved(userId); + return 0; + } catch (ServiceSpecificException e) { + Log.e(TAG, "onUserLskfRemoved failed", e); + return e.errorCode; + } catch (Exception e) { + Log.e(TAG, "Can not connect to keystore", e); + return SYSTEM_ERROR; + } + } + + /** * Informs Keystore 2.0 that an app was uninstalled and the corresponding namespace is to * be cleared. */ diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java index 2d2dd24763c4..4ec5e1b67c5d 100644 --- a/keystore/java/android/security/Authorization.java +++ b/keystore/java/android/security/Authorization.java @@ -18,13 +18,14 @@ package android.security; import android.annotation.NonNull; import android.annotation.Nullable; +import android.hardware.biometrics.BiometricConstants; import android.hardware.security.keymint.HardwareAuthToken; +import android.hardware.security.keymint.HardwareAuthenticatorType; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.StrictMode; import android.security.authorization.IKeystoreAuthorization; -import android.security.authorization.LockScreenEvent; import android.system.keystore2.ResponseCode; import android.util.Log; @@ -37,7 +38,10 @@ public class Authorization { public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR; - private static IKeystoreAuthorization getService() { + /** + * @return an instance of IKeystoreAuthorization + */ + public static IKeystoreAuthorization getService() { return IKeystoreAuthorization.Stub.asInterface( ServiceManager.checkService("android.security.authorization")); } @@ -71,26 +75,37 @@ public class Authorization { } /** - * Informs keystore2 about lock screen event. + * Tells Keystore that the device is now unlocked for a user. * - * @param locked - whether it is a lock (true) or unlock (false) event - * @param syntheticPassword - if it is an unlock event with the password, pass the synthetic - * password provided by the LockSettingService - * @param unlockingSids - KeyMint secure user IDs that should be permitted to unlock - * UNLOCKED_DEVICE_REQUIRED keys. + * @param userId - the user's Android user ID + * @param password - a secret derived from the user's synthetic password, if the unlock method + * is LSKF (or equivalent) and thus has made the synthetic password available + * @return 0 if successful or a {@code ResponseCode}. + */ + public static int onDeviceUnlocked(int userId, @Nullable byte[] password) { + StrictMode.noteDiskWrite(); + try { + getService().onDeviceUnlocked(userId, password); + return 0; + } catch (RemoteException | NullPointerException e) { + Log.w(TAG, "Can not connect to keystore", e); + return SYSTEM_ERROR; + } catch (ServiceSpecificException e) { + return e.errorCode; + } + } + + /** + * Tells Keystore that the device is now locked for a user. * + * @param userId - the user's Android user ID + * @param unlockingSids - list of biometric SIDs with which the device may be unlocked again * @return 0 if successful or a {@code ResponseCode}. */ - public static int onLockScreenEvent(@NonNull boolean locked, @NonNull int userId, - @Nullable byte[] syntheticPassword, @Nullable long[] unlockingSids) { + public static int onDeviceLocked(int userId, @NonNull long[] unlockingSids) { StrictMode.noteDiskWrite(); try { - if (locked) { - getService().onLockScreenEvent(LockScreenEvent.LOCK, userId, null, unlockingSids); - } else { - getService().onLockScreenEvent( - LockScreenEvent.UNLOCK, userId, syntheticPassword, unlockingSids); - } + getService().onDeviceLocked(userId, unlockingSids); return 0; } catch (RemoteException | NullPointerException e) { Log.w(TAG, "Can not connect to keystore", e); @@ -100,4 +115,24 @@ public class Authorization { } } + /** + * Gets the last authentication time of the given user and authenticators. + * + * @param userId user id + * @param authenticatorTypes an array of {@link HardwareAuthenticatorType}. + * @return the last authentication time or + * {@link BiometricConstants#BIOMETRIC_NO_AUTHENTICATION}. + */ + public static long getLastAuthenticationTime( + long userId, @HardwareAuthenticatorType int[] authenticatorTypes) { + try { + return getService().getLastAuthTime(userId, authenticatorTypes); + } catch (RemoteException | NullPointerException e) { + Log.w(TAG, "Can not connect to keystore", e); + return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION; + } catch (ServiceSpecificException e) { + return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION; + } + } + } diff --git a/keystore/java/android/security/GateKeeper.java b/keystore/java/android/security/GateKeeper.java index af188a95c929..464714fe2895 100644 --- a/keystore/java/android/security/GateKeeper.java +++ b/keystore/java/android/security/GateKeeper.java @@ -45,8 +45,19 @@ public abstract class GateKeeper { @UnsupportedAppUsage public static long getSecureUserId() throws IllegalStateException { + return getSecureUserId(UserHandle.myUserId()); + } + + /** + * Return the secure user id for a given user id + * @param userId the user id, e.g. 0 + * @return the secure user id or {@link GateKeeper#INVALID_SECURE_USER_ID} if no such mapping + * for the given user id is found. + * @throws IllegalStateException if there is an error retrieving the secure user id + */ + public static long getSecureUserId(int userId) throws IllegalStateException { try { - return getService().getSecureUserId(UserHandle.myUserId()); + return getService().getSecureUserId(userId); } catch (RemoteException e) { throw new IllegalStateException( "Failed to obtain secure user ID from gatekeeper", e); diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java index 5e16bcee1a0e..dd703f5eefb9 100644 --- a/keystore/java/android/security/KeyStore2.java +++ b/keystore/java/android/security/KeyStore2.java @@ -33,7 +33,6 @@ import android.system.keystore2.ResponseCode; import android.util.Log; import java.util.Calendar; -import java.util.Objects; /** * @hide This should not be made public in its present form because it @@ -139,13 +138,25 @@ public class KeyStore2 { return new KeyStore2(); } + /** + * Gets the {@link IKeystoreService} that should be started in early_hal in Android. + * + * @throws IllegalStateException if the KeystoreService is not available or has not + * been initialized when called. This is a state that should not happen and indicates + * and error somewhere in the stack or with the calling processes access permissions. + */ @NonNull private synchronized IKeystoreService getService(boolean retryLookup) { if (mBinder == null || retryLookup) { mBinder = IKeystoreService.Stub.asInterface(ServiceManager - .getService(KEYSTORE2_SERVICE_NAME)); - Binder.allowBlocking(mBinder.asBinder()); + .getService(KEYSTORE2_SERVICE_NAME)); + } + if (mBinder == null) { + throw new IllegalStateException( + "Could not connect to Keystore service. Keystore may have crashed or not been" + + " initialized"); } - return Objects.requireNonNull(mBinder); + Binder.allowBlocking(mBinder.asBinder()); + return mBinder; } void delete(KeyDescriptor descriptor) throws KeyStoreException { diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index 1ba41b106f56..4982f3732089 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -618,7 +618,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * @see #isMgf1DigestsSpecified() */ @NonNull - @FlaggedApi("MGF1_DIGEST_SETTER") + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) public @KeyProperties.DigestEnum Set<String> getMgf1Digests() { if (mMgf1Digests.isEmpty()) { throw new IllegalStateException("Mask generation function (MGF) not specified"); @@ -633,7 +633,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * @see #getMgf1Digests() */ @NonNull - @FlaggedApi("MGF1_DIGEST_SETTER") + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) public boolean isMgf1DigestsSpecified() { return !mMgf1Digests.isEmpty(); } @@ -1282,15 +1282,18 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * function (MGF1) with a digest. * The default digest for MGF1 is {@code SHA-1}, which will be specified during key creation * time if no digests have been explicitly provided. - * When using the key, the caller may not specify any digests that were not provided during - * key creation time. The caller may specify the default digest, {@code SHA-1}, if no + * {@code null} may not be specified as a parameter to this method: It is not possible to + * disable MGF1 digest, a default must be present for when the caller tries to use it. + * + * <p>When using the key, the caller may not specify any digests that were not provided + * during key creation time. The caller may specify the default digest, {@code SHA-1}, if no * digests were explicitly provided during key creation (but it is not necessary to do so). * * <p>See {@link KeyProperties}.{@code DIGEST} constants. */ @NonNull - @FlaggedApi("MGF1_DIGEST_SETTER") - public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) { + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) + public Builder setMgf1Digests(@NonNull @KeyProperties.DigestEnum String... mgf1Digests) { mMgf1Digests = Set.of(mgf1Digests); return this; } @@ -1596,6 +1599,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * {@link #getAttestationChallenge()} returns non-null and the spec is used to generate a * symmetric (AES or HMAC) key, {@link javax.crypto.KeyGenerator#generateKey()} will throw * {@link java.security.InvalidAlgorithmParameterException}. + * + * <p>The challenge may be up to 128 bytes. */ @NonNull public Builder setAttestationChallenge(byte[] attestationChallenge) { diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index c1e3bab5d37c..7b6b2d142f95 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -401,7 +401,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * @see #isMgf1DigestsSpecified() */ @NonNull - @FlaggedApi("MGF1_DIGEST_SETTER") + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) public @KeyProperties.DigestEnum Set<String> getMgf1Digests() { if (mMgf1Digests.isEmpty()) { throw new IllegalStateException("Mask generation function (MGF) not specified"); @@ -416,7 +416,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * @see #getMgf1Digests() */ @NonNull - @FlaggedApi("MGF1_DIGEST_SETTER") + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) public boolean isMgf1DigestsSpecified() { return !mMgf1Digests.isEmpty(); } @@ -799,7 +799,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { * <p>See {@link KeyProperties}.{@code DIGEST} constants. */ @NonNull - @FlaggedApi("MGF1_DIGEST_SETTER") + @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER) public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) { mMgf1Digests = Set.of(mgf1Digests); return this; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index ed4b485f3927..9c05a3a768a0 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -28,6 +28,7 @@ import android.hardware.security.keymint.SecurityLevel; import android.hardware.security.keymint.Tag; import android.os.Build; import android.os.StrictMode; +import android.security.Flags; import android.security.KeyPairGeneratorSpec; import android.security.KeyStore2; import android.security.KeyStoreException; @@ -853,6 +854,22 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mgf1Digest )); }); + + /* If the MGF1 Digest setter is not set, fall back to the previous behaviour: + * Add, as MGF1 Digest function, all the primary digests. + * Avoid adding the default MGF1 digest as it will have been included in the + * mKeymasterMgf1Digests field. + */ + if (!getMgf1DigestSetterFlag()) { + final int defaultMgf1Digest = KeyProperties.Digest.toKeymaster( + DEFAULT_MGF1_DIGEST); + ArrayUtils.forEach(mKeymasterDigests, (digest) -> { + if (digest != defaultMgf1Digest) { + params.add(KeyStore2ParameterUtils.makeEnum( + KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, digest)); + } + }); + } } }); ArrayUtils.forEach(mKeymasterSignaturePaddings, (padding) -> { @@ -928,6 +945,16 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato return params; } + private static boolean getMgf1DigestSetterFlag() { + try { + return Flags.mgf1DigestSetter(); + } catch (SecurityException e) { + Log.w(TAG, "Cannot read MGF1 Digest setter flag value", e); + return false; + } + } + + private void addAlgorithmSpecificParameters(List<KeyParameter> params) { switch (mKeymasterAlgorithm) { case KeymasterDefs.KM_ALGORITHM_RSA: diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index ddbd93e458fd..2d8c5a380c6b 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -25,6 +25,7 @@ import android.hardware.security.keymint.HardwareAuthenticatorType; import android.hardware.security.keymint.KeyParameter; import android.hardware.security.keymint.SecurityLevel; import android.os.StrictMode; +import android.security.Flags; import android.security.GateKeeper; import android.security.KeyStore2; import android.security.KeyStoreParameter; @@ -256,6 +257,15 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { } } + private static boolean getMgf1DigestSetterFlag() { + try { + return Flags.mgf1DigestSetter(); + } catch (SecurityException e) { + Log.w(NAME, "Cannot read MGF1 Digest setter flag value", e); + return false; + } + } + @Override public Date engineGetCreationDate(String alias) { KeyEntryResponse response = getKeyMetadata(alias); @@ -537,11 +547,31 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { /* Because of default MGF1 digest is SHA-1. It has to be added in Key * characteristics. Otherwise, crypto operations will fail with Incompatible * MGF1 digest. + * If the MGF1 Digest setter flag isn't set, then the condition in the + * if clause above must be false (cannot have MGF1 digests specified if the + * flag was off). In that case, in addition to adding the default MGF1 + * digest, we have to add all the other digests as MGF1 Digests. + * */ importArgs.add(KeyStore2ParameterUtils.makeEnum( KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST) )); + if (!getMgf1DigestSetterFlag()) { + final int defaultMgf1Digest = KeyProperties.Digest.toKeymaster( + DEFAULT_MGF1_DIGEST); + for (String digest : spec.getDigests()) { + int digestToAddAsMgf1Digest = KeyProperties.Digest.toKeymaster( + digest); + // Do not add the default MGF1 digest as it has been added above. + if (digestToAddAsMgf1Digest != defaultMgf1Digest) { + importArgs.add(KeyStore2ParameterUtils.makeEnum( + KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, + digestToAddAsMgf1Digest + )); + } + } + } } } } diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index db581471e2ca..b5e6f94af022 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -514,6 +514,7 @@ cc_defaults { "canvas/CanvasOpRasterizer.cpp", "effects/StretchEffect.cpp", "effects/GainmapRenderer.cpp", + "pipeline/skia/BackdropFilterDrawable.cpp", "pipeline/skia/HolePunch.cpp", "pipeline/skia/SkiaDisplayList.cpp", "pipeline/skia/SkiaRecordingCanvas.cpp", diff --git a/libs/hwui/Mesh.cpp b/libs/hwui/Mesh.cpp index e59bc9565a59..37a7d74330e9 100644 --- a/libs/hwui/Mesh.cpp +++ b/libs/hwui/Mesh.cpp @@ -90,8 +90,8 @@ std::tuple<bool, SkString> Mesh::validate() { FAIL_MESH_VALIDATE("%s mode requires at least %zu vertices but vertex count is %zu.", modeToStr(meshMode), min_vcount_for_mode(meshMode), mVertexCount); } - SkASSERT(!fICount); - SkASSERT(!fIOffset); + LOG_ALWAYS_FATAL_IF(mIndexCount != 0); + LOG_ALWAYS_FATAL_IF(mIndexOffset != 0); } if (!sm.ok()) { diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 06aed63d8def..09d3f05935b9 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -35,7 +35,7 @@ namespace uirenderer { #ifndef __ANDROID__ // Layoutlib does not compile HWUIProperties.sysprop as it depends on cutils properties std::optional<bool> use_vulkan() { - return base::GetBoolProperty("ro.hwui.use_vulkan", false); + return base::GetBoolProperty("ro.hwui.use_vulkan", true); } std::optional<std::int32_t> render_ahead() { diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 1c39db3a31bb..1dd22cf43c5c 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -260,6 +260,12 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu pushStagingDisplayListChanges(observer, info); } + // always damageSelf when filtering backdrop content, or else the BackdropFilterDrawable will + // get a wrong snapshot of previous content. + if (mProperties.layerProperties().getBackdropImageFilter()) { + damageSelf(info); + } + if (mDisplayList) { info.out.hasFunctors |= mDisplayList.hasFunctor(); mHasHolePunches = mDisplayList.hasHolePunches(); diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp index 0589f136b666..c5371236b9cf 100644 --- a/libs/hwui/RenderProperties.cpp +++ b/libs/hwui/RenderProperties.cpp @@ -55,6 +55,12 @@ bool LayerProperties::setImageFilter(SkImageFilter* imageFilter) { return true; } +bool LayerProperties::setBackdropImageFilter(SkImageFilter* imageFilter) { + if (mBackdropImageFilter.get() == imageFilter) return false; + mBackdropImageFilter = sk_ref_sp(imageFilter); + return true; +} + bool LayerProperties::setFromPaint(const SkPaint* paint) { bool changed = false; changed |= setAlpha(static_cast<uint8_t>(PaintUtils::getAlphaDirect(paint))); @@ -70,6 +76,7 @@ LayerProperties& LayerProperties::operator=(const LayerProperties& other) { setXferMode(other.xferMode()); setColorFilter(other.getColorFilter()); setImageFilter(other.getImageFilter()); + setBackdropImageFilter(other.getBackdropImageFilter()); mStretchEffect = other.mStretchEffect; return *this; } diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index 064ba7aee107..e358b57f6fe1 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -97,8 +97,12 @@ public: bool setImageFilter(SkImageFilter* imageFilter); + bool setBackdropImageFilter(SkImageFilter* imageFilter); + SkImageFilter* getImageFilter() const { return mImageFilter.get(); } + SkImageFilter* getBackdropImageFilter() const { return mBackdropImageFilter.get(); } + const StretchEffect& getStretchEffect() const { return mStretchEffect; } StretchEffect& mutableStretchEffect() { return mStretchEffect; } @@ -129,6 +133,7 @@ private: SkBlendMode mMode; sk_sp<SkColorFilter> mColorFilter; sk_sp<SkImageFilter> mImageFilter; + sk_sp<SkImageFilter> mBackdropImageFilter; StretchEffect mStretchEffect; }; diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 8394c3cd4175..ea9b6c90a65f 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -588,10 +588,40 @@ void SkiaCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Pain // Canvas draw operations: Bitmaps // ---------------------------------------------------------------------------- +bool SkiaCanvas::useGainmapShader(Bitmap& bitmap) { + // If the bitmap doesn't have a gainmap, don't use the gainmap shader + if (!bitmap.hasGainmap()) return false; + + // If we don't have an owned canvas, then we're either hardware accelerated or drawing + // to a picture - use the gainmap shader out of caution. Ideally a picture canvas would + // use a drawable here instead to defer making that decision until the last possible + // moment + if (!mCanvasOwned) return true; + + auto info = mCanvasOwned->imageInfo(); + + // If it's an unknown colortype then it's not a bitmap-backed canvas + if (info.colorType() == SkColorType::kUnknown_SkColorType) return true; + + skcms_TransferFunction tfn; + info.colorSpace()->transferFn(&tfn); + + auto transferType = skcms_TransferFunction_getType(&tfn); + switch (transferType) { + case skcms_TFType_HLGish: + case skcms_TFType_HLGinvish: + case skcms_TFType_PQish: + return true; + case skcms_TFType_Invalid: + case skcms_TFType_sRGBish: + return false; + } +} + void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) { auto image = bitmap.makeImage(); - if (bitmap.hasGainmap()) { + if (useGainmapShader(bitmap)) { Paint gainmapPaint = paint ? *paint : Paint(); sk_sp<SkShader> gainmapShader = uirenderer::MakeGainmapShader( image, bitmap.gainmap()->bitmap->makeImage(), bitmap.gainmap()->info, @@ -618,7 +648,7 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float s SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); - if (bitmap.hasGainmap()) { + if (useGainmapShader(bitmap)) { Paint gainmapPaint = paint ? *paint : Paint(); sk_sp<SkShader> gainmapShader = uirenderer::MakeGainmapShader( image, bitmap.gainmap()->bitmap->makeImage(), bitmap.gainmap()->info, diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index b785989f35cb..9cb50ed5b081 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -223,6 +223,8 @@ private: void drawPoints(const float* points, int count, const Paint& paint, SkCanvas::PointMode mode); + bool useGainmapShader(Bitmap& bitmap); + class Clip; std::unique_ptr<SkCanvas> mCanvasOwned; // Might own a canvas we allocated. diff --git a/libs/hwui/jni/YuvToJpegEncoder.cpp b/libs/hwui/jni/YuvToJpegEncoder.cpp index 69418b09fee6..729890638931 100644 --- a/libs/hwui/jni/YuvToJpegEncoder.cpp +++ b/libs/hwui/jni/YuvToJpegEncoder.cpp @@ -5,6 +5,7 @@ #include "SkStream.h" #include "YuvToJpegEncoder.h" #include <ui/PixelFormat.h> +#include <utils/Errors.h> #include <hardware/hardware.h> #include "graphics_jni_helpers.h" @@ -298,7 +299,7 @@ void Yuv422IToJpegEncoder::configSamplingFactors(jpeg_compress_struct* cinfo) { } /////////////////////////////////////////////////////////////////////////////// -using namespace android::ultrahdr; +using namespace ultrahdr; ultrahdr_color_gamut P010Yuv420ToJpegREncoder::findColorGamut(JNIEnv* env, int aDataSpace) { switch (aDataSpace & ADataSpace::STANDARD_MASK) { diff --git a/libs/hwui/jni/YuvToJpegEncoder.h b/libs/hwui/jni/YuvToJpegEncoder.h index 8ef780547184..0e711efc2a73 100644 --- a/libs/hwui/jni/YuvToJpegEncoder.h +++ b/libs/hwui/jni/YuvToJpegEncoder.h @@ -103,7 +103,7 @@ public: * @param aDataSpace data space defined in data_space.h. * @return color gamut for JPEG/R. */ - static android::ultrahdr::ultrahdr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace); + static ultrahdr::ultrahdr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace); /** Map data space (defined in DataSpace.java and data_space.h) to the transfer function * used in JPEG/R @@ -112,8 +112,8 @@ public: * @param aDataSpace data space defined in data_space.h. * @return color gamut for JPEG/R. */ - static android::ultrahdr::ultrahdr_transfer_function findHdrTransferFunction( - JNIEnv* env, int aDataSpace); + static ultrahdr::ultrahdr_transfer_function findHdrTransferFunction(JNIEnv* env, + int aDataSpace); }; #endif // _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_ diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp index 8c7b9a4b5e94..2a218a25913d 100644 --- a/libs/hwui/jni/android_graphics_RenderNode.cpp +++ b/libs/hwui/jni/android_graphics_RenderNode.cpp @@ -243,6 +243,13 @@ static jboolean android_view_RenderNode_setRenderEffect(CRITICAL_JNI_PARAMS_COMM return SET_AND_DIRTY(mutateLayerProperties().setImageFilter, imageFilter, RenderNode::GENERIC); } +static jboolean android_view_RenderNode_setBackdropRenderEffect( + CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong renderEffectPtr) { + SkImageFilter* imageFilter = reinterpret_cast<SkImageFilter*>(renderEffectPtr); + return SET_AND_DIRTY(mutateLayerProperties().setBackdropImageFilter, imageFilter, + RenderNode::GENERIC); +} + static jboolean android_view_RenderNode_setHasOverlappingRendering(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, bool hasOverlappingRendering) { return SET_AND_DIRTY(setHasOverlappingRendering, hasOverlappingRendering, @@ -792,6 +799,8 @@ static const JNINativeMethod gMethods[] = { {"nSetAlpha", "(JF)Z", (void*)android_view_RenderNode_setAlpha}, {"nSetRenderEffect", "(JJ)Z", (void*)android_view_RenderNode_setRenderEffect}, + {"nSetBackdropRenderEffect", "(JJ)Z", + (void*)android_view_RenderNode_setBackdropRenderEffect}, {"nSetHasOverlappingRendering", "(JZ)Z", (void*)android_view_RenderNode_setHasOverlappingRendering}, {"nSetUsageHint", "(JI)V", (void*)android_view_RenderNode_setUsageHint}, diff --git a/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp b/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp new file mode 100644 index 000000000000..ffad69993fd8 --- /dev/null +++ b/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BackdropFilterDrawable.h" + +#include <SkImage.h> +#include <SkSurface.h> + +#include "RenderNode.h" +#include "RenderNodeDrawable.h" + +namespace android { +namespace uirenderer { +namespace skiapipeline { + +BackdropFilterDrawable::~BackdropFilterDrawable() {} + +bool BackdropFilterDrawable::prepareToDraw(SkCanvas* canvas, const RenderProperties& properties, + int backdropImageWidth, int backdropImageHeight) { + // the drawing bounds for blurred content. + mDstBounds.setWH(properties.getWidth(), properties.getHeight()); + + float alphaMultiplier = 1.0f; + RenderNodeDrawable::setViewProperties(properties, canvas, &alphaMultiplier, true); + + // get proper subset for previous content. + canvas->getTotalMatrix().mapRect(&mImageSubset, mDstBounds); + SkRect imageSubset(mImageSubset); + // ensure the subset is inside bounds of previous content. + if (!mImageSubset.intersect(SkRect::MakeWH(backdropImageWidth, backdropImageHeight))) { + return false; + } + + // correct the drawing bounds if subset was changed. + if (mImageSubset != imageSubset) { + SkMatrix inverse; + if (canvas->getTotalMatrix().invert(&inverse)) { + inverse.mapRect(&mDstBounds, mImageSubset); + } + } + + // follow the alpha from the target RenderNode. + mPaint.setAlpha(properties.layerProperties().alpha() * alphaMultiplier); + return true; +} + +void BackdropFilterDrawable::onDraw(SkCanvas* canvas) { + const RenderProperties& properties = mTargetRenderNode->properties(); + auto* backdropFilter = properties.layerProperties().getBackdropImageFilter(); + auto* surface = canvas->getSurface(); + if (!backdropFilter || !surface) { + return; + } + + auto backdropImage = surface->makeImageSnapshot(); + // sync necessary properties from target RenderNode. + if (!prepareToDraw(canvas, properties, backdropImage->width(), backdropImage->height())) { + return; + } + + auto imageSubset = mImageSubset.roundOut(); + backdropImage = + backdropImage->makeWithFilter(canvas->recordingContext(), backdropFilter, imageSubset, + imageSubset, &mOutSubset, &mOutOffset); + canvas->drawImageRect(backdropImage, SkRect::Make(mOutSubset), mDstBounds, + SkSamplingOptions(SkFilterMode::kLinear), &mPaint, + SkCanvas::kStrict_SrcRectConstraint); +} + +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/BackdropFilterDrawable.h b/libs/hwui/pipeline/skia/BackdropFilterDrawable.h new file mode 100644 index 000000000000..9e35837675ae --- /dev/null +++ b/libs/hwui/pipeline/skia/BackdropFilterDrawable.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <SkCanvas.h> +#include <SkDrawable.h> +#include <SkPaint.h> + +namespace android { +namespace uirenderer { + +class RenderNode; +class RenderProperties; + +namespace skiapipeline { + +/** + * This drawable captures it's backdrop content and render it with a + * image filter. + */ +class BackdropFilterDrawable : public SkDrawable { +public: + BackdropFilterDrawable(RenderNode* renderNode, SkCanvas* canvas) + : mTargetRenderNode(renderNode), mBounds(canvas->getLocalClipBounds()) {} + + ~BackdropFilterDrawable(); + +private: + RenderNode* mTargetRenderNode; + SkPaint mPaint; + + SkRect mDstBounds; + SkRect mImageSubset; + SkIRect mOutSubset; + SkIPoint mOutOffset; + + /** + * Check all necessary properties before actual drawing. + * Return true if ready to draw. + */ + bool prepareToDraw(SkCanvas* canvas, const RenderProperties& properties, int backdropImageWidth, + int backdropImageHeight); + +protected: + void onDraw(SkCanvas* canvas) override; + + virtual SkRect onGetBounds() override { return mBounds; } + const SkRect mBounds; +}; + +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index da4f66d45a70..9d72c2315198 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -362,7 +362,7 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { } void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, SkCanvas* canvas, - float* alphaMultiplier) { + float* alphaMultiplier, bool ignoreLayer) { if (properties.getLeft() != 0 || properties.getTop() != 0) { canvas->translate(properties.getLeft(), properties.getTop()); } @@ -378,7 +378,8 @@ void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, S canvas->concat(*properties.getTransformMatrix()); } } - if (Properties::getStretchEffectBehavior() == StretchEffectBehavior::UniformScale) { + if (Properties::getStretchEffectBehavior() == StretchEffectBehavior::UniformScale && + !ignoreLayer) { const StretchEffect& stretch = properties.layerProperties().getStretchEffect(); if (!stretch.isEmpty()) { canvas->concat( @@ -388,10 +389,10 @@ void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, S const bool isLayer = properties.effectiveLayerType() != LayerType::None; int clipFlags = properties.getClippingFlags(); if (properties.getAlpha() < 1) { - if (isLayer) { + if (isLayer && !ignoreLayer) { clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer } - if (CC_LIKELY(isLayer || !properties.getHasOverlappingRendering())) { + if (CC_LIKELY(isLayer || !properties.getHasOverlappingRendering()) || ignoreLayer) { *alphaMultiplier = properties.getAlpha(); } else { // savelayer needed to create an offscreen buffer diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.h b/libs/hwui/pipeline/skia/RenderNodeDrawable.h index c7582e734009..818ac45bf346 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.h +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.h @@ -120,7 +120,7 @@ private: * Applies the rendering properties of a view onto a SkCanvas. */ static void setViewProperties(const RenderProperties& properties, SkCanvas* canvas, - float* alphaMultiplier); + float* alphaMultiplier, bool ignoreLayer = false); /** * Stores transform on the canvas at time of recording and is used for @@ -149,6 +149,11 @@ private: * display list that is searched for any render nodes with getProjectBackwards==true */ SkiaDisplayList* mProjectedDisplayList = nullptr; + + /** + * Allow BackdropFilterDrawable to apply same render properties onto SkCanvas. + */ + friend class BackdropFilterDrawable; }; } // namespace skiapipeline diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 3ca7eeb37a89..58c14c1fabbd 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -37,6 +37,7 @@ #include "NinePatchUtils.h" #include "RenderNode.h" #include "pipeline/skia/AnimatedDrawables.h" +#include "pipeline/skia/BackdropFilterDrawable.h" #ifdef __ANDROID__ // Layoutlib does not support GL, Vulcan etc. #include "pipeline/skia/GLFunctorDrawable.h" #include "pipeline/skia/VkFunctorDrawable.h" @@ -168,6 +169,14 @@ void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) { // Put Vulkan WebViews with non-rectangular clips in a HW layer renderNode->mutateStagingProperties().setClipMayBeComplex(mRecorder.isClipMayBeComplex()); } + + // draw backdrop filter drawable if needed. + if (renderNode->stagingProperties().layerProperties().getBackdropImageFilter()) { + auto* backdropFilterDrawable = + mDisplayList->allocateDrawable<BackdropFilterDrawable>(renderNode, asSkCanvas()); + drawDrawable(backdropFilterDrawable); + } + drawDrawable(&renderNodeDrawable); // use staging property, since recording on UI thread diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 504dfaa2a1f5..cedfaed3260a 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -919,6 +919,7 @@ void CanvasContext::buildLayer(RenderNode* node) { // buildLayer() will leave the tree in an unknown state, so we must stop drawing stopDrawing(); + ScopedActiveContext activeContext(this); TreeInfo info(TreeInfo::MODE_FULL, *this); info.damageAccumulator = &mDamageAccumulator; info.layerUpdateQueue = &mLayerUpdateQueue; diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp index 596bd37e4cf5..f67042b21f8f 100644 --- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp +++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp @@ -20,14 +20,17 @@ #include <SkBlendMode.h> #include <SkClipStack.h> #include <SkSurface_Base.h> +#include <include/effects/SkImageFilters.h> #include <string.h> + #include "AnimationContext.h" #include "DamageAccumulator.h" #include "FatalTestCanvas.h" #include "IContextFactory.h" -#include "hwui/Paint.h" #include "RecordingCanvas.h" #include "SkiaCanvas.h" +#include "hwui/Paint.h" +#include "pipeline/skia/BackdropFilterDrawable.h" #include "pipeline/skia/SkiaDisplayList.h" #include "pipeline/skia/SkiaOpenGLPipeline.h" #include "pipeline/skia/SkiaPipeline.h" @@ -1210,3 +1213,77 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaRecordingCanvas, drawVectorDrawable) { canvas.drawDrawable(&drawable); EXPECT_EQ(2, canvas.mDrawCounter); } + +// Verify drawing logics for BackdropFilterDrawable +RENDERTHREAD_TEST(BackdropFilterDrawable, drawing) { + static const int CANVAS_WIDTH = 100; + static const int CANVAS_HEIGHT = 200; + class SimpleTestCanvas : public TestCanvasBase { + public: + SkRect mDstBounds; + SimpleTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {} + void onDrawRect(const SkRect& rect, const SkPaint& paint) override { + // did nothing. + } + + // called when BackdropFilterDrawable is drawn. + void onDrawImageRect2(const SkImage*, const SkRect& src, const SkRect& dst, + const SkSamplingOptions&, const SkPaint*, + SrcRectConstraint) override { + mDrawCounter++; + mDstBounds = dst; + } + }; + class SimpleLayer : public SkSurface_Base { + public: + SimpleLayer() + : SkSurface_Base(SkImageInfo::MakeN32Premul(CANVAS_WIDTH, CANVAS_HEIGHT), nullptr) { + } + virtual sk_sp<SkImage> onNewImageSnapshot(const SkIRect* bounds) override { + SkBitmap bitmap; + bitmap.allocN32Pixels(CANVAS_WIDTH, CANVAS_HEIGHT); + bitmap.setImmutable(); + return SkImage::MakeFromBitmap(bitmap); + } + SkCanvas* onNewCanvas() override { return new SimpleTestCanvas(); } + sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; } + bool onCopyOnWrite(ContentChangeMode) override { return true; } + void onWritePixels(const SkPixmap&, int x, int y) {} + }; + + auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, + [](RenderProperties& props, SkiaRecordingCanvas& canvas) { + canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, + Paint()); + }); + + sk_sp<SkSurface> surface(new SimpleLayer()); + auto* canvas = reinterpret_cast<SimpleTestCanvas*>(surface->getCanvas()); + RenderNodeDrawable drawable(node.get(), canvas, true); + BackdropFilterDrawable backdropDrawable(node.get(), canvas); + canvas->drawDrawable(&drawable); + canvas->drawDrawable(&backdropDrawable); + // no backdrop filter, skip drawing. + EXPECT_EQ(0, canvas->mDrawCounter); + + sk_sp<SkImageFilter> filter(SkImageFilters::Blur(3, 3, nullptr)); + node->animatorProperties().mutateLayerProperties().setBackdropImageFilter(filter.get()); + canvas->drawDrawable(&drawable); + canvas->drawDrawable(&backdropDrawable); + // backdrop filter is set, ok to draw. + EXPECT_EQ(1, canvas->mDrawCounter); + EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), canvas->mDstBounds); + + canvas->translate(30, 30); + canvas->drawDrawable(&drawable); + canvas->drawDrawable(&backdropDrawable); + // the drawable is still visible, ok to draw. + EXPECT_EQ(2, canvas->mDrawCounter); + EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH - 30, CANVAS_HEIGHT - 30), canvas->mDstBounds); + + canvas->translate(CANVAS_WIDTH, CANVAS_HEIGHT); + canvas->drawDrawable(&drawable); + canvas->drawDrawable(&backdropDrawable); + // the drawable is invisible, skip drawing. + EXPECT_EQ(2, canvas->mDrawCounter); +} diff --git a/media/Android.bp b/media/Android.bp index f69dd3cc3206..349340804f1e 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -23,6 +23,10 @@ aidl_interface { name: "soundtrigger_middleware-aidl", unstable: true, local_include_dir: "aidl", + defaults: [ + "latest_android_media_audio_common_types_import_interface", + "latest_android_media_soundtrigger_types_import_interface", + ], backend: { java: { sdk_version: "module_current", @@ -32,8 +36,6 @@ aidl_interface { "aidl/android/media/soundtrigger_middleware/*.aidl", ], imports: [ - "android.media.audio.common.types-V2", - "android.media.soundtrigger.types-V1", "media_permission-aidl", ], } diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 7faa13c80c62..447d3bbddceb 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -1176,6 +1176,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, case AudioFormat.ENCODING_PCM_FLOAT: case AudioFormat.ENCODING_PCM_16BIT: case AudioFormat.ENCODING_PCM_8BIT: + case AudioFormat.ENCODING_E_AC3_JOC: mAudioFormat = audioFormat; break; default: @@ -1188,20 +1189,12 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, // Convenience method for the contructor's audio buffer size check. - // preconditions: - // mChannelCount is valid - // mAudioFormat is AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT, - // or AudioFormat.ENCODING_PCM_FLOAT // postcondition: // mNativeBufferSizeInBytes is valid (multiple of frame size, positive) private void audioBuffSizeCheck(int audioBufferSize) throws IllegalArgumentException { - // NB: this section is only valid with PCM data. - // To update when supporting compressed formats - int frameSizeInBytes = mChannelCount - * (AudioFormat.getBytesPerSample(mAudioFormat)); - if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) { + if ((audioBufferSize % getFormat().getFrameSizeInBytes() != 0) || (audioBufferSize < 1)) { throw new IllegalArgumentException("Invalid audio buffer size " + audioBufferSize - + " (frame size " + frameSizeInBytes + ")"); + + " (frame size " + getFormat().getFrameSizeInBytes() + ")"); } mNativeBufferSizeInBytes = audioBufferSize; diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java index 0a0a6263686a..ab7c27f70e05 100644 --- a/media/java/android/media/MediaCas.java +++ b/media/java/android/media/MediaCas.java @@ -272,7 +272,7 @@ public final class MediaCas implements AutoCloseable { Log.d(TAG, "Trying to get AIDL service"); IMediaCasService serviceAidl = IMediaCasService.Stub.asInterface( - ServiceManager.getService( + ServiceManager.waitForDeclaredService( IMediaCasService.DESCRIPTOR + "/default")); if (serviceAidl != null) { return serviceAidl; diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 29e8716f08ac..cda919f14bc6 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -442,6 +442,7 @@ public final class MediaSession { * but it must be released if your activity or service is being destroyed. */ public void release() { + setCallback(null); try { mBinder.destroySession(); } catch (RemoteException e) { diff --git a/media/jni/Android.bp b/media/jni/Android.bp index ed1072cf409f..94fce797f5d6 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -81,6 +81,7 @@ cc_library_shared { "libhidlallocatorutils", "libhidlbase", "libsonivox", + "server_configurable_flags", "android.hardware.cas@1.0", "android.hardware.cas.native@1.0", "android.hardware.drm@1.3", @@ -99,6 +100,7 @@ cc_library_shared { static_libs: [ "libgrallocusage", "libmedia_midiiowrapper", + "android.media.playback.flags-aconfig-cc", ], include_dirs: [ @@ -120,11 +122,6 @@ cc_library_shared { "-Wunused", "-Wunreachable-code", ], - - // Workaround Clang LTO crash. - lto: { - never: true, - }, } cc_library_shared { diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp index 14587589372b..2a10fa7957bf 100644 --- a/media/jni/android_media_MediaMetadataRetriever.cpp +++ b/media/jni/android_media_MediaMetadataRetriever.cpp @@ -35,7 +35,9 @@ #include "android_media_MediaDataSource.h" #include "android_media_Streams.h" #include "android_util_Binder.h" +#include <com_android_media_playback_flags.h> +namespace playback_flags = com::android::media::playback::flags; using namespace android; struct fields_t { @@ -374,9 +376,12 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime( jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); return NULL; } - // For getFrameAtTime family of calls, default to ANDROID_BITMAP_FORMAT_RGB_565 - // to keep the behavior consistent with older releases - AndroidBitmapFormat colorFormat = getColorFormat(env, params, ANDROID_BITMAP_FORMAT_RGB_565); + + AndroidBitmapFormat defaultColorFormat = + playback_flags::mediametadataretriever_default_rgba8888() + ? ANDROID_BITMAP_FORMAT_RGBA_8888 + : ANDROID_BITMAP_FORMAT_RGB_565; + AndroidBitmapFormat colorFormat = getColorFormat(env, params, defaultColorFormat); // Call native method to retrieve a video frame VideoFrame *videoFrame = NULL; diff --git a/media/jni/audioeffect/Android.bp b/media/jni/audioeffect/Android.bp index 8b5b726fd2db..cf5059ceb3c9 100644 --- a/media/jni/audioeffect/Android.bp +++ b/media/jni/audioeffect/Android.bp @@ -44,9 +44,4 @@ cc_library_shared { "-Wunreachable-code", "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION", ], - - // Workaround Clang LTO crash. - lto: { - never: true, - }, } diff --git a/media/jni/playback_flags.aconfig b/media/jni/playback_flags.aconfig new file mode 100644 index 000000000000..2bb0ec5375fd --- /dev/null +++ b/media/jni/playback_flags.aconfig @@ -0,0 +1,8 @@ +package: "com.android.media.playback.flags" + +flag { + name: "mediametadataretriever_default_rgba8888" + namespace: "media_solutions" + description: "Change MediaMetadataRetriever to use RGBA8888 for bitmap handling by default." + bug: "298965955" +} diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp index bdd7afeb2f65..7a329bccf940 100644 --- a/media/tests/MediaFrameworkTest/Android.bp +++ b/media/tests/MediaFrameworkTest/Android.bp @@ -20,6 +20,8 @@ android_test { "androidx.test.ext.junit", "androidx.test.rules", "android-ex-camera2", + "android.media.playback.flags-aconfig-java", + "flag-junit", "testables", "testng", "truth", diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java index f70d2d1f8ae7..e3d389737bb0 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java @@ -16,19 +16,27 @@ package com.android.mediaframeworktest.unit; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import android.graphics.Bitmap; import android.media.MediaMetadataRetriever; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.util.Log; import androidx.test.runner.AndroidJUnit4; +import com.android.media.playback.flags.Flags; import com.android.mediaframeworktest.MediaNames; import com.android.mediaframeworktest.MediaProfileReader; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -40,6 +48,9 @@ public class MediaMetadataRetrieverTest { private static final String TAG = "MediaMetadataRetrieverTest"; + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + // Test album art extraction. @MediumTest @Test @@ -284,6 +295,34 @@ public class MediaMetadataRetrieverTest { assertTrue(!hasFailed); } + /** Test the thumbnail is generated when the default is set to RGBA8888 */ + @MediumTest + // TODO(b/305160754) Remove the following annotation and use SetFlagsRule.enableFlags + @RequiresFlagsEnabled(Flags.FLAG_MEDIAMETADATARETRIEVER_DEFAULT_RGBA8888) + @Test + public void testGetFrameAtTimeWithRGBA8888Flag_Set() throws IOException { + try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) { + retriever.setDataSource(MediaNames.TEST_PATH_1); + Bitmap bitmap = retriever.getFrameAtTime(-1); + assertNotNull(bitmap); + assertEquals(Bitmap.Config.ARGB_8888, bitmap.getConfig()); + } + } + + /** Test the thumbnail is generated when the default is not set to RGBA8888 */ + @MediumTest + // TODO(b/305160754) Remove the following annotation and use SetFlagsRule.disableFlags + @RequiresFlagsDisabled(Flags.FLAG_MEDIAMETADATARETRIEVER_DEFAULT_RGBA8888) + @Test + public void testGetFrameAtTimeWithRGBA8888Flag_Unset() throws IOException { + try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) { + retriever.setDataSource(MediaNames.TEST_PATH_1); + Bitmap bitmap = retriever.getFrameAtTime(-1); + assertNotNull(bitmap); + assertEquals(Bitmap.Config.RGB_565, bitmap.getConfig()); + } + } + // TODO: // Encode and test for the correct mix of metadata elements on a per-file basis? // We should be able to compare the actual returned metadata with the expected metadata diff --git a/mime/java-res/android.mime.types b/mime/java-res/android.mime.types index cb74cfc89cbe..fbdfe3e35b87 100644 --- a/mime/java-res/android.mime.types +++ b/mime/java-res/android.mime.types @@ -54,6 +54,8 @@ ?application/ttml+xml ttml dfxp ?application/vnd.android.ota ota ?application/vnd.apple.mpegurl m3u8 +?application/vnd.apple.pkpass pkpass +?application/vnd.apple.pkpasses pkpasses ?application/vnd.ms-pki.stl stl ?application/vnd.ms-powerpoint pot ?application/vnd.ms-wpl wpl diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp index fe3132e3d2a3..ceab164aa324 100644 --- a/native/android/system_fonts.cpp +++ b/native/android/system_fonts.cpp @@ -21,22 +21,20 @@ #include <android/font.h> #include <android/font_matcher.h> #include <android/system_fonts.h> - -#include <memory> -#include <string> -#include <vector> - #include <errno.h> #include <fcntl.h> -#include <libxml/tree.h> -#include <log/log.h> -#include <sys/stat.h> -#include <unistd.h> - #include <hwui/MinikinSkia.h> +#include <libxml/parser.h> +#include <log/log.h> #include <minikin/FontCollection.h> #include <minikin/LocaleList.h> #include <minikin/SystemFonts.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <memory> +#include <string> +#include <vector> struct XmlCharDeleter { void operator()(xmlChar* b) { xmlFree(b); } diff --git a/nfc/Android.bp b/nfc/Android.bp new file mode 100644 index 000000000000..bf9f47ceb0a7 --- /dev/null +++ b/nfc/Android.bp @@ -0,0 +1,51 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +filegroup { + name: "framework-nfc-non-updatable-sources", + path: "java", + srcs: [], +} + +filegroup { + name: "framework-nfc-updatable-sources", + path: "java", + srcs: [ + "java/**/*.java", + "java/**/*.aidl", + ], + exclude_srcs: [ + ":framework-nfc-non-updatable-sources", + ], +} + +java_sdk_library { + name: "framework-nfc", + libs: [ + "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage + ], + srcs: [ + ":framework-nfc-updatable-sources", + ], + defaults: ["framework-non-updatable-unbundled-defaults"], + permitted_packages: [ + "android.nfc", + "com.android.nfc", + ], + hidden_api_packages: [ + "com.android.nfc", + ], + aidl: { + include_dirs: [ + // TODO (b/303286040): Remove these when we change to |framework-module-defaults| + "frameworks/base/nfc/java", + "frameworks/base/core/java", + ], + }, +} diff --git a/nfc/OWNERS b/nfc/OWNERS new file mode 100644 index 000000000000..35e9713f5715 --- /dev/null +++ b/nfc/OWNERS @@ -0,0 +1,2 @@ +# Bug component: 48448 +include platform/packages/apps/Nfc:/OWNERS diff --git a/nfc/TEST_MAPPING b/nfc/TEST_MAPPING new file mode 100644 index 000000000000..5b5ea3790010 --- /dev/null +++ b/nfc/TEST_MAPPING @@ -0,0 +1,10 @@ +{ + "presubmit": [ + { + "name": "NfcManagerTests" + }, + { + "name": "CtsNfcTestCases" + } + ] +} diff --git a/nfc/api/current.txt b/nfc/api/current.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/module-lib-current.txt b/nfc/api/module-lib-current.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/module-lib-current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/module-lib-removed.txt b/nfc/api/module-lib-removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/module-lib-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/removed.txt b/nfc/api/removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/system-current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/system-removed.txt b/nfc/api/system-removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/system-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/test-current.txt b/nfc/api/test-current.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/test-current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/test-removed.txt b/nfc/api/test-removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/test-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/java/android/nfc/Placeholder.java b/nfc/java/android/nfc/Placeholder.java new file mode 100644 index 000000000000..3509644ac106 --- /dev/null +++ b/nfc/java/android/nfc/Placeholder.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.nfc; + +/** + * Placeholder class so new framework-nfc module isn't empty, will be removed once module is + * populated. + * + * @hide + * + */ +public class Placeholder { +} diff --git a/packages/CrashRecovery/OWNERS b/packages/CrashRecovery/OWNERS new file mode 100644 index 000000000000..daa02111f71f --- /dev/null +++ b/packages/CrashRecovery/OWNERS @@ -0,0 +1,3 @@ +ancr@google.com +harshitmahajan@google.com +robertogil@google.com diff --git a/packages/CrashRecovery/framework/Android.bp b/packages/CrashRecovery/framework/Android.bp new file mode 100644 index 000000000000..b2af315ef2c9 --- /dev/null +++ b/packages/CrashRecovery/framework/Android.bp @@ -0,0 +1,9 @@ +filegroup { + name: "framework-crashrecovery-sources", + srcs: [ + "java/**/*.java", + "java/**/*.aidl", + ], + path: "java", + visibility: ["//frameworks/base:__subpackages__"], +} diff --git a/core/java/android/service/watchdog/ExplicitHealthCheckService.java b/packages/CrashRecovery/framework/java/android/service/watchdog/ExplicitHealthCheckService.java index 7befbfb0f370..7befbfb0f370 100644 --- a/core/java/android/service/watchdog/ExplicitHealthCheckService.java +++ b/packages/CrashRecovery/framework/java/android/service/watchdog/ExplicitHealthCheckService.java diff --git a/core/java/android/service/watchdog/IExplicitHealthCheckService.aidl b/packages/CrashRecovery/framework/java/android/service/watchdog/IExplicitHealthCheckService.aidl index 78c0328d36f0..90965092ac2b 100644 --- a/core/java/android/service/watchdog/IExplicitHealthCheckService.aidl +++ b/packages/CrashRecovery/framework/java/android/service/watchdog/IExplicitHealthCheckService.aidl @@ -21,6 +21,7 @@ import android.os.RemoteCallback; /** * @hide */ +@PermissionManuallyEnforced oneway interface IExplicitHealthCheckService { void setCallback(in @nullable RemoteCallback callback); diff --git a/core/java/android/service/watchdog/OWNERS b/packages/CrashRecovery/framework/java/android/service/watchdog/OWNERS index 1c045e10c0ec..1c045e10c0ec 100644 --- a/core/java/android/service/watchdog/OWNERS +++ b/packages/CrashRecovery/framework/java/android/service/watchdog/OWNERS diff --git a/core/java/android/service/watchdog/PackageConfig.aidl b/packages/CrashRecovery/framework/java/android/service/watchdog/PackageConfig.aidl index 013158676f79..013158676f79 100644 --- a/core/java/android/service/watchdog/PackageConfig.aidl +++ b/packages/CrashRecovery/framework/java/android/service/watchdog/PackageConfig.aidl diff --git a/packages/CrashRecovery/services/Android.bp b/packages/CrashRecovery/services/Android.bp new file mode 100644 index 000000000000..27ddff93247e --- /dev/null +++ b/packages/CrashRecovery/services/Android.bp @@ -0,0 +1,9 @@ +filegroup { + name: "services-crashrecovery-sources", + srcs: [ + "java/**/*.java", + "java/**/*.aidl", + ], + path: "java", + visibility: ["//frameworks/base:__subpackages__"], +} diff --git a/services/core/java/com/android/server/ExplicitHealthCheckController.java b/packages/CrashRecovery/services/java/com/android/server/ExplicitHealthCheckController.java index 3d610d3747c9..3d610d3747c9 100644 --- a/services/core/java/com/android/server/ExplicitHealthCheckController.java +++ b/packages/CrashRecovery/services/java/com/android/server/ExplicitHealthCheckController.java diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java index d256aead97e8..d256aead97e8 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java diff --git a/services/core/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java index eb65b2a9eedd..eb65b2a9eedd 100644 --- a/services/core/java/com/android/server/RescueParty.java +++ b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java index 2007079ea5ca..2007079ea5ca 100644 --- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +++ b/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java diff --git a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java b/packages/CrashRecovery/services/java/com/android/server/rollback/WatchdogRollbackLogger.java index f9ef994a523a..f9ef994a523a 100644 --- a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java +++ b/packages/CrashRecovery/services/java/com/android/server/rollback/WatchdogRollbackLogger.java diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java index 1088acef0fb0..4992ef1e1c00 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java @@ -290,7 +290,14 @@ public class InstallInstalling extends AlertActivity { broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); - session.commit(pendingIntent.getIntentSender()); + try { + session.commit(pendingIntent.getIntentSender()); + } catch (Exception e) { + Log.e(LOG_TAG, "Cannot install package: ", e); + launchFailure(PackageInstaller.STATUS_FAILURE, + PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null); + return; + } mCancelButton.setEnabled(false); setFinishOnTouchOutside(false); } else { diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index ed5654d4f259..ec50323dd91d 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -2432,9 +2432,7 @@ class DatabaseHelper extends SQLiteOpenHelper { R.bool.def_auto_time_zone); // Sync timezone to NITZ loadSetting(stmt, Settings.Global.STAY_ON_WHILE_PLUGGED_IN, - ("1".equals(SystemProperties.get("ro.boot.qemu")) - || res.getBoolean(R.bool.def_stay_on_while_plugged_in)) - ? 1 : 0); + res.getBoolean(R.bool.def_stay_on_while_plugged_in) ? 1 : 0); loadIntegerSetting(stmt, Settings.Global.WIFI_SLEEP_POLICY, R.integer.def_wifi_sleep_policy); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 215a040c6a72..3299a37d90da 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -1149,8 +1149,6 @@ public class SettingsProvider extends ContentProvider { Slog.v(LOG_TAG, "getConfigSetting(" + name + ")"); } - Settings.Config.enforceReadPermission(/*namespace=*/name.split("/")[0]); - // Get the value. synchronized (mLock) { return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_CONFIG, @@ -1330,9 +1328,6 @@ public class SettingsProvider extends ContentProvider { Slog.v(LOG_TAG, "getAllConfigFlags() for " + prefix); } - Settings.Config.enforceReadPermission( - prefix != null ? prefix.split("/")[0] : null); - synchronized (mLock) { // Get the settings. SettingsState settingsState = mSettingsRegistry.getSettingsLocked( diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index ee9883b0b0af..1edb89c82065 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -588,6 +588,9 @@ <!-- Permission needed for CTS test - ConcurrencyTest#testP2pSetWfdInfo --> <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" /> + <!-- Permission required for CTS test - CtsThreadNetworkTestCases --> + <uses-permission android:name="android.permission.THREAD_NETWORK_PRIVILEGED"/> + <!-- Permission required for CTS tests to enable/disable rate limiting toasts. --> <uses-permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING" /> diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index 34545cf190f3..967a36b38090 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -27,6 +27,8 @@ cameronyee@google.com chandruis@google.com chrisgollner@google.com cinek@google.com +cocod@google.com +darrellshi@google.com dupin@google.com ethibodeau@google.com evanlaird@google.com @@ -80,6 +82,7 @@ petrcermak@google.com pinyaoting@google.com pixel@google.com pomini@google.com +princedonkor@google.com rahulbanerjee@google.com roosa@google.com saff@google.com @@ -102,6 +105,7 @@ vanjan@google.com victortulias@google.com winsonc@google.com wleshner@google.com +wxyz@google.com xilei@google.com xuqiu@google.com yeinj@google.com diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java index 63b4288ce055..e0ce3db39403 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java @@ -27,7 +27,7 @@ import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_S import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; -import android.os.SystemProperties; +import android.os.Build; import android.provider.Settings; import android.util.Log; @@ -87,7 +87,7 @@ public class ClipboardListener implements String clipSource = mClipboardManager.getPrimaryClipSource(); ClipData clipData = mClipboardManager.getPrimaryClip(); - if (shouldSuppressOverlay(clipData, clipSource, isEmulator())) { + if (shouldSuppressOverlay(clipData, clipSource, Build.IS_EMULATOR)) { Log.i(TAG, "Clipboard overlay suppressed."); return; } @@ -141,10 +141,6 @@ public class ClipboardListener implements return true; } - private static boolean isEmulator() { - return SystemProperties.getBoolean("ro.boot.qemu", false); - } - private boolean isUserSetupComplete() { return Settings.Secure.getInt(mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1; diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java index 67e96645f9c5..27e6895af612 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java @@ -165,6 +165,9 @@ public class PeopleTileViewHelper { + "\\p{Emoji}(\\p{EMod}|\\x{FE0F}\\x{20E3}?|[\\x{E0020}-\\x{E007E}]+\\x{E007F})" + "?)*"; + // Not all JDKs support emoji patterns, including the one errorprone runs under, which + // makes it think that this is an invalid pattern. + @SuppressWarnings("InvalidPatternSyntax") private static final Pattern EMOJI_PATTERN = Pattern.compile(UNICODE_EMOJI_REGEX); public static final String EMPTY_STRING = ""; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java index 6875b523a962..ea140cb99d19 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java @@ -24,6 +24,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.TypedArray; import android.graphics.Rect; +import android.icu.lang.UCharacter; import android.icu.text.DateTimePatternGenerator; import android.os.Bundle; import android.os.Handler; @@ -452,7 +453,7 @@ public class Clock extends TextView implements if (a >= 0) { // Move a back so any whitespace before AM/PM is also in the alternate size. final int b = a; - while (a > 0 && Character.isWhitespace(format.charAt(a-1))) { + while (a > 0 && UCharacter.isUWhiteSpace(format.charAt(a - 1))) { a--; } format = format.substring(0, a) + MAGIC1 + format.substring(a, b) diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java index 941cd7783ed0..900805f818d3 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java @@ -25,6 +25,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.debug.IAdbManager; import android.hardware.usb.UsbManager; +import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.ServiceManager; @@ -69,8 +70,7 @@ public class UsbDebuggingActivity extends AlertActivity super.onCreate(icicle); // Emulator does not support reseating the usb cable to reshow the dialog. - boolean isEmulator = SystemProperties.get("ro.boot.qemu").equals("1"); - if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0 && !isEmulator) { + if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0 && !Build.IS_EMULATOR) { mDisconnectedReceiver = new UsbDisconnectedReceiver(this); IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE); mBroadcastDispatcher.registerReceiver(mDisconnectedReceiver, filter); diff --git a/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java index 1866a9983495..67c2caa338a6 100644 --- a/rs/java/android/renderscript/ScriptC.java +++ b/rs/java/android/renderscript/ScriptC.java @@ -16,9 +16,12 @@ package android.renderscript; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.content.res.Resources; +import android.util.Slog; -import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -35,6 +38,15 @@ public class ScriptC extends Script { private static final String TAG = "ScriptC"; /** + * In targetSdkVersion 35 and above, Renderscript's ScriptC stops being supported + * and an exception is thrown when the class is instantiated. + * In targetSdkVersion 34 and below, Renderscript's ScriptC still works. + */ + @ChangeId + @EnabledAfter(targetSdkVersion = 35) + private static final long RENDERSCRIPT_SCRIPTC_DEPRECATION_CHANGE_ID = 297019750L; + + /** * Only intended for use by the generated derived classes. * * @param id @@ -89,7 +101,19 @@ public class ScriptC extends Script { setID(id); } + private static void throwExceptionIfSDKTooHigh() { + String message = + "ScriptC scripts are not supported when targeting an API Level >= 35. Please refer " + + "to https://developer.android.com/guide/topics/renderscript/migration-guide " + + "for proposed alternatives."; + Slog.w(TAG, message); + if (CompatChanges.isChangeEnabled(RENDERSCRIPT_SCRIPTC_DEPRECATION_CHANGE_ID)) { + throw new UnsupportedOperationException(message); + } + } + private static synchronized long internalCreate(RenderScript rs, Resources resources, int resourceID) { + throwExceptionIfSDKTooHigh(); byte[] pgm; int pgmLength; InputStream is = resources.openRawResource(resourceID); @@ -126,6 +150,7 @@ public class ScriptC extends Script { private static synchronized long internalStringCreate(RenderScript rs, String resName, byte[] bitcode) { // Log.v(TAG, "Create script for resource = " + resName); + throwExceptionIfSDKTooHigh(); return rs.nScriptCCreate(resName, RenderScript.getCachePath(), bitcode, bitcode.length); } } diff --git a/services/Android.bp b/services/Android.bp index 3a0428e0a9f8..e4fe581dc6bf 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -43,7 +43,10 @@ soong_config_module_type { name: "system_optimized_java_defaults", module_type: "java_defaults", config_namespace: "ANDROID", - bool_variables: ["SYSTEM_OPTIMIZE_JAVA"], + bool_variables: [ + "SYSTEM_OPTIMIZE_JAVA", + "FULL_SYSTEM_OPTIMIZE_JAVA", + ], properties: ["optimize"], } @@ -55,9 +58,11 @@ system_optimized_java_defaults { enabled: true, // TODO(b/210510433): Enable optimizations after improving // retracing infra. + // See also FULL_SYSTEM_OPTIMIZE_JAVA. optimize: false, shrink: true, ignore_warnings: false, + proguard_compatibility: false, proguard_flags_files: [ "proguard.flags", // Ensure classes referenced in the framework-res manifest @@ -77,6 +82,12 @@ system_optimized_java_defaults { }, }, }, + // Allow form factors to opt-in full system java optimization + FULL_SYSTEM_OPTIMIZE_JAVA: { + optimize: { + optimize: true, + }, + }, }, } diff --git a/services/companion/java/com/android/server/companion/virtual/OWNERS b/services/companion/java/com/android/server/companion/virtual/OWNERS index 83143a431406..4fe0592f9075 100644 --- a/services/companion/java/com/android/server/companion/virtual/OWNERS +++ b/services/companion/java/com/android/server/companion/virtual/OWNERS @@ -1,6 +1,8 @@ +# Bug component: 1171888 + set noparent -ogunwale@google.com -michaelwr@google.com +marvinramin@google.com vladokom@google.com -marvinramin@google.com
\ No newline at end of file +ogunwale@google.com +michaelwr@google.com
\ No newline at end of file diff --git a/services/core/Android.bp b/services/core/Android.bp index 22f85703f428..37976b58a4e0 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -122,6 +122,9 @@ java_library_static { "java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/wm/EventLogTags.logtags", "java/com/android/server/policy/EventLogTags.logtags", + + // Java/AIDL sources to be moved out to CrashRecovery module + ":services-crashrecovery-sources", ], libs: [ @@ -130,7 +133,6 @@ java_library_static { "android.hardware.light-V2.0-java", "android.hardware.gnss-V2-java", "android.hardware.vibrator-V2-java", - "android.nfc.flags-aconfig-java", "app-compat-annotations", "framework-tethering.stubs.module_lib", "service-art.stubs.system_server", @@ -153,7 +155,7 @@ java_library_static { "android.hardware.boot-V1.0-java", // HIDL "android.hardware.boot-V1.1-java", // HIDL "android.hardware.boot-V1.2-java", // HIDL - "android.hardware.boot-V1-java", // AIDL + "android.hardware.boot-V1-java", // AIDL "android.hardware.broadcastradio-V2.0-java", // HIDL "android.hardware.broadcastradio-V1-java", // AIDL "android.hardware.health-V1.0-java", // HIDL diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java index 572e9c2a5d82..926d7a4d3ea6 100644 --- a/services/core/java/com/android/server/BootReceiver.java +++ b/services/core/java/com/android/server/BootReceiver.java @@ -62,6 +62,7 @@ import java.nio.file.Files; import java.nio.file.attribute.PosixFilePermissions; import java.util.HashMap; import java.util.Iterator; +import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -328,9 +329,11 @@ public class BootReceiver extends BroadcastReceiver { * @param tombstone path to the tombstone * @param proto whether the tombstone is stored as proto * @param processName the name of the process corresponding to the tombstone + * @param tmpFileLock the lock for reading/writing tmp files */ public static void addTombstoneToDropBox( - Context ctx, File tombstone, boolean proto, String processName) { + Context ctx, File tombstone, boolean proto, String processName, + ReentrantLock tmpFileLock) { final DropBoxManager db = ctx.getSystemService(DropBoxManager.class); if (db == null) { Slog.e(TAG, "Can't log tombstone: DropBoxManager not available"); @@ -351,39 +354,11 @@ public class BootReceiver extends BroadcastReceiver { // due to rate limiting. Do this by enclosing the proto tombsstone in a // container proto that has the dropped entry count and the proto tombstone as // bytes (to avoid the complexity of reading and writing nested protos). - - // Read the proto tombstone file as bytes. - final byte[] tombstoneBytes = Files.readAllBytes(tombstone.toPath()); - - final File tombstoneProtoWithHeaders = File.createTempFile( - tombstone.getName(), ".tmp", TOMBSTONE_TMP_DIR); - Files.setPosixFilePermissions( - tombstoneProtoWithHeaders.toPath(), - PosixFilePermissions.fromString("rw-rw----")); - - // Write the new proto container proto with headers. - ParcelFileDescriptor pfd; + tmpFileLock.lock(); try { - pfd = ParcelFileDescriptor.open(tombstoneProtoWithHeaders, MODE_READ_WRITE); - - ProtoOutputStream protoStream = new ProtoOutputStream( - pfd.getFileDescriptor()); - protoStream.write(TombstoneWithHeadersProto.TOMBSTONE, tombstoneBytes); - protoStream.write( - TombstoneWithHeadersProto.DROPPED_COUNT, - rateLimitResult.droppedCountSinceRateLimitActivated()); - protoStream.flush(); - - // Add the proto to dropbox. - db.addFile(TAG_TOMBSTONE_PROTO_WITH_HEADERS, tombstoneProtoWithHeaders, 0); - } catch (FileNotFoundException ex) { - Slog.e(TAG, "failed to open for write: " + tombstoneProtoWithHeaders, ex); - throw ex; + addAugmentedProtoToDropbox(tombstone, db, rateLimitResult); } finally { - // Remove the temporary file. - if (tombstoneProtoWithHeaders != null) { - tombstoneProtoWithHeaders.delete(); - } + tmpFileLock.unlock(); } } } else { @@ -399,6 +374,44 @@ public class BootReceiver extends BroadcastReceiver { writeTimestamps(timestamps); } + private static void addAugmentedProtoToDropbox( + File tombstone, DropBoxManager db, + DropboxRateLimiter.RateLimitResult rateLimitResult) throws IOException { + // Read the proto tombstone file as bytes. + final byte[] tombstoneBytes = Files.readAllBytes(tombstone.toPath()); + + final File tombstoneProtoWithHeaders = File.createTempFile( + tombstone.getName(), ".tmp", TOMBSTONE_TMP_DIR); + Files.setPosixFilePermissions( + tombstoneProtoWithHeaders.toPath(), + PosixFilePermissions.fromString("rw-rw----")); + + // Write the new proto container proto with headers. + try (ParcelFileDescriptor pfd = ParcelFileDescriptor.open( + tombstoneProtoWithHeaders, MODE_READ_WRITE)) { + ProtoOutputStream protoStream = + new ProtoOutputStream(pfd.getFileDescriptor()); + protoStream.write(TombstoneWithHeadersProto.TOMBSTONE, tombstoneBytes); + protoStream.write( + TombstoneWithHeadersProto.DROPPED_COUNT, + rateLimitResult.droppedCountSinceRateLimitActivated()); + protoStream.flush(); + + // Add the proto to dropbox. + db.addFile(TAG_TOMBSTONE_PROTO_WITH_HEADERS, tombstoneProtoWithHeaders, 0); + } catch (FileNotFoundException ex) { + Slog.e(TAG, "failed to open for write: " + tombstoneProtoWithHeaders, ex); + throw ex; + } catch (IOException ex) { + Slog.e(TAG, "IO exception during write: " + tombstoneProtoWithHeaders, ex); + } finally { + // Remove the temporary file and unlock the lock. + if (tombstoneProtoWithHeaders != null) { + tombstoneProtoWithHeaders.delete(); + } + } + } + private static void addLastkToDropBox( DropBoxManager db, HashMap<String, Long> timestamps, String headers, String footers, String filename, int maxSize, diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index b67e62703067..e92f043457f5 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -179,6 +179,8 @@ option java_package com.android.server 3130 pm_snapshot_stats (build_count|1|1),(reuse_count|1|1),(big_builds|1|1),(short_lived|1|1),(max_build_time|1|3),(cumm_build_time|2|3) # Snapshot rebuild instance 3131 pm_snapshot_rebuild (build_time|1|3),(lifetime|1|3) +# Caller information to clear application data +3132 pm_clear_app_data_caller (pid|1),(uid|1),(package|3) # --------------------------- # InputMethodManagerService.java @@ -218,6 +220,14 @@ option java_package com.android.server 35000 auto_brightness_adj (old_lux|5),(old_brightness|5),(new_lux|5),(new_brightness|5) # --------------------------- +# Installer.java +# --------------------------- +# Caller Information to clear application data +39000 installer_clear_app_data_caller (pid|1),(uid|1),(package|3),(flags|1) +# Call stack to clear application data +39001 installer_clear_app_data_call_stack (method|3),(class|3),(file|3),(line|1) + +# --------------------------- # ConnectivityService.java # --------------------------- # Connectivity state changed diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index 987507fe7f03..3aa275c8d9b8 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -1,5 +1,5 @@ -# BootReceiver -per-file BootReceiver.java = gaillard@google.com +# BootReceiver / Watchdog +per-file BootReceiver.java,Watchdog.java = gaillard@google.com # Connectivity / Networking per-file ConnectivityService.java,ConnectivityServiceInitializer.java,NetworkManagementService.java,NsdService.java,VpnManagerService.java = file:/services/core/java/com/android/server/net/OWNERS diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java index 0d423d8a0a62..2ba3a1d751d0 100644 --- a/services/core/java/com/android/server/VpnManagerService.java +++ b/services/core/java/com/android/server/VpnManagerService.java @@ -33,7 +33,6 @@ import android.content.pm.UserInfo; import android.net.ConnectivityManager; import android.net.INetd; import android.net.IVpnManager; -import android.net.LinkProperties; import android.net.Network; import android.net.NetworkStack; import android.net.UnderlyingNetworkInfo; @@ -437,16 +436,9 @@ public class VpnManagerService extends IVpnManager.Stub { throw new UnsupportedOperationException("Legacy VPN is deprecated"); } int user = UserHandle.getUserId(mDeps.getCallingUid()); - // Note that if the caller is not system (uid >= Process.FIRST_APPLICATION_UID), - // the code might not work well since getActiveNetwork might return null if the uid is - // blocked by NetworkPolicyManagerService. - final LinkProperties egress = mCm.getLinkProperties(mCm.getActiveNetwork()); - if (egress == null) { - throw new IllegalStateException("Missing active network connection"); - } synchronized (mVpns) { throwIfLockdownEnabled(); - mVpns.get(user).startLegacyVpn(profile, null /* underlying */, egress); + mVpns.get(user).startLegacyVpn(profile); } } diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 62651dd80cd9..4bfcb8710e4e 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -120,6 +120,7 @@ public class Watchdog implements Dumpable { "/system/bin/mediaserver", "/system/bin/netd", "/system/bin/sdcard", + "/system/bin/servicemanager", "/system/bin/surfaceflinger", "/system/bin/vold", "media.extractor", // system/bin/mediaextractor diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java index 6794f750c82d..3280afdf6703 100644 --- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java +++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java @@ -1797,8 +1797,13 @@ public class AdbDebuggingManager { mFingerprints); try { - dump.write("user_keys", AdbDebuggingManagerProto.USER_KEYS, - FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null)); + File userKeys = new File("/data/misc/adb/adb_keys"); + if (userKeys.exists()) { + dump.write("user_keys", AdbDebuggingManagerProto.USER_KEYS, + FileUtils.readTextFile(userKeys, 0, null)); + } else { + Slog.i(TAG, "No user keys on this device"); + } } catch (IOException e) { Slog.i(TAG, "Cannot read user keys", e); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index e74371e6a66b..6c840a593370 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1690,19 +1690,23 @@ public class ActivityManagerService extends IActivityManager.Stub private static final int INDEX_NATIVE_PSS = 0; private static final int INDEX_NATIVE_SWAP_PSS = 1; private static final int INDEX_NATIVE_RSS = 2; - private static final int INDEX_DALVIK_PSS = 3; - private static final int INDEX_DALVIK_SWAP_PSS = 4; - private static final int INDEX_DALVIK_RSS = 5; - private static final int INDEX_OTHER_PSS = 6; - private static final int INDEX_OTHER_SWAP_PSS = 7; - private static final int INDEX_OTHER_RSS = 8; - private static final int INDEX_TOTAL_PSS = 9; - private static final int INDEX_TOTAL_SWAP_PSS = 10; - private static final int INDEX_TOTAL_RSS = 11; - private static final int INDEX_TOTAL_NATIVE_PSS = 12; - private static final int INDEX_TOTAL_MEMTRACK_GRAPHICS = 13; - private static final int INDEX_TOTAL_MEMTRACK_GL = 14; - private static final int INDEX_LAST = 15; + private static final int INDEX_NATIVE_PRIVATE_DIRTY = 3; + private static final int INDEX_DALVIK_PSS = 4; + private static final int INDEX_DALVIK_SWAP_PSS = 5; + private static final int INDEX_DALVIK_RSS = 6; + private static final int INDEX_DALVIK_PRIVATE_DIRTY = 7; + private static final int INDEX_OTHER_PSS = 8; + private static final int INDEX_OTHER_SWAP_PSS = 9; + private static final int INDEX_OTHER_RSS = 10; + private static final int INDEX_OTHER_PRIVATE_DIRTY = 11; + private static final int INDEX_TOTAL_PSS = 12; + private static final int INDEX_TOTAL_SWAP_PSS = 13; + private static final int INDEX_TOTAL_RSS = 14; + private static final int INDEX_TOTAL_PRIVATE_DIRTY = 15; + private static final int INDEX_TOTAL_NATIVE_PSS = 16; + private static final int INDEX_TOTAL_MEMTRACK_GRAPHICS = 17; + private static final int INDEX_TOTAL_MEMTRACK_GL = 18; + private static final int INDEX_LAST = 19; /** * Used to notify activity lifecycle events. @@ -3468,6 +3472,7 @@ public class ActivityManagerService extends IActivityManager.Stub enforceNotIsolatedCaller("clearApplicationUserData"); int uid = Binder.getCallingUid(); int pid = Binder.getCallingPid(); + EventLog.writeEvent(EventLogTags.AM_CLEAR_APP_DATA_CALLER, pid, uid, packageName); final int resolvedUserId = mUserController.handleIncomingUser(pid, uid, userId, false, ALLOW_FULL_ONLY, "clearApplicationUserData", null); @@ -11354,13 +11359,14 @@ public class ActivityManagerService extends IActivityManager.Stub final long pss; final long swapPss; final long mRss; + final long mPrivateDirty; final int id; // pid final int userId; final boolean hasActivities; ArrayList<MemItem> subitems; - MemItem(String label, String shortLabel, long pss, long swapPss, long rss, int id, - @UserIdInt int userId, + MemItem(String label, String shortLabel, long pss, long swapPss, long rss, + long privateDirty, int id, @UserIdInt int userId, boolean hasActivities) { this.isProc = true; this.label = label; @@ -11368,18 +11374,21 @@ public class ActivityManagerService extends IActivityManager.Stub this.pss = pss; this.swapPss = swapPss; this.mRss = rss; + this.mPrivateDirty = privateDirty; this.id = id; this.userId = userId; this.hasActivities = hasActivities; } - MemItem(String label, String shortLabel, long pss, long swapPss, long rss, int id) { + MemItem(String label, String shortLabel, long pss, long swapPss, long rss, + long privateDirty, int id) { this.isProc = false; this.label = label; this.shortLabel = shortLabel; this.pss = pss; this.swapPss = swapPss; this.mRss = rss; + this.mPrivateDirty = privateDirty; this.id = id; this.userId = UserHandle.USER_SYSTEM; this.hasActivities = false; @@ -11404,7 +11413,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final void dumpMemItems(PrintWriter pw, String prefix, String tag, ArrayList<MemItem> items, boolean sort, boolean isCompact, boolean dumpPss, - boolean dumpSwapPss) { + boolean dumpSwapPss, boolean dumpPrivateDirty) { if (sort && !isCompact) { sortMemItems(items, dumpPss); } @@ -11412,14 +11421,18 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i=0; i<items.size(); i++) { MemItem mi = items.get(i); if (!isCompact) { - if (dumpPss && dumpSwapPss) { - pw.printf("%s%s: %-60s (%s in swap)\n", prefix, stringifyKBSize(mi.pss), - mi.label, stringifyKBSize(mi.swapPss)); - } else { - pw.printf("%s%s: %s%s\n", prefix, stringifyKBSize(dumpPss ? mi.pss : mi.mRss), + pw.printf("%s%s: %s%s\n", prefix, stringifyKBSize(dumpPss ? mi.pss : mi.mRss), mi.label, mi.userId != UserHandle.USER_SYSTEM ? " (user " + mi.userId + ")" : ""); + if (dumpPss && dumpSwapPss) { + pw.printf("(%s in swap%s", stringifyKBSize(mi.swapPss), + dumpPrivateDirty ? ", " : ")"); } + if (dumpPrivateDirty) { + pw.printf("%s%s private dirty)", dumpSwapPss ? "" : "(", + stringifyKBSize(mi.mPrivateDirty)); + } + pw.printf("\n"); } else if (mi.isProc) { pw.print("proc,"); pw.print(tag); pw.print(","); pw.print(mi.shortLabel); pw.print(","); pw.print(mi.id); pw.print(","); @@ -11433,7 +11446,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (mi.subitems != null) { dumpMemItems(pw, prefix + " ", mi.shortLabel, mi.subitems, - true, isCompact, dumpPss, dumpSwapPss); + true, isCompact, dumpPss, dumpSwapPss, dumpPrivateDirty); } } } @@ -11601,6 +11614,7 @@ public class ActivityManagerService extends IActivityManager.Stub boolean isCheckinRequest; boolean dumpSwapPss; boolean dumpProto; + boolean mDumpPrivateDirty; } @NeverCompile // Avoid size overhead of debugging code. @@ -11619,6 +11633,7 @@ public class ActivityManagerService extends IActivityManager.Stub opts.isCheckinRequest = false; opts.dumpSwapPss = false; opts.dumpProto = asProto; + opts.mDumpPrivateDirty = false; int opti = 0; while (opti < args.length) { @@ -11641,6 +11656,8 @@ public class ActivityManagerService extends IActivityManager.Stub opts.dumpSummaryOnly = true; } else if ("-S".equals(opt)) { opts.dumpSwapPss = true; + } else if ("-p".equals(opt)) { + opts.mDumpPrivateDirty = true; } else if ("--unreachable".equals(opt)) { opts.dumpUnreachable = true; } else if ("--oom".equals(opt)) { @@ -11661,6 +11678,7 @@ public class ActivityManagerService extends IActivityManager.Stub pw.println(" -c: dump in a compact machine-parseable representation."); pw.println(" -s: dump only summary of application memory usage."); pw.println(" -S: dump also SwapPss."); + pw.println(" -p: dump also private dirty memory usage."); pw.println(" --oom: only show processes organized by oom adj."); pw.println(" --local: only collect details locally, don't call process."); pw.println(" --package: interpret process arg as package, dumping all"); @@ -11779,14 +11797,18 @@ public class ActivityManagerService extends IActivityManager.Stub EmptyArray.LONG; long[] dalvikSubitemRss = opts.dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] : EmptyArray.LONG; + long[] dalvikSubitemPrivateDirty = opts.dumpDalvik + ? new long[Debug.MemoryInfo.NUM_DVK_STATS] : EmptyArray.LONG; long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS]; long[] miscSwapPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS]; long[] miscRss = new long[Debug.MemoryInfo.NUM_OTHER_STATS]; + long[] miscPrivateDirty = new long[Debug.MemoryInfo.NUM_OTHER_STATS]; long[] memtrackTmp = new long[4]; long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length]; long oomSwapPss[] = new long[DUMP_MEM_OOM_LABEL.length]; long[] oomRss = new long[DUMP_MEM_OOM_LABEL.length]; + long[] oomPrivateDirty = new long[DUMP_MEM_OOM_LABEL.length]; ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[]) new ArrayList[DUMP_MEM_OOM_LABEL.length]; @@ -11882,6 +11904,7 @@ public class ActivityManagerService extends IActivityManager.Stub final long myTotalUss = mi.getTotalUss(); final long myTotalRss = mi.getTotalRss(); final long myTotalSwapPss = mi.getTotalSwappedOutPss(); + final long myTotalPrivateDirty = mi.getTotalPrivateDirty(); synchronized (mProcLock) { if (r.getThread() != null && oomAdj == r.mState.getSetAdjWithServices()) { @@ -11895,29 +11918,36 @@ public class ActivityManagerService extends IActivityManager.Stub ss[INDEX_TOTAL_PSS] += myTotalPss; ss[INDEX_TOTAL_SWAP_PSS] += myTotalSwapPss; ss[INDEX_TOTAL_RSS] += myTotalRss; + ss[INDEX_TOTAL_PRIVATE_DIRTY] += myTotalPrivateDirty; ss[INDEX_TOTAL_MEMTRACK_GRAPHICS] += memtrackGraphics; ss[INDEX_TOTAL_MEMTRACK_GL] += memtrackGl; MemItem pssItem = new MemItem(r.processName + " (pid " + pid + (hasActivities ? " / activities)" : ")"), r.processName, myTotalPss, - myTotalSwapPss, myTotalRss, pid, r.userId, hasActivities); + myTotalSwapPss, myTotalRss, myTotalPrivateDirty, + pid, r.userId, hasActivities); procMems.add(pssItem); procMemsMap.put(pid, pssItem); ss[INDEX_NATIVE_PSS] += mi.nativePss; ss[INDEX_NATIVE_SWAP_PSS] += mi.nativeSwappedOutPss; ss[INDEX_NATIVE_RSS] += mi.nativeRss; + ss[INDEX_NATIVE_PRIVATE_DIRTY] += mi.nativePrivateDirty; ss[INDEX_DALVIK_PSS] += mi.dalvikPss; ss[INDEX_DALVIK_SWAP_PSS] += mi.dalvikSwappedOutPss; ss[INDEX_DALVIK_RSS] += mi.dalvikRss; + ss[INDEX_DALVIK_PRIVATE_DIRTY] += mi.dalvikPrivateDirty; for (int j=0; j<dalvikSubitemPss.length; j++) { dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j); dalvikSubitemSwapPss[j] += mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j); + dalvikSubitemPrivateDirty[j] += + mi.getOtherPrivateDirty(Debug.MemoryInfo.NUM_OTHER_STATS + j); dalvikSubitemRss[j] += mi.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS + j); } ss[INDEX_OTHER_PSS] += mi.otherPss; ss[INDEX_OTHER_RSS] += mi.otherRss; ss[INDEX_OTHER_SWAP_PSS] += mi.otherSwappedOutPss; + ss[INDEX_OTHER_PRIVATE_DIRTY] += mi.otherPrivateDirty; for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) { long mem = mi.getOtherPss(j); miscPss[j] += mem; @@ -11925,6 +11955,9 @@ public class ActivityManagerService extends IActivityManager.Stub mem = mi.getOtherSwappedOutPss(j); miscSwapPss[j] += mem; ss[INDEX_OTHER_SWAP_PSS] -= mem; + mem = mi.getOtherPrivateDirty(j); + miscPrivateDirty[j] += mem; + ss[INDEX_OTHER_PRIVATE_DIRTY] -= mem; mem = mi.getOtherRss(j); miscRss[j] += mem; ss[INDEX_OTHER_RSS] -= mem; @@ -11941,6 +11974,7 @@ public class ActivityManagerService extends IActivityManager.Stub && oomAdj < DUMP_MEM_OOM_ADJ[oomIndex + 1])) { oomPss[oomIndex] += myTotalPss; oomSwapPss[oomIndex] += myTotalSwapPss; + oomPrivateDirty[oomIndex] += myTotalPrivateDirty; if (oomProcs[oomIndex] == null) { oomProcs[oomIndex] = new ArrayList<MemItem>(); } @@ -11987,6 +12021,7 @@ public class ActivityManagerService extends IActivityManager.Stub final long myTotalPss = info.getTotalPss(); final long myTotalSwapPss = info.getTotalSwappedOutPss(); final long myTotalRss = info.getTotalRss(); + final long myTotalPrivateDirty = info.getTotalPrivateDirty(); ss[INDEX_TOTAL_PSS] += myTotalPss; ss[INDEX_TOTAL_SWAP_PSS] += myTotalSwapPss; ss[INDEX_TOTAL_RSS] += myTotalRss; @@ -11996,15 +12031,17 @@ public class ActivityManagerService extends IActivityManager.Stub MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")", st.name, myTotalPss, info.getSummaryTotalSwapPss(), myTotalRss, - st.pid, UserHandle.getUserId(st.uid), false); + myTotalPrivateDirty, st.pid, UserHandle.getUserId(st.uid), false); procMems.add(pssItem); ss[INDEX_NATIVE_PSS] += info.nativePss; ss[INDEX_NATIVE_SWAP_PSS] += info.nativeSwappedOutPss; ss[INDEX_NATIVE_RSS] += info.nativeRss; + ss[INDEX_NATIVE_PRIVATE_DIRTY] += info.nativePrivateDirty; ss[INDEX_DALVIK_PSS] += info.dalvikPss; ss[INDEX_DALVIK_SWAP_PSS] += info.dalvikSwappedOutPss; ss[INDEX_DALVIK_RSS] += info.dalvikRss; + ss[INDEX_DALVIK_PRIVATE_DIRTY] += info.dalvikPrivateDirty; for (int j = 0; j < dalvikSubitemPss.length; j++) { dalvikSubitemPss[j] += info.getOtherPss( Debug.MemoryInfo.NUM_OTHER_STATS + j); @@ -12012,10 +12049,13 @@ public class ActivityManagerService extends IActivityManager.Stub info.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j); dalvikSubitemRss[j] += info.getOtherRss(Debug.MemoryInfo.NUM_OTHER_STATS + j); + dalvikSubitemPrivateDirty[j] += + info.getOtherPrivateDirty(Debug.MemoryInfo.NUM_OTHER_STATS + j); } ss[INDEX_OTHER_PSS] += info.otherPss; ss[INDEX_OTHER_SWAP_PSS] += info.otherSwappedOutPss; ss[INDEX_OTHER_RSS] += info.otherRss; + ss[INDEX_OTHER_PRIVATE_DIRTY] += info.otherPrivateDirty; for (int j = 0; j < Debug.MemoryInfo.NUM_OTHER_STATS; j++) { long mem = info.getOtherPss(j); miscPss[j] += mem; @@ -12026,6 +12066,9 @@ public class ActivityManagerService extends IActivityManager.Stub mem = info.getOtherRss(j); miscRss[j] += mem; ss[INDEX_OTHER_RSS] -= mem; + mem = info.getOtherPrivateDirty(j); + miscPrivateDirty[j] += mem; + ss[INDEX_OTHER_PRIVATE_DIRTY] -= mem; } oomPss[0] += myTotalPss; oomSwapPss[0] += myTotalSwapPss; @@ -12034,21 +12077,26 @@ public class ActivityManagerService extends IActivityManager.Stub } oomProcs[0].add(pssItem); oomRss[0] += myTotalRss; + oomPrivateDirty[0] += myTotalPrivateDirty; } }); ArrayList<MemItem> catMems = new ArrayList<MemItem>(); catMems.add(new MemItem("Native", "Native", - ss[INDEX_NATIVE_PSS], ss[INDEX_NATIVE_SWAP_PSS], ss[INDEX_NATIVE_RSS], -1)); + ss[INDEX_NATIVE_PSS], ss[INDEX_NATIVE_SWAP_PSS], + ss[INDEX_NATIVE_RSS], ss[INDEX_NATIVE_PRIVATE_DIRTY], -1)); final int dalvikId = -2; catMems.add(new MemItem("Dalvik", "Dalvik", ss[INDEX_DALVIK_PSS], - ss[INDEX_DALVIK_SWAP_PSS], ss[INDEX_DALVIK_RSS], dalvikId)); + ss[INDEX_DALVIK_SWAP_PSS], ss[INDEX_DALVIK_RSS], + ss[INDEX_DALVIK_PRIVATE_DIRTY], dalvikId)); catMems.add(new MemItem("Unknown", "Unknown", ss[INDEX_OTHER_PSS], - ss[INDEX_OTHER_SWAP_PSS], ss[INDEX_OTHER_RSS], -3)); + ss[INDEX_OTHER_SWAP_PSS], ss[INDEX_OTHER_RSS], + ss[INDEX_OTHER_PRIVATE_DIRTY], -3)); for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) { String label = Debug.MemoryInfo.getOtherLabel(j); - catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], miscRss[j], j)); + catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], miscRss[j], + miscPrivateDirty[j], j)); } if (dalvikSubitemPss.length > 0) { // Add dalvik subitems. @@ -12074,7 +12122,8 @@ public class ActivityManagerService extends IActivityManager.Stub final String name = Debug.MemoryInfo.getOtherLabel( Debug.MemoryInfo.NUM_OTHER_STATS + j); memItem.subitems.add(new MemItem(name, name, dalvikSubitemPss[j], - dalvikSubitemSwapPss[j], dalvikSubitemRss[j], j)); + dalvikSubitemSwapPss[j], dalvikSubitemRss[j], + dalvikSubitemPrivateDirty[j], j)); } } } @@ -12085,7 +12134,7 @@ public class ActivityManagerService extends IActivityManager.Stub String label = opts.isCompact ? DUMP_MEM_OOM_COMPACT_LABEL[j] : DUMP_MEM_OOM_LABEL[j]; MemItem item = new MemItem(label, label, oomPss[j], oomSwapPss[j], oomRss[j], - DUMP_MEM_OOM_ADJ[j]); + oomPrivateDirty[j], DUMP_MEM_OOM_ADJ[j]); item.subitems = oomProcs[j]; oomMems.add(item); } @@ -12096,33 +12145,34 @@ public class ActivityManagerService extends IActivityManager.Stub if (!brief && !opts.oomOnly && !opts.isCompact) { pw.println(); pw.println("Total RSS by process:"); - dumpMemItems(pw, " ", "proc", procMems, true, opts.isCompact, false, false); + dumpMemItems(pw, " ", "proc", procMems, true, opts.isCompact, false, false, false); pw.println(); } if (!opts.isCompact) { pw.println("Total RSS by OOM adjustment:"); } - dumpMemItems(pw, " ", "oom", oomMems, false, opts.isCompact, false, false); + dumpMemItems(pw, " ", "oom", oomMems, false, opts.isCompact, false, false, false); if (!brief && !opts.oomOnly) { PrintWriter out = categoryPw != null ? categoryPw : pw; if (!opts.isCompact) { out.println(); out.println("Total RSS by category:"); } - dumpMemItems(out, " ", "cat", catMems, true, opts.isCompact, false, false); + dumpMemItems(out, " ", "cat", catMems, true, opts.isCompact, false, false, false); } opts.dumpSwapPss = opts.dumpSwapPss && hasSwapPss && ss[INDEX_TOTAL_SWAP_PSS] != 0; if (!brief && !opts.oomOnly && !opts.isCompact) { pw.println(); pw.println("Total PSS by process:"); dumpMemItems(pw, " ", "proc", procMems, true, opts.isCompact, true, - opts.dumpSwapPss); + opts.dumpSwapPss, opts.mDumpPrivateDirty); pw.println(); } if (!opts.isCompact) { pw.println("Total PSS by OOM adjustment:"); } - dumpMemItems(pw, " ", "oom", oomMems, false, opts.isCompact, true, opts.dumpSwapPss); + dumpMemItems(pw, " ", "oom", oomMems, false, opts.isCompact, true, opts.dumpSwapPss, + opts.mDumpPrivateDirty); if (!brief && !opts.oomOnly) { PrintWriter out = categoryPw != null ? categoryPw : pw; if (!opts.isCompact) { @@ -12130,7 +12180,7 @@ public class ActivityManagerService extends IActivityManager.Stub out.println("Total PSS by category:"); } dumpMemItems(out, " ", "cat", catMems, true, opts.isCompact, true, - opts.dumpSwapPss); + opts.dumpSwapPss, opts.mDumpPrivateDirty); } if (!opts.isCompact) { pw.println(); @@ -12532,7 +12582,7 @@ public class ActivityManagerService extends IActivityManager.Stub ss[INDEX_TOTAL_RSS] += myTotalRss; MemItem pssItem = new MemItem(r.processName + " (pid " + pid + (hasActivities ? " / activities)" : ")"), r.processName, myTotalPss, - myTotalSwapPss, myTotalRss, pid, r.userId, hasActivities); + myTotalSwapPss, myTotalRss, 0, pid, r.userId, hasActivities); procMems.add(pssItem); procMemsMap.put(pid, pssItem); @@ -12619,7 +12669,7 @@ public class ActivityManagerService extends IActivityManager.Stub ss[INDEX_TOTAL_NATIVE_PSS] += myTotalPss; MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")", - st.name, myTotalPss, info.getSummaryTotalSwapPss(), myTotalRss, + st.name, myTotalPss, info.getSummaryTotalSwapPss(), myTotalRss, 0, st.pid, UserHandle.getUserId(st.uid), false); procMems.add(pssItem); @@ -12664,15 +12714,16 @@ public class ActivityManagerService extends IActivityManager.Stub ArrayList<MemItem> catMems = new ArrayList<MemItem>(); catMems.add(new MemItem("Native", "Native", ss[INDEX_NATIVE_PSS], - ss[INDEX_NATIVE_SWAP_PSS], ss[INDEX_NATIVE_RSS], -1)); + ss[INDEX_NATIVE_SWAP_PSS], ss[INDEX_NATIVE_RSS], 0, -1)); final int dalvikId = -2; catMems.add(new MemItem("Dalvik", "Dalvik", ss[INDEX_DALVIK_PSS], - ss[INDEX_DALVIK_SWAP_PSS], ss[INDEX_DALVIK_RSS], dalvikId)); + ss[INDEX_DALVIK_SWAP_PSS], ss[INDEX_DALVIK_RSS], 0, dalvikId)); catMems.add(new MemItem("Unknown", "Unknown", ss[INDEX_OTHER_PSS], - ss[INDEX_OTHER_SWAP_PSS], ss[INDEX_OTHER_RSS], -3)); + ss[INDEX_OTHER_SWAP_PSS], ss[INDEX_OTHER_RSS], 0, -3)); for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) { String label = Debug.MemoryInfo.getOtherLabel(j); - catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], miscRss[j], j)); + catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], + miscRss[j], 0, j)); } if (dalvikSubitemPss.length > 0) { // Add dalvik subitems. @@ -12698,7 +12749,7 @@ public class ActivityManagerService extends IActivityManager.Stub final String name = Debug.MemoryInfo.getOtherLabel( Debug.MemoryInfo.NUM_OTHER_STATS + j); memItem.subitems.add(new MemItem(name, name, dalvikSubitemPss[j], - dalvikSubitemSwapPss[j], dalvikSubitemRss[j], j)); + dalvikSubitemSwapPss[j], dalvikSubitemRss[j], 0, j)); } } } @@ -12708,7 +12759,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (oomPss[j] != 0) { String label = opts.isCompact ? DUMP_MEM_OOM_COMPACT_LABEL[j] : DUMP_MEM_OOM_LABEL[j]; - MemItem item = new MemItem(label, label, oomPss[j], oomSwapPss[j], oomRss[j], + MemItem item = new MemItem(label, label, oomPss[j], oomSwapPss[j], oomRss[j], 0, DUMP_MEM_OOM_ADJ[j]); item.subitems = oomProcs[j]; oomMems.add(item); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 2e45da3c8d42..469582d06018 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -1174,7 +1174,7 @@ final class ActivityManagerShellCommand extends ShellCommand { synchronized (mInternal.mOomAdjuster.mCachedAppOptimizer.mFreezerLock) { app.mOptRecord.setFreezeSticky(isSticky); mInternal.mOomAdjuster.mCachedAppOptimizer.unfreezeAppInternalLSP(app, 0, - false); + true); } } } @@ -4122,7 +4122,7 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" -D: enable debugging"); pw.println(" --suspend: debugged app suspend threads at startup (only with -D)"); pw.println(" -N: enable native debugging"); - pw.println(" -W: wait for launch to complete"); + pw.println(" -W: wait for launch to complete (initial display)"); pw.println(" --start-profiler <FILE>: start profiler and send results to <FILE>"); pw.println(" --sampling INTERVAL: use sample profiling with INTERVAL microseconds"); pw.println(" between samples (use with --start-profiler)"); diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index dc6f8584006e..7dac24104029 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -17,7 +17,6 @@ package com.android.server.am; import static android.Manifest.permission.BATTERY_STATS; -import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.DEVICE_POWER; import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.POWER_SAVER; @@ -103,6 +102,7 @@ import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.ParseUtils; import com.android.internal.util.function.pooled.PooledLambda; +import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.NetworkCapabilitiesUtils; import com.android.server.LocalServices; import com.android.server.Watchdog; @@ -426,7 +426,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); try { - nms.registerObserver(mActivityChangeObserver); + if (!SdkLevel.isAtLeastV()) { + // On V+ devices, ConnectivityService calls BatteryStats API to update + // RadioPowerState change. So BatteryStatsService registers the callback only on + // pre V devices. + nms.registerObserver(mActivityChangeObserver); + } cm.registerDefaultNetworkCallback(mNetworkCallback); } catch (RemoteException e) { Slog.e(TAG, "Could not register INetworkManagement event observer " + e); diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java index 0fcec6faa0cc..c26fd5d9b798 100644 --- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java +++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java @@ -258,13 +258,6 @@ class BroadcastProcessQueue { @Nullable public BroadcastRecord enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record, int recordIndex, @NonNull BroadcastConsumer deferredStatesApplyConsumer) { - // When updateDeferredStates() has already applied a deferred state to - // all pending items, apply to this new broadcast too - if (mLastDeferredStates && record.deferUntilActive - && (record.getDeliveryState(recordIndex) == BroadcastRecord.DELIVERY_PENDING)) { - deferredStatesApplyConsumer.accept(record, recordIndex); - } - // Ignore FLAG_RECEIVER_REPLACE_PENDING if the sender specified the policy using the // BroadcastOptions delivery group APIs. if (record.isReplacePending() @@ -287,6 +280,13 @@ class BroadcastProcessQueue { // with implicit responsiveness expectations. getQueueForBroadcast(record).addLast(newBroadcastArgs); onBroadcastEnqueued(record, recordIndex); + + // When updateDeferredStates() has already applied a deferred state to + // all pending items, apply to this new broadcast too + if (mLastDeferredStates && shouldBeDeferred() + && (record.getDeliveryState(recordIndex) == BroadcastRecord.DELIVERY_PENDING)) { + deferredStatesApplyConsumer.accept(record, recordIndex); + } return null; } @@ -1144,9 +1144,6 @@ class BroadcastProcessQueue { } else if (mProcessPersistent) { mRunnableAt = runnableAt + constants.DELAY_PERSISTENT_PROC_MILLIS; mRunnableAtReason = REASON_PERSISTENT; - } else if (UserHandle.isCore(uid)) { - mRunnableAt = runnableAt; - mRunnableAtReason = REASON_CORE_UID; } else if (mCountOrdered > 0) { mRunnableAt = runnableAt; mRunnableAtReason = REASON_CONTAINS_ORDERED; @@ -1193,6 +1190,9 @@ class BroadcastProcessQueue { // is already cached, they'll be deferred on the line above mRunnableAt = runnableAt; mRunnableAtReason = REASON_CONTAINS_RESULT_TO; + } else if (UserHandle.isCore(uid)) { + mRunnableAt = runnableAt; + mRunnableAtReason = REASON_CORE_UID; } else { mRunnableAt = runnableAt + constants.DELAY_NORMAL_MILLIS; mRunnableAtReason = REASON_NORMAL; @@ -1221,32 +1221,45 @@ class BroadcastProcessQueue { } /** - * Update {@link BroadcastRecord.DELIVERY_DEFERRED} states of all our + * Update {@link BroadcastRecord#DELIVERY_DEFERRED} states of all our * pending broadcasts, when needed. */ void updateDeferredStates(@NonNull BroadcastConsumer applyConsumer, @NonNull BroadcastConsumer clearConsumer) { // When all we have pending is deferred broadcasts, and we're cached, // then we want everything to be marked deferred - final boolean wantDeferredStates = (mCountDeferred > 0) - && (mCountDeferred == mCountEnqueued) && mProcessFreezable; + final boolean wantDeferredStates = shouldBeDeferred(); if (mLastDeferredStates != wantDeferredStates) { mLastDeferredStates = wantDeferredStates; if (wantDeferredStates) { forEachMatchingBroadcast((r, i) -> { - return r.deferUntilActive - && (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_PENDING); + return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_PENDING); }, applyConsumer, false); } else { forEachMatchingBroadcast((r, i) -> { - return r.deferUntilActive - && (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); + return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); }, clearConsumer, false); } } } + void clearDeferredStates(@NonNull BroadcastConsumer clearConsumer) { + if (mLastDeferredStates) { + mLastDeferredStates = false; + forEachMatchingBroadcast((r, i) -> { + return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); + }, clearConsumer, false); + } + } + + @VisibleForTesting + boolean shouldBeDeferred() { + if (mRunnableAtInvalidated) updateRunnableAt(); + return mRunnableAtReason == REASON_CACHED + || mRunnableAtReason == REASON_CACHED_INFINITE_DEFER; + } + /** * Check overall health, confirming things are in a reasonable state and * that we're not wedged. diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java index f420619db490..abec890299a3 100644 --- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java @@ -249,6 +249,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue { private static final int MSG_CHECK_HEALTH = 5; private static final int MSG_CHECK_PENDING_COLD_START_VALIDITY = 6; private static final int MSG_PROCESS_FREEZABLE_CHANGED = 7; + private static final int MSG_UID_STATE_CHANGED = 8; private void enqueueUpdateRunningList() { mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST); @@ -295,6 +296,19 @@ class BroadcastQueueModernImpl extends BroadcastQueue { } return true; } + case MSG_UID_STATE_CHANGED: { + final int uid = (int) msg.obj; + final int procState = msg.arg1; + synchronized (mService) { + if (procState == ActivityManager.PROCESS_STATE_TOP) { + mUidForeground.put(uid, true); + } else { + mUidForeground.delete(uid); + } + refreshProcessQueuesLocked(uid); + } + return true; + } } return false; }; @@ -450,6 +464,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue { break; } + // Clear the deferred state of broadcasts in this queue as we are just about to + // deliver broadcasts to this process. + queue.clearDeferredStates(mBroadcastConsumerDeferClear); + // We might not have heard about a newly running process yet, so // consider refreshing if we think we're cold updateWarmProcess(queue); @@ -672,7 +690,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue { @Override public void onProcessFreezableChangedLocked(@NonNull ProcessRecord app) { mLocalHandler.removeMessages(MSG_PROCESS_FREEZABLE_CHANGED, app); - mLocalHandler.sendMessage(mHandler.obtainMessage(MSG_PROCESS_FREEZABLE_CHANGED, app)); + mLocalHandler.obtainMessage(MSG_PROCESS_FREEZABLE_CHANGED, app).sendToTarget(); } @Override @@ -1510,12 +1528,14 @@ class BroadcastQueueModernImpl extends BroadcastQueue { r.resultExtras = null; }; - private final BroadcastConsumer mBroadcastConsumerDeferApply = (r, i) -> { + @VisibleForTesting + final BroadcastConsumer mBroadcastConsumerDeferApply = (r, i) -> { setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_DEFERRED, "mBroadcastConsumerDeferApply"); }; - private final BroadcastConsumer mBroadcastConsumerDeferClear = (r, i) -> { + @VisibleForTesting + final BroadcastConsumer mBroadcastConsumerDeferClear = (r, i) -> { setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_PENDING, "mBroadcastConsumerDeferClear"); }; @@ -1601,14 +1621,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { - synchronized (mService) { - if (procState == ActivityManager.PROCESS_STATE_TOP) { - mUidForeground.put(uid, true); - } else { - mUidForeground.delete(uid); - } - refreshProcessQueuesLocked(uid); - } + mLocalHandler.removeMessages(MSG_UID_STATE_CHANGED, uid); + mLocalHandler.obtainMessage(MSG_UID_STATE_CHANGED, procState, 0, uid) + .sendToTarget(); } }, ActivityManager.UID_OBSERVER_PROCSTATE, ActivityManager.PROCESS_STATE_TOP, "android"); diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags index 9e9db6aff699..2aed8476d031 100644 --- a/services/core/java/com/android/server/am/EventLogTags.logtags +++ b/services/core/java/com/android/server/am/EventLogTags.logtags @@ -129,3 +129,6 @@ option java_package com.android.server.am # Intent Sender redirect for UserHandle.USER_CURRENT 30110 am_intent_sender_redirect_user (userId|1|5) + +# Caller information to clear application data +30120 am_clear_app_data_caller (pid|1),(uid|1),(package|3) diff --git a/services/core/java/com/android/server/am/LmkdStatsReporter.java b/services/core/java/com/android/server/am/LmkdStatsReporter.java index 4380b42ee54c..507fd9efaffd 100644 --- a/services/core/java/com/android/server/am/LmkdStatsReporter.java +++ b/services/core/java/com/android/server/am/LmkdStatsReporter.java @@ -44,6 +44,7 @@ public final class LmkdStatsReporter { private static final int DIRECT_RECL_AND_THRASHING = 5; private static final int LOW_MEM_AND_SWAP_UTIL = 6; private static final int LOW_FILECACHE_AFTER_THRASHING = 7; + private static final int LOW_MEM = 8; /** * Processes the LMK_KILL_OCCURRED packet data @@ -106,6 +107,8 @@ public final class LmkdStatsReporter { return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM_AND_SWAP_UTIL; case LOW_FILECACHE_AFTER_THRASHING: return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_FILECACHE_AFTER_THRASHING; + case LOW_MEM: + return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM; default: return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__UNKNOWN; } diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java index e4a5a3e0ed00..235843643a0d 100644 --- a/services/core/java/com/android/server/app/GameManagerService.java +++ b/services/core/java/com/android/server/app/GameManagerService.java @@ -399,59 +399,6 @@ public final class GameManagerService extends IGameManagerService.Stub { } } - public enum FrameRate { - FPS_DEFAULT(0), - FPS_30(30), - FPS_36(36), - FPS_40(40), - FPS_45(45), - FPS_48(48), - FPS_60(60), - FPS_72(72), - FPS_90(90), - FPS_120(120), - FPS_144(144), - FPS_INVALID(-1); - - public final int fps; - - FrameRate(int fps) { - this.fps = fps; - } - } - - // Turn the raw string to the corresponding fps int. - // Return 0 when disabling, -1 for invalid fps. - static int getFpsInt(String raw) { - // TODO(b/243448953): make sure this translates to proper values based on current display - switch (raw) { - case "30": - return FrameRate.FPS_30.fps; - case "36": - return FrameRate.FPS_36.fps; - case "40": - return FrameRate.FPS_40.fps; - case "45": - return FrameRate.FPS_45.fps; - case "48": - return FrameRate.FPS_48.fps; - case "60": - return FrameRate.FPS_60.fps; - case "72": - return FrameRate.FPS_72.fps; - case "90": - return FrameRate.FPS_90.fps; - case "120": - return FrameRate.FPS_120.fps; - case "144": - return FrameRate.FPS_144.fps; - case "disable": - case "": - return FrameRate.FPS_DEFAULT.fps; - } - return FrameRate.FPS_INVALID.fps; - } - /** * Called by games to communicate the current state to the platform. * @@ -699,7 +646,12 @@ public final class GameManagerService extends IGameManagerService.Stub { } public synchronized int getFps() { - return GameManagerService.getFpsInt(mFps); + try { + final int fpsInt = Integer.parseInt(mFps); + return fpsInt; + } catch (NumberFormatException e) { + return 0; + } } synchronized String getFpsStr() { @@ -739,7 +691,12 @@ public final class GameManagerService extends IGameManagerService.Stub { } android.app.GameModeConfiguration toPublicGameModeConfig() { - int fpsOverride = getFpsInt(mFps); + int fpsOverride; + try { + fpsOverride = Integer.parseInt(mFps); + } catch (NumberFormatException e) { + fpsOverride = 0; + } // TODO(b/243448953): match to proper value in case of display change? fpsOverride = fpsOverride > 0 ? fpsOverride : android.app.GameModeConfiguration.FPS_OVERRIDE_NONE; diff --git a/services/core/java/com/android/server/app/GameManagerShellCommand.java b/services/core/java/com/android/server/app/GameManagerShellCommand.java index 00ff489ee0ff..ab57c4fe837e 100644 --- a/services/core/java/com/android/server/app/GameManagerShellCommand.java +++ b/services/core/java/com/android/server/app/GameManagerShellCommand.java @@ -241,8 +241,10 @@ public class GameManagerShellCommand extends ShellCommand { case "--fps": if (fpsStr == null) { fpsStr = getNextArgRequired(); - if (fpsStr != null && GameManagerService.getFpsInt(fpsStr) == -1) { - pw.println("Invalid frame rate '" + fpsStr + "'"); + try { + Integer.parseInt(fpsStr); + } catch (NumberFormatException e) { + pw.println("Invalid frame rate: '" + fpsStr + "'"); return -1; } } else { @@ -375,8 +377,8 @@ public class GameManagerShellCommand extends ShellCommand { pw.println(" --downscale [0.3|0.35|0.4|0.45|0.5|0.55|0.6|0.65"); pw.println(" |0.7|0.75|0.8|0.85|0.9|disable]: Set app to run at the"); pw.println(" specified scaling ratio."); - pw.println(" --fps [30|45|60|90|120|disable]: Set app to run at the specified fps,"); - pw.println(" if supported."); + pw.println(" --fps: Integer value to set app to run at the specified fps,"); + pw.println(" if supported. 0 to disable."); pw.println(" reset [--mode [2|3|performance|battery] --user <USER_ID>] <PACKAGE_NAME>"); pw.println(" Resets the game mode of the app to device configuration."); pw.println(" This should only be used to reset any override to non custom game mode"); diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java index 4dfd9b076354..f0dd23ce832a 100644 --- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java +++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java @@ -221,20 +221,24 @@ public class AppOpsCheckingServiceImpl implements AppOpsCheckingServiceInterface synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid, null); if (opModes == null) { - if (mode != defaultMode) { - opModes = new SparseIntArray(); - mUidModes.put(uid, opModes); - opModes.put(op, mode); - scheduleWriteLocked(); + if (mode == defaultMode) { + return false; } + opModes = new SparseIntArray(); + mUidModes.put(uid, opModes); + opModes.put(op, mode); + scheduleWriteLocked(); } else { - if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) { + if (opModes.indexOfKey(op) >= 0) { + if (opModes.get(op) == mode) { + return false; + } + } else if (mode == defaultMode) { return false; } if (mode == defaultMode) { opModes.delete(op); if (opModes.size() <= 0) { - opModes = null; mUidModes.delete(uid); } } else { diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java index 969dd60a8012..f46586779f4c 100644 --- a/services/core/java/com/android/server/audio/SpatializerHelper.java +++ b/services/core/java/com/android/server/audio/SpatializerHelper.java @@ -37,10 +37,9 @@ import android.media.ISpatializerHeadTrackingCallback; import android.media.ISpatializerHeadTrackingModeCallback; import android.media.ISpatializerOutputCallback; import android.media.MediaMetrics; -import android.media.SpatializationLevel; -import android.media.SpatializationMode; import android.media.Spatializer; -import android.media.SpatializerHeadTrackingMode; +import android.media.audio.common.HeadTracking; +import android.media.audio.common.Spatialization; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.text.TextUtils; @@ -82,22 +81,22 @@ public class SpatializerHelper { /*package*/ static final SparseIntArray SPAT_MODE_FOR_DEVICE_TYPE = new SparseIntArray(14) { { - append(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, SpatializationMode.SPATIALIZER_TRANSAURAL); - append(AudioDeviceInfo.TYPE_WIRED_HEADSET, SpatializationMode.SPATIALIZER_BINAURAL); - append(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, SpatializationMode.SPATIALIZER_BINAURAL); + append(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, Spatialization.Mode.TRANSAURAL); + append(AudioDeviceInfo.TYPE_WIRED_HEADSET, Spatialization.Mode.BINAURAL); + append(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, Spatialization.Mode.BINAURAL); // assumption for A2DP: mostly headsets - append(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, SpatializationMode.SPATIALIZER_BINAURAL); - append(AudioDeviceInfo.TYPE_DOCK, SpatializationMode.SPATIALIZER_TRANSAURAL); - append(AudioDeviceInfo.TYPE_USB_ACCESSORY, SpatializationMode.SPATIALIZER_TRANSAURAL); - append(AudioDeviceInfo.TYPE_USB_DEVICE, SpatializationMode.SPATIALIZER_TRANSAURAL); - append(AudioDeviceInfo.TYPE_USB_HEADSET, SpatializationMode.SPATIALIZER_BINAURAL); - append(AudioDeviceInfo.TYPE_LINE_ANALOG, SpatializationMode.SPATIALIZER_TRANSAURAL); - append(AudioDeviceInfo.TYPE_LINE_DIGITAL, SpatializationMode.SPATIALIZER_TRANSAURAL); - append(AudioDeviceInfo.TYPE_AUX_LINE, SpatializationMode.SPATIALIZER_TRANSAURAL); - append(AudioDeviceInfo.TYPE_BLE_HEADSET, SpatializationMode.SPATIALIZER_BINAURAL); - append(AudioDeviceInfo.TYPE_BLE_SPEAKER, SpatializationMode.SPATIALIZER_TRANSAURAL); + append(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, Spatialization.Mode.BINAURAL); + append(AudioDeviceInfo.TYPE_DOCK, Spatialization.Mode.TRANSAURAL); + append(AudioDeviceInfo.TYPE_USB_ACCESSORY, Spatialization.Mode.TRANSAURAL); + append(AudioDeviceInfo.TYPE_USB_DEVICE, Spatialization.Mode.TRANSAURAL); + append(AudioDeviceInfo.TYPE_USB_HEADSET, Spatialization.Mode.BINAURAL); + append(AudioDeviceInfo.TYPE_LINE_ANALOG, Spatialization.Mode.TRANSAURAL); + append(AudioDeviceInfo.TYPE_LINE_DIGITAL, Spatialization.Mode.TRANSAURAL); + append(AudioDeviceInfo.TYPE_AUX_LINE, Spatialization.Mode.TRANSAURAL); + append(AudioDeviceInfo.TYPE_BLE_HEADSET, Spatialization.Mode.BINAURAL); + append(AudioDeviceInfo.TYPE_BLE_SPEAKER, Spatialization.Mode.TRANSAURAL); // assumption that BLE broadcast would be mostly consumed on headsets - append(AudioDeviceInfo.TYPE_BLE_BROADCAST, SpatializationMode.SPATIALIZER_BINAURAL); + append(AudioDeviceInfo.TYPE_BLE_BROADCAST, Spatialization.Mode.BINAURAL); } }; @@ -224,12 +223,12 @@ public class SpatializerHelper { ArrayList<Integer> list = new ArrayList<>(0); for (byte value : values) { switch (value) { - case SpatializerHeadTrackingMode.OTHER: - case SpatializerHeadTrackingMode.DISABLED: + case HeadTracking.Mode.OTHER: + case HeadTracking.Mode.DISABLED: // not expected here, skip break; - case SpatializerHeadTrackingMode.RELATIVE_WORLD: - case SpatializerHeadTrackingMode.RELATIVE_SCREEN: + case HeadTracking.Mode.RELATIVE_WORLD: + case HeadTracking.Mode.RELATIVE_SCREEN: list.add(headTrackingModeTypeToSpatializerInt(value)); break; default: @@ -252,10 +251,10 @@ public class SpatializerHelper { byte[] spatModes = spat.getSupportedModes(); for (byte mode : spatModes) { switch (mode) { - case SpatializationMode.SPATIALIZER_BINAURAL: + case Spatialization.Mode.BINAURAL: mBinauralSupported = true; break; - case SpatializationMode.SPATIALIZER_TRANSAURAL: + case Spatialization.Mode.TRANSAURAL: mTransauralSupported = true; break; default: @@ -272,8 +271,8 @@ public class SpatializerHelper { // initialize list of compatible devices for (int i = 0; i < SPAT_MODE_FOR_DEVICE_TYPE.size(); i++) { int mode = SPAT_MODE_FOR_DEVICE_TYPE.valueAt(i); - if ((mode == (int) SpatializationMode.SPATIALIZER_BINAURAL && mBinauralSupported) - || (mode == (int) SpatializationMode.SPATIALIZER_TRANSAURAL + if ((mode == (int) Spatialization.Mode.BINAURAL && mBinauralSupported) + || (mode == (int) Spatialization.Mode.TRANSAURAL && mTransauralSupported)) { mSACapableDeviceTypes.add(SPAT_MODE_FOR_DEVICE_TYPE.keyAt(i)); } @@ -576,9 +575,9 @@ public class SpatializerHelper { int spatMode = SPAT_MODE_FOR_DEVICE_TYPE.get(device.getDeviceType(), Integer.MIN_VALUE); - device.setSAEnabled(spatMode == SpatializationMode.SPATIALIZER_BINAURAL + device.setSAEnabled(spatMode == Spatialization.Mode.BINAURAL ? mBinauralEnabledDefault - : spatMode == SpatializationMode.SPATIALIZER_TRANSAURAL + : spatMode == Spatialization.Mode.TRANSAURAL ? mTransauralEnabledDefault : false); device.setHeadTrackerEnabled(mHeadTrackingEnabledDefault); @@ -628,9 +627,9 @@ public class SpatializerHelper { if (isBluetoothDevice(internalDeviceType)) return deviceType; final int spatMode = SPAT_MODE_FOR_DEVICE_TYPE.get(deviceType, Integer.MIN_VALUE); - if (spatMode == SpatializationMode.SPATIALIZER_TRANSAURAL) { + if (spatMode == Spatialization.Mode.TRANSAURAL) { return AudioDeviceInfo.TYPE_BUILTIN_SPEAKER; - } else if (spatMode == SpatializationMode.SPATIALIZER_BINAURAL) { + } else if (spatMode == Spatialization.Mode.BINAURAL) { return AudioDeviceInfo.TYPE_WIRED_HEADPHONES; } return AudioDeviceInfo.TYPE_UNKNOWN; @@ -755,8 +754,8 @@ public class SpatializerHelper { // not be included. final byte modeForDevice = (byte) SPAT_MODE_FOR_DEVICE_TYPE.get(ada.getType(), /*default when type not found*/ -1); - if ((modeForDevice == SpatializationMode.SPATIALIZER_BINAURAL && mBinauralSupported) - || (modeForDevice == SpatializationMode.SPATIALIZER_TRANSAURAL + if ((modeForDevice == Spatialization.Mode.BINAURAL && mBinauralSupported) + || (modeForDevice == Spatialization.Mode.TRANSAURAL && mTransauralSupported)) { return true; } @@ -966,6 +965,11 @@ public class SpatializerHelper { if (mSpat == null) { mSpatCallback = new SpatializerCallback(); mSpat = AudioSystem.getSpatializer(mSpatCallback); + if (mSpat == null) { + Log.e(TAG, "createSpat(): No Spatializer found"); + postReset(); + return; + } try { //TODO: register heatracking callback only when sensors are registered if (mIsHeadTrackingSupported) { @@ -1430,7 +1434,7 @@ public class SpatializerHelper { } synchronized void onInitSensors() { - final boolean init = mFeatureEnabled && (mSpatLevel != SpatializationLevel.NONE); + final boolean init = mFeatureEnabled && (mSpatLevel != Spatialization.Level.NONE); final String action = init ? "initializing" : "releasing"; if (mSpat == null) { logloge("not " + action + " sensors, null spatializer"); @@ -1496,13 +1500,13 @@ public class SpatializerHelper { // SDK <-> AIDL converters private static int headTrackingModeTypeToSpatializerInt(byte mode) { switch (mode) { - case SpatializerHeadTrackingMode.OTHER: + case HeadTracking.Mode.OTHER: return Spatializer.HEAD_TRACKING_MODE_OTHER; - case SpatializerHeadTrackingMode.DISABLED: + case HeadTracking.Mode.DISABLED: return Spatializer.HEAD_TRACKING_MODE_DISABLED; - case SpatializerHeadTrackingMode.RELATIVE_WORLD: + case HeadTracking.Mode.RELATIVE_WORLD: return Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD; - case SpatializerHeadTrackingMode.RELATIVE_SCREEN: + case HeadTracking.Mode.RELATIVE_SCREEN: return Spatializer.HEAD_TRACKING_MODE_RELATIVE_DEVICE; default: throw (new IllegalArgumentException("Unexpected head tracking mode:" + mode)); @@ -1512,13 +1516,13 @@ public class SpatializerHelper { private static byte spatializerIntToHeadTrackingModeType(int sdkMode) { switch (sdkMode) { case Spatializer.HEAD_TRACKING_MODE_OTHER: - return SpatializerHeadTrackingMode.OTHER; + return HeadTracking.Mode.OTHER; case Spatializer.HEAD_TRACKING_MODE_DISABLED: - return SpatializerHeadTrackingMode.DISABLED; + return HeadTracking.Mode.DISABLED; case Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD: - return SpatializerHeadTrackingMode.RELATIVE_WORLD; + return HeadTracking.Mode.RELATIVE_WORLD; case Spatializer.HEAD_TRACKING_MODE_RELATIVE_DEVICE: - return SpatializerHeadTrackingMode.RELATIVE_SCREEN; + return HeadTracking.Mode.RELATIVE_SCREEN; default: throw (new IllegalArgumentException("Unexpected head tracking mode:" + sdkMode)); } @@ -1526,11 +1530,11 @@ public class SpatializerHelper { private static int spatializationLevelToSpatializerInt(byte level) { switch (level) { - case SpatializationLevel.NONE: + case Spatialization.Level.NONE: return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE; - case SpatializationLevel.SPATIALIZER_MULTICHANNEL: + case Spatialization.Level.MULTICHANNEL: return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL; - case SpatializationLevel.SPATIALIZER_MCHAN_BED_PLUS_OBJECTS: + case Spatialization.Level.BED_PLUS_OBJECTS: return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MCHAN_BED_PLUS_OBJECTS; default: throw (new IllegalArgumentException("Unexpected spatializer level:" + level)); diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java index 4538cad513d6..0629e6373b6e 100644 --- a/services/core/java/com/android/server/biometrics/AuthService.java +++ b/services/core/java/com/android/server/biometrics/AuthService.java @@ -39,6 +39,7 @@ import android.content.pm.PackageManager; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.ComponentInfoInternal; +import android.hardware.biometrics.Flags; import android.hardware.biometrics.IAuthService; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; import android.hardware.biometrics.IBiometricService; @@ -333,6 +334,33 @@ public class AuthService extends SystemService { } @Override + public long getLastAuthenticationTime(int userId, + @Authenticators.Types int authenticators) throws RemoteException { + // Only allow internal clients to call getLastAuthenticationTime with a different + // userId. + final int callingUserId = UserHandle.getCallingUserId(); + + if (userId != callingUserId) { + checkInternalPermission(); + } else { + checkPermission(); + } + + final long identity = Binder.clearCallingIdentity(); + try { + // We can't do this above because we need the READ_DEVICE_CONFIG permission, which + // the calling user may not possess. + if (!Flags.lastAuthenticationTime()) { + throw new UnsupportedOperationException(); + } + + return mBiometricService.getLastAuthenticationTime(userId, authenticators); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override public boolean hasEnrolledBiometrics(int userId, String opPackageName) throws RemoteException { checkInternalPermission(); diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index e8ffe4feb458..9c454ae3b867 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -18,6 +18,7 @@ package com.android.server.biometrics; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.hardware.biometrics.BiometricManager.Authenticators; +import static android.hardware.biometrics.BiometricManager.BIOMETRIC_NO_AUTHENTICATION; import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_IDLE; @@ -37,6 +38,7 @@ import android.hardware.SensorPrivacyManager; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricPrompt; +import android.hardware.biometrics.Flags; import android.hardware.biometrics.IBiometricAuthenticator; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; import android.hardware.biometrics.IBiometricSensorReceiver; @@ -51,6 +53,7 @@ import android.hardware.biometrics.SensorPropertiesInternal; import android.hardware.camera2.CameraManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; +import android.hardware.security.keymint.HardwareAuthenticatorType; import android.net.Uri; import android.os.Binder; import android.os.Build; @@ -60,10 +63,16 @@ import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceSpecificException; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.security.Authorization; +import android.security.GateKeeper; import android.security.KeyStore; +import android.security.authorization.IKeystoreAuthorization; +import android.security.authorization.ResponseCode; +import android.service.gatekeeper.IGateKeeperService; import android.text.TextUtils; import android.util.ArraySet; import android.util.Pair; @@ -77,6 +86,7 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.DumpUtils; import com.android.server.SystemService; import com.android.server.biometrics.log.BiometricContext; +import com.android.server.utils.Slogf; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -114,6 +124,10 @@ public class BiometricService extends SystemService { KeyStore mKeyStore; @VisibleForTesting ITrustManager mTrustManager; + @VisibleForTesting + IKeystoreAuthorization mKeystoreAuthorization; + @VisibleForTesting + IGateKeeperService mGateKeeper; // Get and cache the available biometric authenticators and their associated info. final ArrayList<BiometricSensor> mSensors = new ArrayList<>(); @@ -630,6 +644,64 @@ public class BiometricService extends SystemService { } @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) + @Override // Binder call + public long getLastAuthenticationTime( + int userId, @Authenticators.Types int authenticators) { + super.getLastAuthenticationTime_enforcePermission(); + + if (!Flags.lastAuthenticationTime()) { + throw new UnsupportedOperationException(); + } + + Slogf.d(TAG, "getLastAuthenticationTime(userId=%d, authenticators=0x%x)", + userId, authenticators); + + final long secureUserId; + try { + secureUserId = mGateKeeper.getSecureUserId(userId); + } catch (RemoteException e) { + Slogf.w(TAG, "Failed to get secure user id for " + userId, e); + return BIOMETRIC_NO_AUTHENTICATION; + } + + if (secureUserId == GateKeeper.INVALID_SECURE_USER_ID) { + Slogf.w(TAG, "No secure user id for " + userId); + return BIOMETRIC_NO_AUTHENTICATION; + } + + ArrayList<Integer> hardwareAuthenticators = new ArrayList<>(2); + + if ((authenticators & Authenticators.DEVICE_CREDENTIAL) != 0) { + hardwareAuthenticators.add(HardwareAuthenticatorType.PASSWORD); + } + + if ((authenticators & Authenticators.BIOMETRIC_STRONG) != 0) { + hardwareAuthenticators.add(HardwareAuthenticatorType.FINGERPRINT); + } + + if (hardwareAuthenticators.isEmpty()) { + throw new IllegalArgumentException("authenticators must not be empty"); + } + + int[] authTypesArray = hardwareAuthenticators.stream() + .mapToInt(Integer::intValue) + .toArray(); + try { + return mKeystoreAuthorization.getLastAuthTime(secureUserId, authTypesArray); + } catch (RemoteException e) { + Slog.w(TAG, "Error getting last auth time: " + e); + return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION; + } catch (ServiceSpecificException e) { + // This is returned when the feature flag test fails in keystore2 + if (e.errorCode == ResponseCode.PERMISSION_DENIED) { + throw new UnsupportedOperationException(); + } + + return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION; + } + } + + @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public boolean hasEnrolledBiometrics(int userId, String opPackageName) { @@ -951,6 +1023,14 @@ public class BiometricService extends SystemService { return ActivityManager.getService(); } + public IKeystoreAuthorization getKeystoreAuthorizationService() { + return Authorization.getService(); + } + + public IGateKeeperService getGateKeeperService() { + return GateKeeper.getService(); + } + public ITrustManager getTrustManager() { return ITrustManager.Stub.asInterface(ServiceManager.getService(Context.TRUST_SERVICE)); } @@ -1064,6 +1144,8 @@ public class BiometricService extends SystemService { mBiometricContext = injector.getBiometricContext(context); mUserManager = injector.getUserManager(context); mBiometricCameraManager = injector.getBiometricCameraManager(context); + mKeystoreAuthorization = injector.getKeystoreAuthorizationService(); + mGateKeeper = injector.getGateKeeperService(); try { injector.getActivityManagerService().registerUserSwitchObserver( diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java index 3c885a145315..3b18f0c76d25 100644 --- a/services/core/java/com/android/server/camera/CameraServiceProxy.java +++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java @@ -52,7 +52,6 @@ import android.hardware.display.DisplayManager; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; import android.media.AudioManager; -import android.nfc.INfcAdapter; import android.nfc.NfcAdapter; import android.nfc.NfcManager; import android.os.Binder; @@ -1252,45 +1251,19 @@ public class CameraServiceProxy extends SystemService } } - // TODO(b/303286040): Remove the raw INfcAdapter usage once |ENABLE_NFC_MAINLINE_FLAG| is - // rolled out. - private static final String NFC_SERVICE_BINDER_NAME = "nfc"; - // Flags arguments to NFC adapter to enable/disable NFC - public static final int DISABLE_POLLING_FLAGS = 0x1000; - public static final int ENABLE_POLLING_FLAGS = 0x0000; - private void setNfcReaderModeUsingINfcAdapter(boolean enablePolling) { - IBinder nfcServiceBinder = getBinderService(NFC_SERVICE_BINDER_NAME); - if (nfcServiceBinder == null) { + private void notifyNfcService(boolean enablePolling) { + NfcManager nfcManager = mContext.getSystemService(NfcManager.class); + if (nfcManager == null) { Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); return; } - INfcAdapter nfcAdapterRaw = INfcAdapter.Stub.asInterface(nfcServiceBinder); - int flags = enablePolling ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS; - if (DEBUG) Slog.v(TAG, "Setting NFC reader mode to flags " + flags); - try { - nfcAdapterRaw.setReaderMode(nfcInterfaceToken, null, flags, null); - } catch (RemoteException e) { - Slog.w(TAG, "Could not notify NFC service, remote exception: " + e); - } - } - - private void notifyNfcService(boolean enablePolling) { - if (android.nfc.Flags.enableNfcMainline()) { - NfcManager nfcManager = mContext.getSystemService(NfcManager.class); - if (nfcManager == null) { - Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); - return; - } - NfcAdapter nfcAdapter = nfcManager.getDefaultAdapter(); - if (nfcAdapter == null) { - Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); - return; - } - if (DEBUG) Slog.v(TAG, "Setting NFC reader mode. enablePolling: " + enablePolling); - nfcAdapter.setReaderMode(enablePolling); - } else { - setNfcReaderModeUsingINfcAdapter(enablePolling); + NfcAdapter nfcAdapter = nfcManager.getDefaultAdapter(); + if (nfcAdapter == null) { + Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); + return; } + if (DEBUG) Slog.v(TAG, "Setting NFC reader mode. enablePolling: " + enablePolling); + nfcAdapter.setReaderMode(enablePolling); } private static int[] toArray(Collection<Integer> c) { diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index 4b8b43134e6c..74310b52cf06 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -54,6 +54,7 @@ import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; @@ -65,7 +66,6 @@ import android.os.Parcel; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; @@ -114,8 +114,6 @@ import java.util.function.Consumer; public class ClipboardService extends SystemService { private static final String TAG = "ClipboardService"; - private static final boolean IS_EMULATOR = - SystemProperties.getBoolean("ro.boot.qemu", false); @VisibleForTesting public static final long DEFAULT_CLIPBOARD_TIMEOUT_MILLIS = 3600000; @@ -190,7 +188,7 @@ public class ClipboardService extends SystemService { mAutofillInternal = LocalServices.getService(AutofillManagerInternal.class); final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard"); mPermissionOwner = permOwner; - if (IS_EMULATOR) { + if (Build.IS_EMULATOR) { mEmulatorClipboardMonitor = new EmulatorClipboardMonitor((clip) -> { synchronized (mLock) { setPrimaryClipInternalLocked(getClipboardLocked(0, DEVICE_ID_DEFAULT), clip, diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 53fbe8f37046..c5170585a1b3 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -22,7 +22,6 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.RouteInfo.RTN_THROW; import static android.net.RouteInfo.RTN_UNREACHABLE; import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_AUTO; @@ -45,12 +44,10 @@ import android.app.AppOpsManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -59,7 +56,6 @@ import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.net.ConnectivityDiagnosticsManager; import android.net.ConnectivityManager; -import android.net.DnsResolver; import android.net.INetd; import android.net.INetworkManagementEventObserver; import android.net.Ikev2VpnProfile; @@ -70,8 +66,6 @@ import android.net.IpSecManager.IpSecTunnelInterface; import android.net.IpSecTransform; import android.net.LinkAddress; import android.net.LinkProperties; -import android.net.LocalSocket; -import android.net.LocalSocketAddress; import android.net.Network; import android.net.NetworkAgent; import android.net.NetworkAgentConfig; @@ -112,8 +106,6 @@ import android.net.vcn.VcnTransportInfo; import android.os.Binder; import android.os.Build.VERSION_CODES; import android.os.Bundle; -import android.os.CancellationSignal; -import android.os.FileUtils; import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; @@ -124,7 +116,6 @@ import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; -import android.os.SystemService; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -152,7 +143,6 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; -import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.BinderUtils; import com.android.net.module.util.LinkPropertiesUtils; import com.android.net.module.util.NetdUtils; @@ -165,11 +155,8 @@ import com.android.server.vcn.util.PersistableBundleUtils; import libcore.io.IoUtils; -import java.io.File; import java.io.FileDescriptor; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -195,14 +182,11 @@ import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; /** * @hide @@ -457,10 +441,6 @@ public class Vpn { // The user id of initiating VPN. private final int mUserId; - interface RetryScheduler { - void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException; - } - private static class CarrierConfigInfo { public final String mccMnc; public final int keepaliveDelaySec; @@ -489,26 +469,6 @@ public class Vpn { return Binder.getCallingUid() == Process.SYSTEM_UID; } - public void startService(final String serviceName) { - SystemService.start(serviceName); - } - - public void stopService(final String serviceName) { - SystemService.stop(serviceName); - } - - public boolean isServiceRunning(final String serviceName) { - return SystemService.isRunning(serviceName); - } - - public boolean isServiceStopped(final String serviceName) { - return SystemService.isStopped(serviceName); - } - - public File getStateFile() { - return new File("/data/misc/vpn/state"); - } - public DeviceIdleInternal getDeviceIdleInternal() { return LocalServices.getService(DeviceIdleInternal.class); } @@ -517,104 +477,6 @@ public class Vpn { return VpnConfig.getIntentForStatusPanel(context); } - public void sendArgumentsToDaemon( - final String daemon, final LocalSocket socket, final String[] arguments, - final RetryScheduler retryScheduler) throws IOException, InterruptedException { - final LocalSocketAddress address = new LocalSocketAddress( - daemon, LocalSocketAddress.Namespace.RESERVED); - - // Wait for the socket to connect. - while (true) { - try { - socket.connect(address); - break; - } catch (Exception e) { - // ignore - } - retryScheduler.checkInterruptAndDelay(true /* sleepLonger */); - } - socket.setSoTimeout(500); - - final OutputStream out = socket.getOutputStream(); - for (String argument : arguments) { - byte[] bytes = argument.getBytes(StandardCharsets.UTF_8); - if (bytes.length >= 0xFFFF) { - throw new IllegalArgumentException("Argument is too large"); - } - out.write(bytes.length >> 8); - out.write(bytes.length); - out.write(bytes); - retryScheduler.checkInterruptAndDelay(false /* sleepLonger */); - } - out.write(0xFF); - out.write(0xFF); - - // Wait for End-of-File. - final InputStream in = socket.getInputStream(); - while (true) { - try { - if (in.read() == -1) { - break; - } - } catch (Exception e) { - // ignore - } - retryScheduler.checkInterruptAndDelay(true /* sleepLonger */); - } - } - - @NonNull - public InetAddress resolve(final String endpoint) - throws ExecutionException, InterruptedException { - try { - return InetAddresses.parseNumericAddress(endpoint); - } catch (IllegalArgumentException e) { - // Endpoint is not numeric : fall through and resolve - } - - final CancellationSignal cancellationSignal = new CancellationSignal(); - try { - final DnsResolver resolver = DnsResolver.getInstance(); - final CompletableFuture<InetAddress> result = new CompletableFuture(); - final DnsResolver.Callback<List<InetAddress>> cb = - new DnsResolver.Callback<List<InetAddress>>() { - @Override - public void onAnswer(@NonNull final List<InetAddress> answer, - final int rcode) { - if (answer.size() > 0) { - result.complete(answer.get(0)); - } else { - result.completeExceptionally( - new UnknownHostException(endpoint)); - } - } - - @Override - public void onError(@Nullable final DnsResolver.DnsException error) { - // Unfortunately UnknownHostException doesn't accept a cause, so - // print a message here instead. Only show the summary, not the - // full stack trace. - Log.e(TAG, "Async dns resolver error : " + error); - result.completeExceptionally(new UnknownHostException(endpoint)); - } - }; - resolver.query(null /* network, null for default */, endpoint, - DnsResolver.FLAG_EMPTY, r -> r.run(), cancellationSignal, cb); - return result.get(); - } catch (final ExecutionException e) { - Log.e(TAG, "Cannot resolve VPN endpoint : " + endpoint + ".", e); - throw e; - } catch (final InterruptedException e) { - Log.e(TAG, "Legacy VPN was interrupted while resolving the endpoint", e); - cancellationSignal.cancel(); - throw e; - } - } - - public boolean isInterfacePresent(final Vpn vpn, final String iface) { - return vpn.jniCheck(iface) != 0; - } - /** * @see ParcelFileDescriptor#adoptFd(int) */ @@ -1063,8 +925,6 @@ public class Vpn { // Store mPackage since it might be reset or might be replaced with the other VPN app. final String oldPackage = mPackage; final boolean isPackageChanged = !Objects.equals(packageName, oldPackage); - // TODO: Remove "SdkLevel.isAtLeastT()" check once VpnManagerService is decoupled from - // ConnectivityServiceTest. // Only notify VPN apps that were already always-on, and only if the always-on provider // changed, or the lockdown mode changed. final boolean shouldNotifyOldPkg = isVpnApp(oldPackage) && mAlwaysOn @@ -1078,12 +938,6 @@ public class Vpn { saveAlwaysOnPackage(); - // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from - // ConnectivityServiceTest. - if (!SdkLevel.isAtLeastT()) { - return true; - } - if (shouldNotifyOldPkg) { // If both of shouldNotifyOldPkg & isPackageChanged are true, that means the // always-on of old package is disabled or the old package is replaced with the new @@ -1984,9 +1838,7 @@ public class Vpn { for (String app : packageNames) { int uid = getAppUid(mContext, app, userId); if (uid != -1) uids.add(uid); - // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from - // ConnectivityServiceTest. - if (Process.isApplicationUid(uid) && SdkLevel.isAtLeastT()) { + if (Process.isApplicationUid(uid)) { uids.add(Process.toSdkSandboxUid(uid)); } } @@ -2297,15 +2149,6 @@ public class Vpn { private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() { @Override - public void interfaceStatusChanged(String interfaze, boolean up) { - synchronized (Vpn.this) { - if (!up && mVpnRunner != null && mVpnRunner instanceof LegacyVpnRunner) { - ((LegacyVpnRunner) mVpnRunner).exitIfOuterInterfaceIs(interfaze); - } - } - } - - @Override public void interfaceRemoved(String interfaze) { synchronized (Vpn.this) { if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { @@ -2556,17 +2399,6 @@ public class Vpn { private native boolean jniAddAddress(String interfaze, String address, int prefixLen); private native boolean jniDelAddress(String interfaze, String address, int prefixLen); - private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) { - for (RouteInfo route : prop.getAllRoutes()) { - // Currently legacy VPN only works on IPv4. - if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) { - return route; - } - } - - throw new IllegalStateException("Unable to find IPv4 default gateway"); - } - private void enforceNotRestrictedUser() { final long token = Binder.clearCallingIdentity(); try { @@ -2585,15 +2417,14 @@ public class Vpn { * secondary thread to perform connection work, returning quickly. * * Should only be called to respond to Binder requests as this enforces caller permission. Use - * {@link #startLegacyVpnPrivileged(VpnProfile, Network, LinkProperties)} to skip the + * {@link #startLegacyVpnPrivileged(VpnProfile)} to skip the * permission check only when the caller is trusted (or the call is initiated by the system). */ - public void startLegacyVpn(VpnProfile profile, @Nullable Network underlying, - LinkProperties egress) { + public void startLegacyVpn(VpnProfile profile) { enforceControlPermission(); final long token = Binder.clearCallingIdentity(); try { - startLegacyVpnPrivileged(profile, underlying, egress); + startLegacyVpnPrivileged(profile); } finally { Binder.restoreCallingIdentity(token); } @@ -2652,23 +2483,19 @@ public class Vpn { } /** - * Like {@link #startLegacyVpn(VpnProfile, Network, LinkProperties)}, but does not - * check permissions under the assumption that the caller is the system. + * Like {@link #startLegacyVpn(VpnProfile)}, but does not check permissions under + * the assumption that the caller is the system. * * Callers are responsible for checking permissions if needed. */ - public void startLegacyVpnPrivileged(VpnProfile profile, - @Nullable Network underlying, @NonNull LinkProperties egress) { + public void startLegacyVpnPrivileged(VpnProfile profileToStart) { + final VpnProfile profile = profileToStart.clone(); UserInfo user = mUserManager.getUserInfo(mUserId); if (user.isRestricted() || mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, new UserHandle(mUserId))) { throw new SecurityException("Restricted users cannot establish VPNs"); } - final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress); - final String gateway = ipv4DefaultRoute.getGateway().getHostAddress(); - final String iface = ipv4DefaultRoute.getInterface(); - // Load certificates. String privateKey = ""; String userCert = ""; @@ -2700,8 +2527,6 @@ public class Vpn { throw new IllegalStateException("Cannot load credentials"); } - // Prepare arguments for racoon. - String[] racoon = null; switch (profile.type) { case VpnProfile.TYPE_IKEV2_IPSEC_RSA: // Secret key is still just the alias (not the actual private key). The private key @@ -2731,109 +2556,9 @@ public class Vpn { // profile. startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN); return; - case VpnProfile.TYPE_L2TP_IPSEC_PSK: - racoon = new String[] { - iface, profile.server, "udppsk", profile.ipsecIdentifier, - profile.ipsecSecret, "1701", - }; - break; - case VpnProfile.TYPE_L2TP_IPSEC_RSA: - racoon = new String[] { - iface, profile.server, "udprsa", makeKeystoreEngineGrantString(privateKey), - userCert, caCert, serverCert, "1701", - }; - break; - case VpnProfile.TYPE_IPSEC_XAUTH_PSK: - racoon = new String[] { - iface, profile.server, "xauthpsk", profile.ipsecIdentifier, - profile.ipsecSecret, profile.username, profile.password, "", gateway, - }; - break; - case VpnProfile.TYPE_IPSEC_XAUTH_RSA: - racoon = new String[] { - iface, profile.server, "xauthrsa", makeKeystoreEngineGrantString(privateKey), - userCert, caCert, serverCert, profile.username, profile.password, "", gateway, - }; - break; - case VpnProfile.TYPE_IPSEC_HYBRID_RSA: - racoon = new String[] { - iface, profile.server, "hybridrsa", - caCert, serverCert, profile.username, profile.password, "", gateway, - }; - break; - } - - // Prepare arguments for mtpd. MTU/MRU calculated conservatively. Only IPv4 supported - // because LegacyVpn. - // 1500 - 60 (Carrier-internal IPv6 + UDP + GTP) - 10 (PPP) - 16 (L2TP) - 8 (UDP) - // - 77 (IPsec w/ SHA-2 512, 256b trunc-len, AES-CBC) - 8 (UDP encap) - 20 (IPv4) - // - 28 (464xlat) - String[] mtpd = null; - switch (profile.type) { - case VpnProfile.TYPE_PPTP: - mtpd = new String[] { - iface, "pptp", profile.server, "1723", - "name", profile.username, "password", profile.password, - "linkname", "vpn", "refuse-eap", "nodefaultroute", - "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270", - (profile.mppe ? "+mppe" : "nomppe"), - }; - if (profile.mppe) { - // Disallow PAP authentication when MPPE is requested, as MPPE cannot work - // with PAP anyway, and users may not expect PAP (plain text) to be used when - // MPPE was requested. - mtpd = Arrays.copyOf(mtpd, mtpd.length + 1); - mtpd[mtpd.length - 1] = "-pap"; - } - break; - case VpnProfile.TYPE_L2TP_IPSEC_PSK: - case VpnProfile.TYPE_L2TP_IPSEC_RSA: - mtpd = new String[] { - iface, "l2tp", profile.server, "1701", profile.l2tpSecret, - "name", profile.username, "password", profile.password, - "linkname", "vpn", "refuse-eap", "nodefaultroute", - "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270", - }; - break; - } - - VpnConfig config = new VpnConfig(); - config.legacy = true; - config.user = profile.key; - config.interfaze = iface; - config.session = profile.name; - config.isMetered = false; - config.proxyInfo = profile.proxy; - if (underlying != null) { - config.underlyingNetworks = new Network[] { underlying }; } - config.addLegacyRoutes(profile.routes); - if (!profile.dnsServers.isEmpty()) { - config.dnsServers = Arrays.asList(profile.dnsServers.split(" +")); - } - if (!profile.searchDomains.isEmpty()) { - config.searchDomains = Arrays.asList(profile.searchDomains.split(" +")); - } - startLegacyVpn(config, racoon, mtpd, profile); - } - - private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd, - VpnProfile profile) { - stopVpnRunnerPrivileged(); - - // Prepare for the new request. - prepareInternal(VpnConfig.LEGACY_VPN); - updateState(DetailedState.CONNECTING, "startLegacyVpn"); - - // Start a new LegacyVpnRunner and we are done! - mVpnRunner = new LegacyVpnRunner(config, racoon, mtpd, profile); - startLegacyVpnRunner(); - } - - @VisibleForTesting - protected void startLegacyVpnRunner() { - mVpnRunner.start(); + throw new UnsupportedOperationException("Legacy VPN is deprecated"); } /** @@ -2851,17 +2576,7 @@ public class Vpn { return; } - final boolean isLegacyVpn = mVpnRunner instanceof LegacyVpnRunner; mVpnRunner.exit(); - - // LegacyVpn uses daemons that must be shut down before new ones are brought up. - // The same limitation does not apply to Platform VPNs. - if (isLegacyVpn) { - synchronized (LegacyVpnRunner.TAG) { - // wait for old thread to completely finish before spinning up - // new instance, otherwise state updates can be out of order. - } - } } /** @@ -3537,6 +3252,13 @@ public class Vpn { * given network to start a new IKE session. */ private void startOrMigrateIkeSession(@Nullable Network underlyingNetwork) { + synchronized (Vpn.this) { + // Ignore stale runner. + if (mVpnRunner != this) return; + setVpnNetworkPreference(mSessionKey, + createUserAndRestrictedProfilesRanges(mUserId, + mConfig.allowedApplications, mConfig.disallowedApplications)); + } if (underlyingNetwork == null) { // For null underlyingNetwork case, there will not be a NetworkAgent available so // no underlying network update is necessary here. Note that updating @@ -4057,6 +3779,7 @@ public class Vpn { updateState(DetailedState.FAILED, exception.getMessage()); } + clearVpnNetworkPreference(mSessionKey); disconnectVpnRunner(); } @@ -4143,9 +3866,7 @@ public class Vpn { // Ignore stale runner. if (mVpnRunner != this) return; - // TODO(b/230548427): Remove SDK check once VPN related stuff are - // decoupled from ConnectivityServiceTest. - if (SdkLevel.isAtLeastT() && category != null && isVpnApp(mPackage)) { + if (category != null && isVpnApp(mPackage)) { sendEventToVpnManagerApp(category, errorClass, errorCode, getPackage(), mSessionKey, makeVpnProfileStateLocked(), mActiveNetwork, @@ -4193,6 +3914,13 @@ public class Vpn { } resetIkeState(); + if (errorCode != VpnManager.ERROR_CODE_NETWORK_LOST + // Clear the VPN network preference when the retry delay is higher than 5s. + // mRetryCount was increased when scheduleRetryNewIkeSession() is called, + // therefore use mRetryCount - 1 here. + && mDeps.getNextRetryDelayMs(mRetryCount - 1) > 5_000L) { + clearVpnNetworkPreference(mSessionKey); + } } /** @@ -4239,13 +3967,17 @@ public class Vpn { mCarrierConfigManager.unregisterCarrierConfigChangeListener( mCarrierConfigChangeListener); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); - clearVpnNetworkPreference(mSessionKey); mExecutor.shutdown(); } @Override public void exitVpnRunner() { + // mSessionKey won't be changed since the Ikev2VpnRunner is created, so it's ok to use + // it outside the mExecutor. And clearing the VPN network preference here can prevent + // the case that the VPN network preference isn't cleared when Ikev2VpnRunner became + // stale. + clearVpnNetworkPreference(mSessionKey); try { mExecutor.execute(() -> { disconnectVpnRunner(); @@ -4256,343 +3988,6 @@ public class Vpn { } } - /** - * Bringing up a VPN connection takes time, and that is all this thread - * does. Here we have plenty of time. The only thing we need to take - * care of is responding to interruptions as soon as possible. Otherwise - * requests will pile up. This could be done in a Handler as a state - * machine, but it is much easier to read in the current form. - */ - private class LegacyVpnRunner extends VpnRunner { - private static final String TAG = "LegacyVpnRunner"; - - private final String[] mDaemons; - private final String[][] mArguments; - private final LocalSocket[] mSockets; - private final String mOuterInterface; - private final AtomicInteger mOuterConnection = - new AtomicInteger(ConnectivityManager.TYPE_NONE); - private final VpnProfile mProfile; - - private long mBringupStartTime = -1; - - /** - * Watch for the outer connection (passing in the constructor) going away. - */ - private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (!mEnableTeardown) return; - - if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { - if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, - ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) { - NetworkInfo info = (NetworkInfo)intent.getExtra( - ConnectivityManager.EXTRA_NETWORK_INFO); - if (info != null && !info.isConnectedOrConnecting()) { - try { - mObserver.interfaceStatusChanged(mOuterInterface, false); - } catch (RemoteException e) {} - } - } - } - } - }; - - // GuardedBy("Vpn.this") (annotation can't be applied to constructor) - LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) { - super(TAG); - if (racoon == null && mtpd == null) { - throw new IllegalArgumentException( - "Arguments to racoon and mtpd must not both be null"); - } - mConfig = config; - mDaemons = new String[] {"racoon", "mtpd"}; - // TODO: clear arguments from memory once launched - mArguments = new String[][] {racoon, mtpd}; - mSockets = new LocalSocket[mDaemons.length]; - - // This is the interface which VPN is running on, - // mConfig.interfaze will change to point to OUR - // internal interface soon. TODO - add inner/outer to mconfig - // TODO - we have a race - if the outer iface goes away/disconnects before we hit this - // we will leave the VPN up. We should check that it's still there/connected after - // registering - mOuterInterface = mConfig.interfaze; - - mProfile = profile; - - if (!TextUtils.isEmpty(mOuterInterface)) { - for (Network network : mConnectivityManager.getAllNetworks()) { - final LinkProperties lp = mConnectivityManager.getLinkProperties(network); - if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) { - final NetworkInfo netInfo = mConnectivityManager.getNetworkInfo(network); - if (netInfo != null) { - mOuterConnection.set(netInfo.getType()); - break; - } - } - } - } - - IntentFilter filter = new IntentFilter(); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - mContext.registerReceiver(mBroadcastReceiver, filter); - } - - /** - * Checks if the parameter matches the underlying interface - * - * <p>If the underlying interface is torn down, the LegacyVpnRunner also should be. It has - * no ability to migrate between interfaces (or Networks). - */ - public void exitIfOuterInterfaceIs(String interfaze) { - if (interfaze.equals(mOuterInterface)) { - Log.i(TAG, "Legacy VPN is going down with " + interfaze); - exitVpnRunner(); - } - } - - /** Tears down this LegacyVpn connection */ - @Override - public void exitVpnRunner() { - // We assume that everything is reset after stopping the daemons. - interrupt(); - - // Always disconnect. This may be called again in cleanupVpnStateLocked() if - // exitVpnRunner() was called from exit(), but it will be a no-op. - agentDisconnect(); - try { - mContext.unregisterReceiver(mBroadcastReceiver); - } catch (IllegalArgumentException e) {} - } - - @Override - public void run() { - // Wait for the previous thread since it has been interrupted. - Log.v(TAG, "Waiting"); - synchronized (TAG) { - Log.v(TAG, "Executing"); - try { - bringup(); - waitForDaemonsToStop(); - interrupted(); // Clear interrupt flag if execute called exit. - } catch (InterruptedException e) { - } finally { - for (LocalSocket socket : mSockets) { - IoUtils.closeQuietly(socket); - } - // This sleep is necessary for racoon to successfully complete sending delete - // message to server. - try { - Thread.sleep(50); - } catch (InterruptedException e) { - } - for (String daemon : mDaemons) { - mDeps.stopService(daemon); - } - } - agentDisconnect(); - } - } - - private void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException { - long now = SystemClock.elapsedRealtime(); - if (now - mBringupStartTime <= 60000) { - Thread.sleep(sleepLonger ? 200 : 1); - } else { - updateState(DetailedState.FAILED, "checkpoint"); - throw new IllegalStateException("VPN bringup took too long"); - } - } - - private void checkAndFixupArguments(@NonNull final InetAddress endpointAddress) { - final String endpointAddressString = endpointAddress.getHostAddress(); - // Perform some safety checks before inserting the address in place. - // Position 0 in mDaemons and mArguments must be racoon, and position 1 must be mtpd. - if (!"racoon".equals(mDaemons[0]) || !"mtpd".equals(mDaemons[1])) { - throw new IllegalStateException("Unexpected daemons order"); - } - - // Respectively, the positions at which racoon and mtpd take the server address - // argument are 1 and 2. Not all types of VPN require both daemons however, and - // in that case the corresponding argument array is null. - if (mArguments[0] != null) { - if (!mProfile.server.equals(mArguments[0][1])) { - throw new IllegalStateException("Invalid server argument for racoon"); - } - mArguments[0][1] = endpointAddressString; - } - - if (mArguments[1] != null) { - if (!mProfile.server.equals(mArguments[1][2])) { - throw new IllegalStateException("Invalid server argument for mtpd"); - } - mArguments[1][2] = endpointAddressString; - } - } - - private void bringup() { - // Catch all exceptions so we can clean up a few things. - try { - // resolve never returns null. If it does because of some bug, it will be - // caught by the catch() block below and cleanup gracefully. - final InetAddress endpointAddress = mDeps.resolve(mProfile.server); - - // Big hack : dynamically replace the address of the server in the arguments - // with the resolved address. - checkAndFixupArguments(endpointAddress); - - // Initialize the timer. - mBringupStartTime = SystemClock.elapsedRealtime(); - - // Wait for the daemons to stop. - for (String daemon : mDaemons) { - while (!mDeps.isServiceStopped(daemon)) { - checkInterruptAndDelay(true); - } - } - - // Clear the previous state. - final File state = mDeps.getStateFile(); - state.delete(); - if (state.exists()) { - throw new IllegalStateException("Cannot delete the state"); - } - new File("/data/misc/vpn/abort").delete(); - - updateState(DetailedState.CONNECTING, "execute"); - - // Start the daemon with arguments. - for (int i = 0; i < mDaemons.length; ++i) { - String[] arguments = mArguments[i]; - if (arguments == null) { - continue; - } - - // Start the daemon. - String daemon = mDaemons[i]; - mDeps.startService(daemon); - - // Wait for the daemon to start. - while (!mDeps.isServiceRunning(daemon)) { - checkInterruptAndDelay(true); - } - - // Create the control socket. - mSockets[i] = new LocalSocket(); - - // Wait for the socket to connect and send over the arguments. - mDeps.sendArgumentsToDaemon(daemon, mSockets[i], arguments, - this::checkInterruptAndDelay); - } - - // Wait for the daemons to create the new state. - while (!state.exists()) { - // Check if a running daemon is dead. - for (int i = 0; i < mDaemons.length; ++i) { - String daemon = mDaemons[i]; - if (mArguments[i] != null && !mDeps.isServiceRunning(daemon)) { - throw new IllegalStateException(daemon + " is dead"); - } - } - checkInterruptAndDelay(true); - } - - // Now we are connected. Read and parse the new state. - String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1); - if (parameters.length != 7) { - throw new IllegalStateException("Cannot parse the state: '" - + String.join("', '", parameters) + "'"); - } - - // Set the interface and the addresses in the config. - synchronized (Vpn.this) { - mConfig.interfaze = parameters[0].trim(); - - mConfig.addLegacyAddresses(parameters[1]); - // Set the routes if they are not set in the config. - if (mConfig.routes == null || mConfig.routes.isEmpty()) { - mConfig.addLegacyRoutes(parameters[2]); - } - - // Set the DNS servers if they are not set in the config. - if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) { - String dnsServers = parameters[3].trim(); - if (!dnsServers.isEmpty()) { - mConfig.dnsServers = Arrays.asList(dnsServers.split(" ")); - } - } - - // Set the search domains if they are not set in the config. - if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) { - String searchDomains = parameters[4].trim(); - if (!searchDomains.isEmpty()) { - mConfig.searchDomains = Arrays.asList(searchDomains.split(" ")); - } - } - - // Add a throw route for the VPN server endpoint, if one was specified. - if (endpointAddress instanceof Inet4Address) { - mConfig.routes.add(new RouteInfo( - new IpPrefix(endpointAddress, 32), null /*gateway*/, - null /*iface*/, RTN_THROW)); - } else if (endpointAddress instanceof Inet6Address) { - mConfig.routes.add(new RouteInfo( - new IpPrefix(endpointAddress, 128), null /*gateway*/, - null /*iface*/, RTN_THROW)); - } else { - Log.e(TAG, "Unknown IP address family for VPN endpoint: " - + endpointAddress); - } - - // Here is the last step and it must be done synchronously. - // Set the start time - mConfig.startTime = SystemClock.elapsedRealtime(); - - // Check if the thread was interrupted while we were waiting on the lock. - checkInterruptAndDelay(false); - - // Check if the interface is gone while we are waiting. - if (!mDeps.isInterfacePresent(Vpn.this, mConfig.interfaze)) { - throw new IllegalStateException(mConfig.interfaze + " is gone"); - } - - // Now INetworkManagementEventObserver is watching our back. - mInterface = mConfig.interfaze; - prepareStatusIntent(); - - agentConnect(); - - Log.i(TAG, "Connected!"); - } - } catch (Exception e) { - Log.i(TAG, "Aborting", e); - updateState(DetailedState.FAILED, e.getMessage()); - exitVpnRunner(); - } - } - - /** - * Check all daemons every two seconds. Return when one of them is stopped. - * The caller will move to the disconnected state when this function returns, - * which can happen if a daemon failed or if the VPN was torn down. - */ - private void waitForDaemonsToStop() throws InterruptedException { - if (!mNetworkInfo.isConnected()) { - return; - } - while (true) { - Thread.sleep(2000); - for (int i = 0; i < mDaemons.length; i++) { - if (mArguments[i] != null && mDeps.isServiceStopped(mDaemons[i])) { - return; - } - } - } - } - } - private void verifyCallingUidAndPackage(String packageName) { mDeps.verifyCallingUidAndPackage(mContext, packageName, mUserId); } @@ -4839,11 +4234,9 @@ public class Vpn { // Build intent first because the sessionKey will be reset after performing // VpnRunner.exit(). Also, cache mOwnerUID even if ownerUID will not be changed in // VpnRunner.exit() to prevent design being changed in the future. - // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from - // ConnectivityServiceTest. final int ownerUid = mOwnerUID; Intent intent = null; - if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) { + if (isVpnApp(mPackage)) { intent = buildVpnManagerEventIntent( VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, -1 /* errorClass */, -1 /* errorCode*/, mPackage, @@ -4884,12 +4277,8 @@ public class Vpn { // The underlying network, NetworkCapabilities and LinkProperties are not // necessary to send to VPN app since the purpose of this event is to notify // VPN app that VPN is deactivated by the user. - // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from - // ConnectivityServiceTest. - if (SdkLevel.isAtLeastT()) { - mEventChanges.log("[VMEvent] " + packageName + " stopped"); - sendEventToVpnManagerApp(intent, packageName); - } + mEventChanges.log("[VMEvent] " + packageName + " stopped"); + sendEventToVpnManagerApp(intent, packageName); } private boolean storeAppExclusionList(@NonNull String packageName, diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 7d0d5a73f093..ec6b5ea41339 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -559,7 +559,9 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice { HdmiDeviceInfo cecDeviceInfo = mService.getHdmiCecNetwork().getCecDeviceInfo(address); // If no non-default display name is available for the device, request the devices OSD name. - if (cecDeviceInfo != null && cecDeviceInfo.getDisplayName().equals( + // On TV devices, the OSD name is queried in NewDeviceAction instead. + if (!mService.isTvDevice() && cecDeviceInfo != null + && cecDeviceInfo.getDisplayName().equals( HdmiUtils.getDefaultDeviceName(address))) { mService.sendCecCommand( HdmiCecMessageBuilder.buildGiveOsdNameCommand( diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java index 7045e65a8936..d994849611f8 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java @@ -899,6 +899,9 @@ public class HdmiCecNetwork { * port id. */ int portIdToPath(int portId) { + if (portId == Constants.CEC_SWITCH_HOME) { + return getPhysicalAddress(); + } HdmiPortInfo portInfo = getPortInfo(portId); if (portInfo == null) { Slog.e(TAG, "Cannot find the port info: " + portId); diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java index 6147c10f85d5..f3532e5ce7e9 100644 --- a/services/core/java/com/android/server/hdmi/NewDeviceAction.java +++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java @@ -182,7 +182,7 @@ final class NewDeviceAction extends HdmiCecFeatureAction { .setVendorId(mVendorId) .setDisplayName(mDisplayName) .build(); - localDevice().mService.getHdmiCecNetwork().addCecDevice(deviceInfo); + localDevice().mService.getHdmiCecNetwork().updateCecDevice(deviceInfo); // Consume CEC messages we already got for this newly found device. tv().processDelayedMessages(mDeviceLogicalAddress); diff --git a/services/core/java/com/android/server/inputmethod/OWNERS b/services/core/java/com/android/server/inputmethod/OWNERS index 6e5eb5631112..aa638aa49fb3 100644 --- a/services/core/java/com/android/server/inputmethod/OWNERS +++ b/services/core/java/com/android/server/inputmethod/OWNERS @@ -3,6 +3,8 @@ set noparent roosa@google.com yukawa@google.com tarandeep@google.com +fstern@google.com +cosminbaies@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 fa95a348d8d3..c08b6d2301e8 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -243,6 +243,10 @@ public class LockSettingsService extends ILockSettings.Stub { private static final String MIGRATED_FRP2 = "migrated_frp2"; private static final String MIGRATED_KEYSTORE_NS = "migrated_keystore_namespace"; private static final String MIGRATED_SP_CE_ONLY = "migrated_all_users_to_sp_and_bound_ce"; + private static final String MIGRATED_SP_FULL = "migrated_all_users_to_sp_and_bound_keys"; + + private static final boolean FIX_UNLOCKED_DEVICE_REQUIRED_KEYS = + android.security.Flags.fixUnlockedDeviceRequiredKeysV2(); // Duration that LockSettingsService will store the gatekeeper password for. This allows // multiple biometric enrollments without prompting the user to enter their password via @@ -853,9 +857,11 @@ public class LockSettingsService extends ILockSettings.Stub { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) { - // Notify keystore that a new user was added. - final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); - AndroidKeyStoreMaintenance.onUserAdded(userHandle); + if (!FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { + // Notify keystore that a new user was added. + final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); + AndroidKeyStoreMaintenance.onUserAdded(userHandle); + } } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) { final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); mStorage.prefetchUser(userHandle); @@ -1019,24 +1025,53 @@ public class LockSettingsService extends ILockSettings.Stub { } mEarlyCreatedUsers = null; // no longer needed - // Also do a one-time migration of all users to SP-based credentials with the CE key - // encrypted by the SP. This is needed for the system user on the first boot of a - // device, as the system user is special and never goes through the user creation flow - // that other users do. It is also needed for existing users on a device upgraded from - // Android 13 or earlier, where users with no LSKF didn't necessarily have an SP, and if - // they did have an SP then their CE key wasn't encrypted by it. + // Do a one-time migration for any unsecured users: create the user's synthetic password + // if not already done, encrypt the user's CE key with the synthetic password if not + // already done, and create the user's Keystore super keys if not already done. + // + // This is needed for the following cases: + // + // - Finalizing the creation of the system user on the first boot of a device, as the + // system user is special and doesn't go through the normal user creation flow. + // + // - Upgrading from Android 13 or earlier, where unsecured users didn't necessarily have + // a synthetic password, and if they did have a synthetic password their CE key wasn't + // encrypted by it. Also, unsecured users didn't have Keystore super keys. // - // If this gets interrupted (e.g. by the device powering off), there shouldn't be a - // problem since this will run again on the next boot, and setCeStorageProtection() is - // okay with the CE key being already protected by the given secret. - if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) { - for (UserInfo user : mUserManager.getAliveUsers()) { - removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber); - synchronized (mSpManager) { - migrateUserToSpWithBoundCeKeyLocked(user.id); + // - Upgrading from Android 14, where unsecured users didn't have Keystore super keys. + // + // The end result is that all users, regardless of whether they are secured or not, have + // a synthetic password with all keys initialized and protected by it. + // + // Note: if this migration gets interrupted (e.g. by the device powering off), there + // shouldn't be a problem since this will run again on the next boot, and + // setCeStorageProtection() and initKeystoreSuperKeys(..., true) are idempotent. + if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { + if (!getBoolean(MIGRATED_SP_FULL, false, 0)) { + for (UserInfo user : mUserManager.getAliveUsers()) { + removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber); + synchronized (mSpManager) { + migrateUserToSpWithBoundKeysLocked(user.id); + } + } + setBoolean(MIGRATED_SP_FULL, true, 0); + } + } else { + if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) { + for (UserInfo user : mUserManager.getAliveUsers()) { + removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber); + synchronized (mSpManager) { + migrateUserToSpWithBoundCeKeyLocked(user.id); + } } + setString(MIGRATED_SP_CE_ONLY, "true", 0); + } + + if (getBoolean(MIGRATED_SP_FULL, false, 0)) { + // The FIX_UNLOCKED_DEVICE_REQUIRED_KEYS flag was enabled but then got disabled. + // Ensure the full migration runs again the next time the flag is enabled... + setBoolean(MIGRATED_SP_FULL, false, 0); } - setString(MIGRATED_SP_CE_ONLY, "true", 0); } mThirdPartyAppsStarted = true; @@ -1067,6 +1102,37 @@ public class LockSettingsService extends ILockSettings.Stub { } } + @GuardedBy("mSpManager") + private void migrateUserToSpWithBoundKeysLocked(@UserIdInt int userId) { + if (isUserSecure(userId)) { + Slogf.d(TAG, "User %d is secured; no migration needed", userId); + return; + } + long protectorId = getCurrentLskfBasedProtectorId(userId); + if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) { + Slogf.i(TAG, "Migrating unsecured user %d to SP-based credential", userId); + initializeSyntheticPassword(userId); + return; + } + Slogf.i(TAG, "Existing unsecured user %d has a synthetic password", userId); + AuthenticationResult result = mSpManager.unlockLskfBasedProtector( + getGateKeeperService(), protectorId, LockscreenCredential.createNone(), userId, + null); + SyntheticPassword sp = result.syntheticPassword; + if (sp == null) { + Slogf.wtf(TAG, "Failed to unwrap synthetic password for unsecured user %d", userId); + return; + } + // While setCeStorageProtection() is idempotent, it does log some error messages when called + // again. Skip it if we know it was already handled by an earlier upgrade to Android 14. + if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) { + Slogf.i(TAG, "Encrypting CE key of user %d with synthetic password", userId); + setCeStorageProtection(userId, sp); + } + Slogf.i(TAG, "Initializing Keystore super keys for user %d", userId); + initKeystoreSuperKeys(userId, sp, /* allowExisting= */ true); + } + /** * Returns the lowest password quality that still presents the same UI for entering it. * @@ -1348,8 +1414,22 @@ public class LockSettingsService extends ILockSettings.Stub { AndroidKeyStoreMaintenance.onUserPasswordChanged(userHandle, password); } + @VisibleForTesting /** Note: this method is overridden in unit tests */ + void initKeystoreSuperKeys(@UserIdInt int userId, SyntheticPassword sp, boolean allowExisting) { + final byte[] password = sp.deriveKeyStorePassword(); + try { + int res = AndroidKeyStoreMaintenance.initUserSuperKeys(userId, password, allowExisting); + if (res != 0) { + throw new IllegalStateException("Failed to initialize Keystore super keys for user " + + userId); + } + } finally { + Arrays.fill(password, (byte) 0); + } + } + private void unlockKeystore(int userId, SyntheticPassword sp) { - Authorization.onLockScreenEvent(false, userId, sp.deriveKeyStorePassword(), null); + Authorization.onDeviceUnlocked(userId, sp.deriveKeyStorePassword()); } @VisibleForTesting /** Note: this method is overridden in unit tests */ @@ -2071,6 +2151,9 @@ public class LockSettingsService extends ILockSettings.Stub { return; } onSyntheticPasswordUnlocked(userId, result.syntheticPassword); + if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { + unlockKeystore(userId, result.syntheticPassword); + } unlockCeStorage(userId, result.syntheticPassword); } } @@ -2350,6 +2433,16 @@ public class LockSettingsService extends ILockSettings.Stub { } private void createNewUser(@UserIdInt int userId, int userSerialNumber) { + + // Delete all Keystore keys for userId, just in case any were left around from a removed + // user with the same userId. This should be unnecessary, but we've been doing this for a + // long time, so for now we keep doing it just in case it's ever important. Don't wait + // until initKeystoreSuperKeys() to do this; that can be delayed if the user is being + // created during early boot, and maybe something will use Keystore before then. + if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { + AndroidKeyStoreMaintenance.onUserAdded(userId); + } + synchronized (mUserCreationAndRemovalLock) { // During early boot, don't actually create the synthetic password yet, but rather // automatically delay it to later. We do this because protecting the synthetic @@ -2756,7 +2849,7 @@ public class LockSettingsService extends ILockSettings.Stub { /** * Creates the synthetic password (SP) for the given user, protects it with an empty LSKF, and - * protects the user's CE key with a key derived from the SP. + * protects the user's CE storage key and Keystore super keys with keys derived from the SP. * * <p>This is called just once in the lifetime of the user: at user creation time (possibly * delayed until the time when Weaver is guaranteed to be available), or when upgrading from @@ -2775,6 +2868,9 @@ public class LockSettingsService extends ILockSettings.Stub { LockscreenCredential.createNone(), sp, userId); setCurrentLskfBasedProtectorId(protectorId, userId); setCeStorageProtection(userId, sp); + if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { + initKeystoreSuperKeys(userId, sp, /* allowExisting= */ false); + } onSyntheticPasswordCreated(userId, sp); Slogf.i(TAG, "Successfully initialized synthetic password for user %d", userId); return sp; @@ -2867,11 +2963,10 @@ public class LockSettingsService extends ILockSettings.Stub { /** * Changes the user's LSKF by creating an LSKF-based protector that uses the new LSKF (which may * be empty) and replacing the old LSKF-based protector with it. The SP itself is not changed. - * - * Also maintains the invariants described in {@link SyntheticPasswordManager} by - * setting/clearing the protection (by the SP) on the user's auth-bound Keystore keys when the - * LSKF is added/removed, respectively. If an LSKF is being added, then the Gatekeeper auth - * token is also refreshed. + * <p> + * Also maintains the invariants described in {@link SyntheticPasswordManager} by enrolling / + * deleting the synthetic password into Gatekeeper as the LSKF is set / cleared, and asking + * Keystore to delete the user's auth-bound keys when the LSKF is cleared. */ @GuardedBy("mSpManager") private long setLockCredentialWithSpLocked(LockscreenCredential credential, @@ -2890,7 +2985,9 @@ public class LockSettingsService extends ILockSettings.Stub { if (!mSpManager.hasSidForUser(userId)) { mSpManager.newSidForUser(getGateKeeperService(), sp, userId); mSpManager.verifyChallenge(getGateKeeperService(), sp, 0L, userId); - setKeystorePassword(sp.deriveKeyStorePassword(), userId); + if (!FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { + setKeystorePassword(sp.deriveKeyStorePassword(), userId); + } } } else { // Cache all profile password if they use unified work challenge. This will later be @@ -2901,7 +2998,11 @@ public class LockSettingsService extends ILockSettings.Stub { gateKeeperClearSecureUserId(userId); unlockCeStorage(userId, sp); unlockKeystore(userId, sp); - setKeystorePassword(null, userId); + if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) { + AndroidKeyStoreMaintenance.onUserLskfRemoved(userId); + } else { + setKeystorePassword(null, userId); + } removeBiometricsForUser(userId); } setCurrentLskfBasedProtectorId(newProtectorId, userId); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java index 4bac872dbaa9..17f2fcc5b9d8 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java @@ -155,43 +155,45 @@ class LockSettingsShellCommand extends ShellCommand { try (final PrintWriter pw = getOutPrintWriter();) { pw.println("lockSettings service commands:"); pw.println(""); - pw.println("NOTE: when lock screen is set, all commands require the --old <CREDENTIAL>" - + " argument."); + pw.println("NOTE: when a secure lock screen is set, most commands require the"); + pw.println("--old <CREDENTIAL> option."); pw.println(""); pw.println(" help"); pw.println(" Prints this help text."); pw.println(""); - pw.println(" get-disabled [--old <CREDENTIAL>] [--user USER_ID]"); - pw.println(" Checks whether lock screen is disabled."); + pw.println(" get-disabled [--user USER_ID]"); + pw.println(" Prints true if the lock screen is completely disabled, i.e. set to None."); + pw.println(" Otherwise prints false."); pw.println(""); - pw.println(" set-disabled [--old <CREDENTIAL>] [--user USER_ID] <true|false>"); - pw.println(" When true, disables lock screen."); + pw.println(" set-disabled [--user USER_ID] <true|false>"); + pw.println(" Sets whether the lock screen is disabled. If the lock screen is secure, this"); + pw.println(" has no immediate effect. I.e. this can only change between Swipe and None."); pw.println(""); pw.println(" set-pattern [--old <CREDENTIAL>] [--user USER_ID] <PATTERN>"); - pw.println(" Sets the lock screen as pattern, using the given PATTERN to unlock."); + pw.println(" Sets a secure lock screen that uses the given PATTERN. PATTERN is a series"); + pw.println(" of digits 1-9 that identify the cells of the pattern."); pw.println(""); pw.println(" set-pin [--old <CREDENTIAL>] [--user USER_ID] <PIN>"); - pw.println(" Sets the lock screen as PIN, using the given PIN to unlock."); + pw.println(" Sets a secure lock screen that uses the given PIN."); pw.println(""); pw.println(" set-password [--old <CREDENTIAL>] [--user USER_ID] <PASSWORD>"); - pw.println(" Sets the lock screen as password, using the given PASSWORD to unlock."); + pw.println(" Sets a secure lock screen that uses the given PASSWORD."); pw.println(""); pw.println(" clear [--old <CREDENTIAL>] [--user USER_ID]"); - pw.println(" Clears the lock credentials."); + pw.println(" Clears the lock credential."); pw.println(""); pw.println(" verify [--old <CREDENTIAL>] [--user USER_ID]"); - pw.println(" Verifies the lock credentials."); + pw.println(" Verifies the lock credential."); pw.println(""); pw.println(" remove-cache [--user USER_ID]"); pw.println(" Removes cached unified challenge for the managed profile."); pw.println(""); pw.println(" set-resume-on-reboot-provider-package <package_name>"); - pw.println(" Sets the package name for server based resume on reboot service " - + "provider."); + pw.println(" Sets the package name for server based resume on reboot service provider."); pw.println(""); pw.println(" require-strong-auth [--user USER_ID] <reason>"); - pw.println(" Requires the strong authentication. The current supported reasons: " - + "STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN."); + pw.println(" Requires strong authentication. The current supported reasons:"); + pw.println(" STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN."); pw.println(""); } } diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java index 8e9c21f5f35f..cc205d4a53bd 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java @@ -90,10 +90,15 @@ import java.util.Set; * * - The user's credential-encrypted storage is always protected by the SP. * - * - The user's auth-bound Keystore keys are protected by the SP, but only while an LSKF is set. - * This works by setting the user's Keystore and Gatekeeper passwords to SP-derived secrets, but - * only while an LSKF is set. When the LSKF is removed, these passwords are cleared, - * invalidating the user's auth-bound keys. + * - The user's Keystore superencryption keys are always protected by the SP. These in turn + * protect the Keystore keys that require user authentication, an unlocked device, or both. + * + * - A secret derived from the synthetic password is enrolled in Gatekeeper for the user, but only + * while the user has a (nonempty) LSKF. This enrollment has an associated ID called the Secure + * user ID or SID. This use of Gatekeeper, which is separate from the use of GateKeeper that may + * be used in the LSKF-based protector, makes it so that unlocking the synthetic password + * generates a HardwareAuthToken (but only when the user has LSKF). That HardwareAuthToken can + * be provided to KeyMint to authorize the use of the user's authentication-bound Keystore keys. * * Files stored on disk for each user: * For the SP itself, stored under NULL_PROTECTOR_ID: diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java index 1b7d1ba59b06..9a0b3914122c 100644 --- a/services/core/java/com/android/server/net/LockdownVpnTracker.java +++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java @@ -208,7 +208,7 @@ public class LockdownVpnTracker { // network is the system default. So, if the VPN is up and underlying network // (e.g., wifi) disconnects, CS will inform apps that the VPN's capabilities have // changed to match the new default network (e.g., cell). - mVpn.startLegacyVpnPrivileged(mProfile, network, egressProp); + mVpn.startLegacyVpnPrivileged(mProfile); } catch (IllegalStateException e) { mAcceptedEgressIface = null; Log.e(TAG, "Failed to start VPN", e); diff --git a/services/core/java/com/android/server/net/NetworkManagementService.java b/services/core/java/com/android/server/net/NetworkManagementService.java index a5a934f78420..681d1a0ee10a 100644 --- a/services/core/java/com/android/server/net/NetworkManagementService.java +++ b/services/core/java/com/android/server/net/NetworkManagementService.java @@ -327,10 +327,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub { /** * Notify our observers of a change in the data activity state of the interface */ - private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos, + private void notifyInterfaceClassActivity(int label, boolean isActive, long tsNanos, int uid) { invokeForAllObservers(o -> o.interfaceClassDataActivityChanged( - type, isActive, tsNanos, uid)); + label, isActive, tsNanos, uid)); } // Sync the state of the given chain with the native daemon. @@ -1059,17 +1059,25 @@ public class NetworkManagementService extends INetworkManagementService.Stub { Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode); return true; } - Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver"); + Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setDataSaverModeEnabled"); try { - final boolean changed = mNetdService.bandwidthEnableDataSaver(enable); - if (changed) { + if (SdkLevel.isAtLeastV()) { + // setDataSaverEnabled throws if it fails to set data saver. + mContext.getSystemService(ConnectivityManager.class) + .setDataSaverEnabled(enable); mDataSaverMode = enable; + return true; } else { - Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed"); + final boolean changed = mNetdService.bandwidthEnableDataSaver(enable); + if (changed) { + mDataSaverMode = enable; + } else { + Log.e(TAG, "setDataSaverMode(" + enable + "): failed to set iptables"); + } + return changed; } - return changed; - } catch (RemoteException e) { - Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e); + } catch (RemoteException | IllegalStateException e) { + Log.e(TAG, "setDataSaverMode(" + enable + "): failed with exception", e); return false; } finally { Trace.traceEnd(Trace.TRACE_TAG_NETWORK); diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java index e5616d04554d..ab0d0d2626db 100644 --- a/services/core/java/com/android/server/os/NativeTombstoneManager.java +++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java @@ -61,6 +61,7 @@ import java.util.Collections; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import java.util.concurrent.locks.ReentrantLock; /** * A class to manage native tombstones. @@ -74,6 +75,8 @@ public final class NativeTombstoneManager { private final Handler mHandler; private final TombstoneWatcher mWatcher; + private final ReentrantLock mTmpFileLock = new ReentrantLock(); + private final Object mLock = new Object(); @GuardedBy("mLock") @@ -112,7 +115,12 @@ public final class NativeTombstoneManager { // Clean up temporary files if they made it this far (e.g. if system server crashes). if (filename.endsWith(".tmp")) { - path.delete(); + mTmpFileLock.lock(); + try { + path.delete(); + } finally { + mTmpFileLock.unlock(); + } return; } @@ -128,7 +136,7 @@ public final class NativeTombstoneManager { if (parsedTombstone.isPresent()) { processName = parsedTombstone.get().getProcessName(); } - BootReceiver.addTombstoneToDropBox(mContext, path, isProtoFile, processName); + BootReceiver.addTombstoneToDropBox(mContext, path, isProtoFile, processName, mTmpFileLock); } private Optional<TombstoneFile> handleProtoTombstone(File path, boolean addToList) { diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java index f95f7bc0d165..0803bb662c70 100644 --- a/services/core/java/com/android/server/pm/AppDataHelper.java +++ b/services/core/java/com/android/server/pm/AppDataHelper.java @@ -122,7 +122,7 @@ public class AppDataHelper { StorageManagerInternal.class); for (UserInfo user : umInternal.getUsers(false /*excludeDying*/)) { final int flags; - if (StorageManager.isUserKeyUnlocked(user.id) + if (StorageManager.isCeStorageUnlocked(user.id) && smInternal.isCeStoragePrepared(user.id)) { flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } else if (umInternal.isUserRunning(user.id)) { @@ -404,7 +404,7 @@ public class AppDataHelper { // First look for stale data that doesn't belong, and check if things // have changed since we did our last restorecon if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) { - if (StorageManager.isFileEncrypted() && !StorageManager.isUserKeyUnlocked(userId)) { + if (StorageManager.isFileEncrypted() && !StorageManager.isCeStorageUnlocked(userId)) { throw new RuntimeException( "Yikes, someone asked us to reconcile CE storage while " + userId + " was still locked; this would have caused massive data loss!"); diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 78f1fa60b69f..723a3ae659c9 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -3538,7 +3538,7 @@ public class ComputerEngine implements Computer { @Override public int getPackageStartability(boolean safeMode, @NonNull String packageName, int callingUid, @UserIdInt int userId) { - final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId); + final boolean ceStorageUnlocked = StorageManager.isCeStorageUnlocked(userId); final PackageStateInternal ps = getPackageStateInternal(packageName); if (ps == null || shouldFilterApplication(ps, callingUid, userId) || !ps.getUserStateOrDefault(userId).isInstalled()) { @@ -3553,7 +3553,7 @@ public class ComputerEngine implements Computer { return PackageManagerService.PACKAGE_STARTABILITY_FROZEN; } - if (!userKeyUnlocked && !AndroidPackageUtils.isEncryptionAware(ps.getPkg())) { + if (!ceStorageUnlocked && !AndroidPackageUtils.isEncryptionAware(ps.getPkg())) { return PackageManagerService.PACKAGE_STARTABILITY_DIRECT_BOOT_UNSUPPORTED; } return PackageManagerService.PACKAGE_STARTABILITY_OK; diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java index fcaaa90dbc8a..c33af9b28b62 100644 --- a/services/core/java/com/android/server/pm/DumpHelper.java +++ b/services/core/java/com/android/server/pm/DumpHelper.java @@ -160,7 +160,7 @@ final class DumpHelper { pkg = snapshot.resolveInternalPackageName(pkg, PackageManager.VERSION_CODE_HIGHEST); - pw.println(mPermissionManager.checkPermission(perm, pkg, user)); + pw.println(mPermissionManager.checkPermission(pkg, perm, user)); return; } else if ("l".equals(cmd) || "libraries".equals(cmd)) { dumpState.setDump(DumpState.DUMP_LIBS); diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 8080e4074a17..988a32f3ffc7 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -486,20 +486,30 @@ final class InstallPackageHelper { pkgSetting.setLoadingProgress(1f); } + // TODO: passes the package name as an argument in a message to the handler for V+ + // so we don't need to rely on creating lambda objects so frequently. + if (UpdateOwnershipHelper.hasValidOwnershipDenyList(pkgSetting)) { + mPm.mHandler.post(() -> handleUpdateOwnerDenyList(pkgSetting)); + } + return pkg; + } + + private void handleUpdateOwnerDenyList(PackageSetting pkgSetting) { ArraySet<String> listItems = mUpdateOwnershipHelper.readUpdateOwnerDenyList(pkgSetting); if (listItems != null && !listItems.isEmpty()) { - mUpdateOwnershipHelper.addToUpdateOwnerDenyList(pkgSetting.getPackageName(), listItems); - for (String unownedPackage : listItems) { - PackageSetting unownedSetting = mPm.mSettings.getPackageLPr(unownedPackage); - SystemConfig config = SystemConfig.getInstance(); - if (unownedSetting != null - && config.getSystemAppUpdateOwnerPackageName(unownedPackage) == null) { - unownedSetting.setUpdateOwnerPackage(null); + mUpdateOwnershipHelper.addToUpdateOwnerDenyList(pkgSetting.getPackageName(), + listItems); + SystemConfig config = SystemConfig.getInstance(); + synchronized (mPm.mLock) { + for (String unownedPackage : listItems) { + PackageSetting unownedSetting = mPm.mSettings.getPackageLPr(unownedPackage); + if (unownedSetting != null + && config.getSystemAppUpdateOwnerPackageName(unownedPackage) == null) { + unownedSetting.setUpdateOwnerPackage(null); + } } } } - - return pkg; } /** diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 9ac983dfebeb..c401dab3a482 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -24,6 +24,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.Context; import android.content.pm.PackageStats; +import android.os.Binder; import android.os.Build; import android.os.CreateAppDataArgs; import android.os.CreateAppDataResult; @@ -34,9 +35,11 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.storage.CrateMetadata; import android.text.format.DateUtils; +import android.util.EventLog; import android.util.Slog; import com.android.internal.os.BackgroundThread; +import com.android.server.EventLogTags; import com.android.server.SystemService; import dalvik.system.BlockGuard; @@ -438,6 +441,26 @@ public class Installer extends SystemService { if (!checkBeforeRemote()) return; try { mInstalld.clearAppData(uuid, packageName, userId, flags, ceDataInode); + + final StackTraceElement[] elements = Thread.currentThread().getStackTrace(); + String className; + String methodName; + String fileName; + int lineNumber; + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + EventLog.writeEvent(EventLogTags.INSTALLER_CLEAR_APP_DATA_CALLER, pid, uid, packageName, + flags); + // Skip the first two elements since they are always the same, ie + // Thread#getStackTrace() and VMStack#getThreadStackTrace() + for (int i = 2; i < elements.length; i++) { + className = elements[i].getClassName(); + methodName = elements[i].getMethodName(); + fileName = elements[i].getFileName(); + lineNumber = elements[i].getLineNumber(); + EventLog.writeEvent(EventLogTags.INSTALLER_CLEAR_APP_DATA_CALL_STACK, methodName, + className, fileName, lineNumber); + } } catch (Exception e) { throw InstallerException.from(e); } diff --git a/services/core/java/com/android/server/pm/MovePackageHelper.java b/services/core/java/com/android/server/pm/MovePackageHelper.java index fef53d15c09d..4780ed1950b8 100644 --- a/services/core/java/com/android/server/pm/MovePackageHelper.java +++ b/services/core/java/com/android/server/pm/MovePackageHelper.java @@ -198,7 +198,8 @@ public final class MovePackageHelper { // If we're moving app data around, we need all the users unlocked if (moveCompleteApp) { for (int userId : installedUserIds) { - if (StorageManager.isFileEncrypted() && !StorageManager.isUserKeyUnlocked(userId)) { + if (StorageManager.isFileEncrypted() + && !StorageManager.isCeStorageUnlocked(userId)) { freezer.close(); throw new PackageManagerException(MOVE_FAILED_LOCKED_USER, "User " + userId + " must be unlocked"); diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 6a2ddc8f94b0..ea082cf77987 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -159,6 +159,9 @@ public class OtaDexoptService extends IOtaDexopt.Stub { if (pkgSetting.getPkg().isCoreApp()) { throw new IllegalStateException("Found a core app that's not important"); } + // Use REASON_FIRST_BOOT to query "pm.dexopt.first-boot" for the compiler filter, but + // the reason itself won't make it into the actual compiler reason because it will be + // overridden in otapreopt.cpp. mDexoptCommands.addAll(generatePackageDexopts(pkgSetting.getPkg(), pkgSetting, PackageManagerService.REASON_FIRST_BOOT)); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 20bd56d56945..a1c435af0452 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3460,7 +3460,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService UserManagerInternal umInternal = mInjector.getUserManagerInternal(); StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class); final int flags; - if (StorageManager.isUserKeyUnlocked(userId) && smInternal.isCeStoragePrepared(userId)) { + if (StorageManager.isCeStorageUnlocked(userId) && smInternal.isCeStoragePrepared(userId)) { flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } else if (umInternal.isUserRunning(userId)) { flags = StorageManager.FLAG_STORAGE_DE; @@ -4729,6 +4729,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService throw new SecurityException("Cannot clear data for a protected package: " + packageName); } + final int callingPid = Binder.getCallingPid(); + EventLog.writeEvent(EventLogTags.PM_CLEAR_APP_DATA_CALLER, callingPid, callingUid, + packageName); // Queue up an async operation since the package deletion may take a little while. mHandler.post(new Runnable() { @@ -4861,6 +4864,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService /* checkShell= */ false, "delete application cache files"); final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_INSTANT_APPS); + final int callingPid = Binder.getCallingPid(); + EventLog.writeEvent(EventLogTags.PM_CLEAR_APP_DATA_CALLER, callingPid, callingUid, + packageName); // Queue up an async operation since the package deletion may take a little while. mHandler.post(() -> { diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java index 8f8f4376d2cc..89619232eb04 100644 --- a/services/core/java/com/android/server/pm/StorageEventHelper.java +++ b/services/core/java/com/android/server/pm/StorageEventHelper.java @@ -183,7 +183,7 @@ public final class StorageEventHelper extends StorageEventListener { StorageManagerInternal.class); for (UserInfo user : mPm.mUserManager.getUsers(false /* includeDying */)) { final int flags; - if (StorageManager.isUserKeyUnlocked(user.id) + if (StorageManager.isCeStorageUnlocked(user.id) && smInternal.isCeStoragePrepared(user.id)) { flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } else if (umInternal.isUserRunning(user.id)) { diff --git a/services/core/java/com/android/server/pm/UpdateOwnershipHelper.java b/services/core/java/com/android/server/pm/UpdateOwnershipHelper.java index 43752f31a1a2..adac68b25749 100644 --- a/services/core/java/com/android/server/pm/UpdateOwnershipHelper.java +++ b/services/core/java/com/android/server/pm/UpdateOwnershipHelper.java @@ -48,7 +48,7 @@ public class UpdateOwnershipHelper { private final Object mLock = new Object(); - private static boolean hasValidOwnershipDenyList(PackageSetting pkgSetting) { + static boolean hasValidOwnershipDenyList(PackageSetting pkgSetting) { AndroidPackage pkg = pkgSetting.getPkg(); // we're checking for uses-permission for these priv permissions instead of grant as we're // only considering system apps to begin with, so presumed to be granted. diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java index 6d58d3401675..8adb5661ad1d 100644 --- a/services/core/java/com/android/server/pm/UserDataPreparer.java +++ b/services/core/java/com/android/server/pm/UserDataPreparer.java @@ -23,10 +23,10 @@ import android.content.pm.UserInfo; import android.os.Environment; import android.os.FileUtils; import android.os.RecoverySystem; -import android.os.storage.StorageManager; -import android.os.storage.VolumeInfo; import android.os.SystemProperties; import android.os.UserHandle; +import android.os.storage.StorageManager; +import android.os.storage.VolumeInfo; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -35,6 +35,7 @@ import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.utils.Slogf; import java.io.File; import java.io.IOException; @@ -43,7 +44,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.Set; /** * Helper class for preparing and destroying user storage @@ -65,31 +65,37 @@ class UserDataPreparer { /** * Prepare storage areas for given user on all mounted devices. */ - void prepareUserData(int userId, int userSerial, int flags) { + void prepareUserData(UserInfo userInfo, int flags) { synchronized (mInstallLock) { final StorageManager storage = mContext.getSystemService(StorageManager.class); /* * Internal storage must be prepared before adoptable storage, since the user's volume * keys are stored in their internal storage. */ - prepareUserDataLI(null /* internal storage */, userId, userSerial, flags, true); + prepareUserDataLI(null /* internal storage */, userInfo, flags, true); for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { final String volumeUuid = vol.getFsUuid(); if (volumeUuid != null) { - prepareUserDataLI(volumeUuid, userId, userSerial, flags, true); + prepareUserDataLI(volumeUuid, userInfo, flags, true); } } } } - private void prepareUserDataLI(String volumeUuid, int userId, int userSerial, int flags, + private void prepareUserDataLI(String volumeUuid, UserInfo userInfo, int flags, boolean allowRecover) { - // Prepare storage and verify that serial numbers are consistent; if - // there's a mismatch we need to destroy to avoid leaking data + final int userId = userInfo.id; + final int userSerial = userInfo.serialNumber; final StorageManager storage = mContext.getSystemService(StorageManager.class); + final boolean isNewUser = userInfo.lastLoggedInTime == 0; + Slogf.d(TAG, "Preparing user data; volumeUuid=%s, userId=%d, flags=0x%x, isNewUser=%s", + volumeUuid, userId, flags, isNewUser); try { + // Prepare CE and/or DE storage. storage.prepareUserStorage(volumeUuid, userId, userSerial, 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. if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) { enforceSerialNumber(getDataUserDeDirectory(volumeUuid, userId), userSerial); if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) { @@ -103,9 +109,10 @@ class UserDataPreparer { } } + // Prepare the app data directories. mInstaller.createUserData(volumeUuid, userId, userSerial, flags); - // CE storage is available after they are prepared. + // If applicable, record that the system user's CE storage has been prepared. if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && (userId == UserHandle.USER_SYSTEM)) { String propertyName = "sys.user." + userId + ".ce_available"; @@ -113,20 +120,31 @@ class UserDataPreparer { SystemProperties.set(propertyName, "true"); } } catch (Exception e) { - logCriticalInfo(Log.WARN, "Destroying user " + userId + " on volume " + volumeUuid - + " because we failed to prepare: " + e); - destroyUserDataLI(volumeUuid, userId, flags); - + // Failed to prepare user data. For new users, specifically users that haven't ever + // been unlocked, destroy the user data, and try again (if not already retried). This + // might be effective at resolving some errors, such as stale directories from a reused + // user ID. Don't auto-destroy data for existing users, since issues with existing + // users might be fixable via an OTA without having to wipe the user's data. + if (isNewUser) { + logCriticalInfo(Log.ERROR, "Destroying user " + userId + " on volume " + volumeUuid + + " because we failed to prepare: " + e); + destroyUserDataLI(volumeUuid, userId, flags); + } else { + logCriticalInfo(Log.ERROR, "Failed to prepare user " + userId + " on volume " + + volumeUuid + ": " + e); + } if (allowRecover) { // Try one last time; if we fail again we're really in trouble - prepareUserDataLI(volumeUuid, userId, userSerial, - flags | StorageManager.FLAG_STORAGE_DE, false); + prepareUserDataLI(volumeUuid, userInfo, flags | StorageManager.FLAG_STORAGE_DE, + false); } else { + // 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); - if (userId == UserHandle.USER_SYSTEM) { + if (isNewUser && userId == UserHandle.USER_SYSTEM && volumeUuid == null) { RecoverySystem.rebootPromptAndWipeUserData(mContext, - "prepareUserData failed for system user"); + "failed to prepare internal storage for system user"); } } catch (IOException e2) { throw new RuntimeException("error rebooting into recovery", e2); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index e5c19f575eba..68148482c68a 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1348,7 +1348,7 @@ public class UserManagerService extends IUserManager.Stub { } final boolean needToShowConfirmCredential = !dontAskCredential && mLockPatternUtils.isSecure(userId) - && (!hasUnifiedChallenge || !StorageManager.isUserKeyUnlocked(userId)); + && (!hasUnifiedChallenge || !StorageManager.isCeStorageUnlocked(userId)); if (needToShowConfirmCredential) { if (onlyIfCredentialNotRequired) { return false; @@ -4914,8 +4914,7 @@ public class UserManagerService extends IUserManager.Stub { // unlocked. We do this to ensure that CE storage isn't prepared before the CE key is // saved to disk. This also matches what is done for user 0. t.traceBegin("prepareUserData"); - mUserDataPreparer.prepareUserData(userId, userInfo.serialNumber, - StorageManager.FLAG_STORAGE_DE); + mUserDataPreparer.prepareUserData(userInfo, StorageManager.FLAG_STORAGE_DE); t.traceEnd(); t.traceBegin("LSS.createNewUser"); @@ -6199,12 +6198,11 @@ public class UserManagerService extends IUserManager.Stub { } TimingsTraceAndSlog t = new TimingsTraceAndSlog(); t.traceBegin("onBeforeStartUser-" + userId); - final int userSerial = userInfo.serialNumber; // Migrate only if build fingerprints mismatch boolean migrateAppsData = !PackagePartitions.FINGERPRINT.equals( userInfo.lastLoggedInFingerprint); t.traceBegin("prepareUserData"); - mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE); + mUserDataPreparer.prepareUserData(userInfo, StorageManager.FLAG_STORAGE_DE); t.traceEnd(); t.traceBegin("reconcileAppsData"); getPackageManagerInternal().reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE, @@ -6230,14 +6228,13 @@ public class UserManagerService extends IUserManager.Stub { if (userInfo == null) { return; } - final int userSerial = userInfo.serialNumber; // Migrate only if build fingerprints mismatch boolean migrateAppsData = !PackagePartitions.FINGERPRINT.equals( userInfo.lastLoggedInFingerprint); final TimingsTraceAndSlog t = new TimingsTraceAndSlog(); t.traceBegin("prepareUserData-" + userId); - mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_CE); + mUserDataPreparer.prepareUserData(userInfo, StorageManager.FLAG_STORAGE_CE); t.traceEnd(); StorageManagerInternal smInternal = LocalServices.getService(StorageManagerInternal.class); @@ -6992,9 +6989,9 @@ public class UserManagerService extends IUserManager.Stub { synchronized (mUserStates) { state = mUserStates.get(userId, -1); } - // Special case, in the stopping/shutdown state user key can still be unlocked + // Special case: in the stopping/shutdown state, CE storage can still be unlocked. if (state == UserState.STATE_STOPPING || state == UserState.STATE_SHUTDOWN) { - return StorageManager.isUserKeyUnlocked(userId); + return StorageManager.isCeStorageUnlocked(userId); } return (state == UserState.STATE_RUNNING_UNLOCKING) || (state == UserState.STATE_RUNNING_UNLOCKED); @@ -7011,9 +7008,9 @@ public class UserManagerService extends IUserManager.Stub { synchronized (mUserStates) { state = mUserStates.get(userId, -1); } - // Special case, in the stopping/shutdown state user key can still be unlocked + // Special case: in the stopping/shutdown state, CE storage can still be unlocked. if (state == UserState.STATE_STOPPING || state == UserState.STATE_SHUTDOWN) { - return StorageManager.isUserKeyUnlocked(userId); + return StorageManager.isCeStorageUnlocked(userId); } return state == UserState.STATE_RUNNING_UNLOCKED; } diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java index d0c346a63889..57f4a5ddb2bd 100644 --- a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java +++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java @@ -337,7 +337,8 @@ public class ArtStatsLogUtils { 0, // deprecated, used to be durationIncludingSleepMs 0, // optimizedPackagesCount 0, // packagesDependingOnBootClasspathCount - 0); // totalPackagesCount + 0, // totalPackagesCount + ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__PASS__PASS_UNKNOWN); } } } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 297ad73e054b..c24d5236f4f7 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1001,7 +1001,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { } synchronized (mLock) { - mAttributions.put(source.getToken(), source); + // Change the token for the AttributionSource we're storing, so that we don't store + // a strong reference to the original token inside the map itself. + mAttributions.put(source.getToken(), source.withDefaultToken()); } } @@ -1009,7 +1011,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { synchronized (mLock) { final AttributionSource cachedSource = mAttributions.get(source.getToken()); if (cachedSource != null) { - return cachedSource.equals(source); + return cachedSource.equalsExceptToken(source); } return false; } diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java index 0e99e7ee1daa..bd9738e43d41 100644 --- a/services/core/java/com/android/server/policy/PermissionPolicyService.java +++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java @@ -1315,7 +1315,8 @@ public final class PermissionPolicyService extends SystemService { } private boolean isTaskStartedFromLauncher(String currPkg, TaskInfo taskInfo) { - return currPkg.equals(taskInfo.baseActivity.getPackageName()) + return taskInfo.baseActivity != null + && currPkg.equals(taskInfo.baseActivity.getPackageName()) && isLauncherIntent(taskInfo.baseIntent); } diff --git a/services/core/java/com/android/server/power/OWNERS b/services/core/java/com/android/server/power/OWNERS index a0e91ad7cf45..94340ec26cba 100644 --- a/services/core/java/com/android/server/power/OWNERS +++ b/services/core/java/com/android/server/power/OWNERS @@ -2,4 +2,6 @@ michaelwr@google.com santoscordon@google.com philipjunker@google.com -per-file ThermalManagerService.java=wvw@google.com +per-file ThermalManagerService.java=file:/THERMAL_OWNERS +per-file LowPowerStandbyController.java=qingxun@google.com +per-file LowPowerStandbyControllerInternal.java=qingxun@google.com diff --git a/services/core/java/com/android/server/power/TEST_MAPPING b/services/core/java/com/android/server/power/TEST_MAPPING index cf1bfc3b555f..fbfe291b1659 100644 --- a/services/core/java/com/android/server/power/TEST_MAPPING +++ b/services/core/java/com/android/server/power/TEST_MAPPING @@ -20,6 +20,7 @@ "name": "FrameworksServicesTests", "options": [ {"include-filter": "com.android.server.power"}, + {"exclude-filter": "com.android.server.power.BatteryStatsTests"}, {"exclude-annotation": "android.platform.test.annotations.FlakyTest"}, {"exclude-annotation": "androidx.test.filters.FlakyTest"} ] @@ -38,7 +39,8 @@ { "name": "FrameworksServicesTests", "options": [ - {"include-filter": "com.android.server.power"} + {"include-filter": "com.android.server.power"}, + {"exclude-filter": "com.android.server.power.BatteryStatsTests"} ] } ] diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java index 27329e20bc8d..5dff9ef5076e 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -8203,18 +8203,18 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("mBsi") private void ensureMultiStateCounters(long timestampMs) { - if (mProcStateTimeMs != null) { - return; + if (mProcStateTimeMs == null) { + mProcStateTimeMs = + new TimeInFreqMultiStateCounter(mBsi.mOnBatteryTimeBase, + PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(), + timestampMs); + } + if (mProcStateScreenOffTimeMs == null) { + mProcStateScreenOffTimeMs = + new TimeInFreqMultiStateCounter(mBsi.mOnBatteryScreenOffTimeBase, + PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(), + timestampMs); } - - mProcStateTimeMs = - new TimeInFreqMultiStateCounter(mBsi.mOnBatteryTimeBase, - PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(), - timestampMs); - mProcStateScreenOffTimeMs = - new TimeInFreqMultiStateCounter(mBsi.mOnBatteryScreenOffTimeBase, - PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(), - timestampMs); } @GuardedBy("mBsi") diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java index 7b0fe9a9abc7..a01bac688fbf 100644 --- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java +++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java @@ -266,10 +266,10 @@ public class AppDataRollbackHelper { } /** - * @return {@code true} iff. {@code userId} is locked on an FBE device. + * @return {@code true} iff the credential-encrypted storage for {@code userId} is locked. */ @VisibleForTesting public boolean isUserCredentialLocked(int userId) { - return StorageManager.isFileEncrypted() && !StorageManager.isUserKeyUnlocked(userId); + return StorageManager.isFileEncrypted() && !StorageManager.isCeStorageUnlocked(userId); } } diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index 9128974fa9d3..cc892a03a141 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -1281,12 +1281,19 @@ public class StatsPullAtomService extends SystemService { private void addBytesTransferByTagAndMeteredAtoms(@NonNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData) { + // Workaround for 5G NSA mode, see {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}. + // 5G NSA mode means the primary cell is LTE with a secondary connection to an + // NR cell. To mitigate risk, NetworkStats is currently storing this state as + // a fake RAT type rather than storing the boolean separately. + final boolean is5GNsa = statsExt.ratType == NetworkStatsManager.NETWORK_TYPE_5G_NSA; + for (NetworkStats.Entry entry : statsExt.stats) { pulledData.add(FrameworkStatsLog.buildStatsEvent( FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.getUid(), entry.getMetered() == NetworkStats.METERED_YES, entry.getTag(), entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), - entry.getTxPackets())); + entry.getTxPackets(), + is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType)); } } @@ -1414,6 +1421,7 @@ public class StatsPullAtomService extends SystemService { final NetworkStats nonTaggedStats = NetworkStatsUtils.fromPublicNetworkStats(queryNonTaggedStats); + queryNonTaggedStats.close(); if (!includeTags) return nonTaggedStats; final android.app.usage.NetworkStats queryTaggedStats = @@ -1422,6 +1430,7 @@ public class StatsPullAtomService extends SystemService { currentTimeInMillis); final NetworkStats taggedStats = NetworkStatsUtils.fromPublicNetworkStats(queryTaggedStats); + queryTaggedStats.close(); return nonTaggedStats.add(taggedStats); } diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 635e11be3a16..327f74f081da 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -829,7 +829,7 @@ public class TrustManagerService extends SystemService { } final boolean trusted; - if (android.security.Flags.fixUnlockedDeviceRequiredKeys()) { + if (android.security.Flags.fixUnlockedDeviceRequiredKeysV2()) { trusted = getUserTrustStateInner(id) == TrustState.TRUSTED; } else { trusted = aggregateIsTrusted(id); @@ -867,21 +867,19 @@ public class TrustManagerService extends SystemService { mDeviceLockedForUser.put(userId, locked); } if (changed) { - dispatchDeviceLocked(userId, locked); - Authorization.onLockScreenEvent(locked, userId, null, - getBiometricSids(userId)); + notifyTrustAgentsOfDeviceLockState(userId, locked); + notifyKeystoreOfDeviceLockState(userId, locked); // Also update the user's profiles who have unified challenge, since they // share the same unlocked state (see {@link #isDeviceLocked(int)}) for (int profileHandle : mUserManager.getEnabledProfileIds(userId)) { if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(profileHandle)) { - Authorization.onLockScreenEvent(locked, profileHandle, null, - getBiometricSids(profileHandle)); + notifyKeystoreOfDeviceLockState(profileHandle, locked); } } } } - private void dispatchDeviceLocked(int userId, boolean isLocked) { + private void notifyTrustAgentsOfDeviceLockState(int userId, boolean isLocked) { for (int i = 0; i < mActiveAgents.size(); i++) { AgentInfo agent = mActiveAgents.valueAt(i); if (agent.userId == userId) { @@ -894,6 +892,17 @@ public class TrustManagerService extends SystemService { } } + private void notifyKeystoreOfDeviceLockState(int userId, boolean isLocked) { + if (isLocked) { + Authorization.onDeviceLocked(userId, getBiometricSids(userId)); + } 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 + // the password. However, for unlocks with biometric or trust agent, this is required. + Authorization.onDeviceUnlocked(userId, /* password= */ null); + } + } + private void dispatchEscrowTokenActivatedLocked(long handle, int userId) { for (int i = 0; i < mActiveAgents.size(); i++) { AgentInfo agent = mActiveAgents.valueAt(i); @@ -1427,10 +1436,10 @@ public class TrustManagerService extends SystemService { } } - private long[] getBiometricSids(int userId) { + private @NonNull long[] getBiometricSids(int userId) { BiometricManager biometricManager = mContext.getSystemService(BiometricManager.class); if (biometricManager == null) { - return null; + return new long[0]; } return biometricManager.getAuthenticatorIds(userId); } @@ -1647,8 +1656,22 @@ public class TrustManagerService extends SystemService { fout.printf(" User \"%s\" (id=%d, flags=%#x)", user.name, user.id, user.flags); if (!user.supportsSwitchToByUser()) { - fout.println("(managed profile)"); - fout.println(" disabled because switching to this user is not possible."); + final boolean locked; + if (user.isProfile()) { + if (mLockPatternUtils.isSeparateProfileChallengeEnabled(user.id)) { + fout.print(" (profile with separate challenge)"); + locked = isDeviceLockedInner(user.id); + } else { + fout.print(" (profile with unified challenge)"); + locked = isDeviceLockedInner(resolveProfileParent(user.id)); + } + } else { + fout.println(" (user that cannot be switched to)"); + locked = isDeviceLockedInner(user.id); + } + fout.println(": deviceLocked=" + dumpBool(locked)); + fout.println( + " Trust agents disabled because switching to this user is not possible."); return; } if (isCurrent) { @@ -1715,8 +1738,7 @@ public class TrustManagerService extends SystemService { mDeviceLockedForUser.put(userId, locked); } - Authorization.onLockScreenEvent(locked, userId, null, - getBiometricSids(userId)); + notifyKeystoreOfDeviceLockState(userId, locked); if (locked) { try { diff --git a/services/core/java/com/android/server/utils/OWNERS b/services/core/java/com/android/server/utils/OWNERS index be91611deccc..fbc0b56c2eb7 100644 --- a/services/core/java/com/android/server/utils/OWNERS +++ b/services/core/java/com/android/server/utils/OWNERS @@ -10,3 +10,8 @@ per-file Watcher.java = file:/services/core/java/com/android/server/pm/OWNERS per-file Watcher.java = shombert@google.com per-file EventLogger.java = file:/platform/frameworks/av:/media/janitors/media_solutions_OWNERS per-file EventLogger.java = jmtrivi@google.com + +# Bug component : 158088 = per-file AnrTimer*.java +per-file AnrTimer*.java = file:/PERFORMANCE_OWNERS + +per-file flags.aconfig = file:/PERFORMANCE_OWNERS diff --git a/services/core/java/com/android/server/vcn/VcnContext.java b/services/core/java/com/android/server/vcn/VcnContext.java index d958222ea407..9213d96ad4ca 100644 --- a/services/core/java/com/android/server/vcn/VcnContext.java +++ b/services/core/java/com/android/server/vcn/VcnContext.java @@ -18,6 +18,8 @@ package com.android.server.vcn; import android.annotation.NonNull; import android.content.Context; +import android.net.vcn.FeatureFlags; +import android.net.vcn.FeatureFlagsImpl; import android.os.Looper; import java.util.Objects; @@ -31,6 +33,7 @@ public class VcnContext { @NonNull private final Context mContext; @NonNull private final Looper mLooper; @NonNull private final VcnNetworkProvider mVcnNetworkProvider; + @NonNull private final FeatureFlags mFeatureFlags; private final boolean mIsInTestMode; public VcnContext( @@ -42,6 +45,9 @@ public class VcnContext { mLooper = Objects.requireNonNull(looper, "Missing looper"); mVcnNetworkProvider = Objects.requireNonNull(vcnNetworkProvider, "Missing networkProvider"); mIsInTestMode = isInTestMode; + + // Auto-generated class + mFeatureFlags = new FeatureFlagsImpl(); } @NonNull @@ -63,6 +69,11 @@ public class VcnContext { return mIsInTestMode; } + @NonNull + public FeatureFlags getFeatureFlags() { + return mFeatureFlags; + } + /** * 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 d480ddb092eb..54c97dd37941 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -1222,6 +1222,14 @@ public class VcnGatewayConnection extends StateMachine { @VisibleForTesting(visibility = Visibility.PRIVATE) void setSafeModeAlarm() { + final boolean isFlagSafeModeConfigEnabled = mVcnContext.getFeatureFlags().safeModeConfig(); + logVdbg("isFlagSafeModeConfigEnabled " + isFlagSafeModeConfigEnabled); + + if (isFlagSafeModeConfigEnabled && !mConnectionConfig.isSafeModeEnabled()) { + logVdbg("setSafeModeAlarm: safe mode disabled"); + return; + } + logVdbg("Setting safe mode alarm; mCurrentToken: " + mCurrentToken); // Only schedule a NEW alarm if none is already set. diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 18a6254ca115..82a954d4178f 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4214,6 +4214,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A Slog.v(TAG_APP, "Keeping entry during removeHistory for activity " + this); } } + if (task != null && task.mKillProcessesOnDestroyed) { + mTaskSupervisor.removeTimeoutOfKillProcessesOnProcessDied(this, task); + } // upgrade transition trigger to task if this is the last activity since it means we are // closing the task. final WindowContainer trigger = remove && task != null && task.getChildCount() == 1 diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index b34ae1930048..ecdca93ccaaa 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -1891,7 +1891,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // DestroyActivityItem may be called first. final ActivityRecord top = task.getTopMostActivity(); if (top != null && top.finishing && !top.mAppStopped && top.lastVisibleTime > 0 - && !task.mKillProcessesOnDestroyed) { + && !task.mKillProcessesOnDestroyed && top.hasProcess()) { task.mKillProcessesOnDestroyed = true; mHandler.sendMessageDelayed( mHandler.obtainMessage(KILL_TASK_PROCESSES_TIMEOUT_MSG, task), @@ -1901,8 +1901,26 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { killTaskProcessesIfPossible(task); } + void removeTimeoutOfKillProcessesOnProcessDied(@NonNull ActivityRecord r, @NonNull Task task) { + if (r.packageName.equals(task.getBasePackageName())) { + task.mKillProcessesOnDestroyed = false; + mHandler.removeMessages(KILL_TASK_PROCESSES_TIMEOUT_MSG, task); + } + } + void killTaskProcessesOnDestroyedIfNeeded(Task task) { if (task == null || !task.mKillProcessesOnDestroyed) return; + final int[] numDestroyingActivities = new int[1]; + task.forAllActivities(r -> { + if (r.finishing && r.lastVisibleTime > 0 && r.attachedToProcess()) { + numDestroyingActivities[0]++; + } + }); + if (numDestroyingActivities[0] > 1) { + // Skip if there are still destroying activities. When the last activity reports + // destroyed, the number will be 1 to proceed the kill. + return; + } mHandler.removeMessages(KILL_TASK_PROCESSES_TIMEOUT_MSG, task); killTaskProcessesIfPossible(task); } @@ -2763,7 +2781,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } break; case KILL_TASK_PROCESSES_TIMEOUT_MSG: { final Task task = (Task) msg.obj; - if (task.mKillProcessesOnDestroyed) { + if (task.mKillProcessesOnDestroyed && task.hasActivity()) { Slog.i(TAG, "Destroy timeout of remove-task, attempt to kill " + task); killTaskProcessesIfPossible(task); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 7addaa265ab2..1c8770b123bb 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4668,6 +4668,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp scheduleAnimation(); mWmService.mH.post(() -> InputMethodManagerInternal.get().onImeParentChanged()); + } else if (mImeControlTarget != null && mImeControlTarget == mImeLayeringTarget) { + // Even if the IME surface parent is not changed, the layer target belonging to the + // parent may have changes. Then attempt to reassign if the IME control target is + // possible to be the relative layer. + final SurfaceControl lastRelativeLayer = mImeWindowsContainer.getLastRelativeLayer(); + if (lastRelativeLayer != mImeLayeringTarget.mSurfaceControl) { + assignRelativeLayerForIme(getSyncTransaction(), false /* forceUpdate */); + if (lastRelativeLayer != mImeWindowsContainer.getLastRelativeLayer()) { + scheduleAnimation(); + } + } } } diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS index f8c39d0906a0..cd704478aa83 100644 --- a/services/core/java/com/android/server/wm/OWNERS +++ b/services/core/java/com/android/server/wm/OWNERS @@ -18,5 +18,8 @@ rgl@google.com yunfanc@google.com wilsonshih@google.com -per-file BackgroundActivityStartController.java = set noparent -per-file BackgroundActivityStartController.java = brufino@google.com, topjohnwu@google.com, achim@google.com, ogunwale@google.com, louischang@google.com, lus@google.com +# Files related to background activity launches +per-file Background*Start* = set noparent +per-file Background*Start* = file:/BAL_OWNERS +per-file Background*Start* = ogunwale@google.com, louischang@google.com + diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 9a0e47de7873..eba9bf669d47 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1637,8 +1637,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return false; } - if (!StorageManager.isUserKeyUnlocked(mCurrentUser)) { - // Can't launch home on secondary display areas if device is still locked. + if (!StorageManager.isCeStorageUnlocked(mCurrentUser)) { + // Can't launch home on secondary display areas if CE storage is still locked. return false; } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 3063d46208c2..f2346e6eab5d 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4626,7 +4626,7 @@ class Task extends TaskFragment { // Expanding pip into new rotation, so create a rotation leash // until the display is rotated. topActivity.getOrCreateFixedRotationLeash( - topActivity.getSyncTransaction()); + topActivity.getPendingTransaction()); } lastParentBeforePip.moveToFront("movePinnedActivityToOriginalTask"); } @@ -6135,6 +6135,7 @@ class Task extends TaskFragment { // Avoid resuming activities on secondary displays since we don't want bubble // activities to be resumed while bubble is still collapsed. // TODO(b/113840485): Having keyguard going away state for secondary displays. + && display != null && display.isDefaultDisplay) { return false; } @@ -6510,11 +6511,11 @@ class Task extends TaskFragment { mActivityType = ACTIVITY_TYPE_STANDARD; } - if (mActivityType != ACTIVITY_TYPE_STANDARD + if (!DisplayContent.alwaysCreateRootTask(tda.getWindowingMode(), mActivityType) && mActivityType != ACTIVITY_TYPE_UNDEFINED) { - // For now there can be only one root task of a particular non-standard activity - // type on a display. So, get that ignoring whatever windowing mode it is - // currently in. + // Only Recents or Standard activity types are allowed to have more than one + // root task on a display, this is independent of whatever windowing mode it + // is currently in. Task rootTask = tda.getRootTask(WINDOWING_MODE_UNDEFINED, mActivityType); if (rootTask != null) { throw new IllegalArgumentException("Root task=" + rootTask + " of activityType=" diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 0152666a830d..4cab3a29f136 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2635,6 +2635,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return mLastLayer; } + SurfaceControl getLastRelativeLayer() { + return mLastRelativeToLayer; + } + protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) { if (mSurfaceFreezer.hasLeash()) { // When the freezer has created animation leash parent for the window, set the layer diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 06978a5338ea..0a5b9eb270a1 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3276,7 +3276,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // just kill it. And if it is a window of foreground activity, the activity can be // restarted automatically if needed. Slog.w(TAG, "Exception thrown during dispatchAppVisibility " + this, e); - android.os.Process.killProcess(mSession.mPid); + if (android.os.Process.getUidForPid(mSession.mPid) == mSession.mUid) { + android.os.Process.killProcess(mSession.mPid); + } } } diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS index bc294902f0fc..fd9d4a44b65d 100644 --- a/services/core/jni/OWNERS +++ b/services/core/jni/OWNERS @@ -29,3 +29,6 @@ per-file com_android_server_tv_* = file:/media/java/android/media/tv/OWNERS per-file com_android_server_vibrator_* = file:/services/core/java/com/android/server/vibrator/OWNERS 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 diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp index 81a547290d5e..a8e6f689b424 100644 --- a/services/incremental/IncrementalService.cpp +++ b/services/incremental/IncrementalService.cpp @@ -910,7 +910,7 @@ void IncrementalService::disallowReadLogs(StorageId storageId) { constants().readLogsDisabledMarkerName), 0777, idFromMetadata(metadata), {})) { //{.metadata = {metadata.data(), (IncFsSize)metadata.size()}})) { - LOG(ERROR) << "Failed to make marker file for storageId: " << storageId; + LOG(ERROR) << "Failed to make marker file for storageId: " << storageId << " err: " << -err; return; } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 3610542c7caf..f1f5d8359f42 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1451,8 +1451,6 @@ public final class SystemServer implements Dumpable { boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice", false); - boolean isEmulator = SystemProperties.get("ro.boot.qemu").equals("1"); - boolean isWatch = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WATCH); @@ -2261,7 +2259,7 @@ public final class SystemServer implements Dumpable { if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST) || mPackageManager.hasSystemFeature( PackageManager.FEATURE_USB_ACCESSORY) - || isEmulator) { + || Build.IS_EMULATOR) { // Manage USB host and device support t.traceBegin("StartUsbService"); mSystemServiceManager.startService(USB_SERVICE_CLASS); diff --git a/services/midi/OWNERS b/services/midi/OWNERS index f4d51f91b51b..683cae1b0f3a 100644 --- a/services/midi/OWNERS +++ b/services/midi/OWNERS @@ -1 +1,3 @@ philburk@google.com +robertwu@google.com +elaurent@google.com #{LAST_RESORT_SUGGESTION} diff --git a/services/proguard.flags b/services/proguard.flags index e11e613adb5c..88561b460b05 100644 --- a/services/proguard.flags +++ b/services/proguard.flags @@ -14,13 +14,20 @@ } # APIs referenced by dependent JAR files and modules --keep @interface android.annotation.SystemApi +# TODO(b/300514883): Pull @SystemApi keep rules from system-api.pro. +-keep interface android.annotation.SystemApi -keep @android.annotation.SystemApi class * { public protected *; } -keepclasseswithmembers class * { @android.annotation.SystemApi *; } +# Also ensure nested classes are kept. This is overly conservative, but handles +# cases where such classes aren't explicitly marked @SystemApi. +-if @android.annotation.SystemApi class * +-keep public class <1>$** { + public protected *; +} # Derivatives of SystemService and other services created via reflection -keep,allowoptimization,allowaccessmodification class * extends com.android.server.SystemService { @@ -38,15 +45,16 @@ public static void write(...); } -# Binder interfaces --keep,allowoptimization,allowaccessmodification class * extends android.os.IInterface --keep,allowoptimization,allowaccessmodification class * extends android.os.IHwInterface - # Various classes subclassed in or referenced via JNI in ethernet-service -keep public class android.net.** { *; } -keep,allowoptimization,allowaccessmodification class com.android.net.module.util.* { *; } -keep,allowoptimization,allowaccessmodification public class com.android.server.net.IpConfigStore { *; } -keep,allowoptimization,allowaccessmodification public class com.android.server.net.BaseNetworkObserver { *; } +-keep,allowoptimization,allowaccessmodification class com.android.server.display.feature.DisplayManagerFlags { *; } +-keep,allowoptimization,allowaccessmodification class android.app.admin.flags.FeatureFlagsImpl { *; } +-keep,allowoptimization,allowaccessmodification class com.android.server.input.NativeInputManagerService$NativeImpl { *; } +-keep,allowoptimization,allowaccessmodification class com.android.server.ThreadPriorityBooster { *; } +-keep,allowaccessmodification class android.app.admin.flags.Flags { *; } # Referenced via CarServiceHelperService in car-frameworks-service (avoid removing) -keep public class com.android.server.utils.Slogf { *; } @@ -99,9 +107,6 @@ -keep,allowoptimization,allowaccessmodification class com.android.server.input.InputManagerService { <methods>; } --keep,allowoptimization,allowaccessmodification class com.android.server.input.NativeInputManagerService$NativeImpl { - <methods>; -} -keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbHostManager { *** usbDeviceRemoved(...); *** usbDeviceAdded(...); 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 afbe352ad676..e5be4d9aa755 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 @@ -21,6 +21,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -56,6 +58,7 @@ public class UserDataPreparerTest { private static final int TEST_USER_SERIAL = 1000; private static final int TEST_USER_ID = 10; + private static final UserInfo TEST_USER = new UserInfo(); private TestUserDataPreparer mUserDataPreparer; @@ -72,6 +75,8 @@ public class UserDataPreparerTest { @Before public void setup() { + TEST_USER.id = TEST_USER_ID; + TEST_USER.serialNumber = TEST_USER_SERIAL; Context ctx = InstrumentationRegistry.getContext(); FileUtils.deleteContents(ctx.getCacheDir()); mInstallLock = new Object(); @@ -92,8 +97,7 @@ public class UserDataPreparerTest { userDeDir.mkdirs(); File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID); systemDeDir.mkdirs(); - mUserDataPreparer - .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_DE); + 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)); verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID), @@ -110,8 +114,7 @@ public class UserDataPreparerTest { userCeDir.mkdirs(); File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID); systemCeDir.mkdirs(); - mUserDataPreparer - .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_CE); + 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)); verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID), @@ -123,6 +126,28 @@ public class UserDataPreparerTest { } @Test + 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), + eq(StorageManager.FLAG_STORAGE_CE)); + mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); + verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID), + eq(StorageManager.FLAG_STORAGE_CE)); + } + + @Test + 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), + eq(StorageManager.FLAG_STORAGE_CE)); + mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); + verify(mStorageManagerMock, never()).destroyUserStorage(isNull(String.class), + eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); + } + + @Test public void testDestroyUserData_De_DoesNotDestroyCe() throws Exception { // Add file in CE storage File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java new file mode 100644 index 000000000000..a0beb174dc94 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.am; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.annotation.NonNull; +import android.app.usage.UsageStatsManagerInternal; +import android.content.ComponentName; +import android.content.Context; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManagerInternal; +import android.content.pm.ResolveInfo; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.TestLooperManager; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.SparseArray; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.server.AlarmManagerInternal; +import com.android.server.DropBoxManagerInternal; +import com.android.server.LocalServices; +import com.android.server.appop.AppOpsService; +import com.android.server.wm.ActivityTaskManagerService; + +import org.junit.Rule; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.File; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; + +public abstract class BaseBroadcastQueueTest { + + static final int USER_GUEST = 11; + + static final String PACKAGE_ANDROID = "android"; + static final String PACKAGE_PHONE = "com.android.phone"; + static final String PACKAGE_RED = "com.example.red"; + static final String PACKAGE_GREEN = "com.example.green"; + static final String PACKAGE_BLUE = "com.example.blue"; + static final String PACKAGE_YELLOW = "com.example.yellow"; + static final String PACKAGE_ORANGE = "com.example.orange"; + + static final String PROCESS_SYSTEM = "system"; + + static final String CLASS_RED = "com.example.red.Red"; + static final String CLASS_GREEN = "com.example.green.Green"; + static final String CLASS_BLUE = "com.example.blue.Blue"; + static final String CLASS_YELLOW = "com.example.yellow.Yellow"; + static final String CLASS_ORANGE = "com.example.orange.Orange"; + + static final BroadcastProcessQueue.BroadcastPredicate BROADCAST_PREDICATE_ANY = + (r, i) -> true; + + @Rule + public final ApplicationExitInfoTest.ServiceThreadRule + mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule(); + + @Mock + AppOpsService mAppOpsService; + @Mock + PackageManagerInternal mPackageManagerInt; + @Mock + UsageStatsManagerInternal mUsageStatsManagerInt; + @Mock + DropBoxManagerInternal mDropBoxManagerInt; + @Mock + AlarmManagerInternal mAlarmManagerInt; + @Mock + ProcessList mProcessList; + + Context mContext; + ActivityManagerService mAms; + BroadcastConstants mConstants; + BroadcastSkipPolicy mSkipPolicy; + HandlerThread mHandlerThread; + TestLooperManager mLooper; + AtomicInteger mNextPid; + + /** + * Map from PID to registered registered runtime receivers. + */ + SparseArray<ReceiverList> mRegisteredReceivers = new SparseArray<>(); + + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + mHandlerThread = new HandlerThread(getTag()); + mHandlerThread.start(); + // Pause all event processing until a test chooses to resume + mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() + .acquireLooperManager(mHandlerThread.getLooper())); + mNextPid = new AtomicInteger(100); + + LocalServices.removeServiceForTest(DropBoxManagerInternal.class); + LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt); + LocalServices.removeServiceForTest(PackageManagerInternal.class); + LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt); + LocalServices.removeServiceForTest(AlarmManagerInternal.class); + LocalServices.addService(AlarmManagerInternal.class, mAlarmManagerInt); + doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent(); + doNothing().when(mPackageManagerInt).setPackageStoppedState(any(), anyBoolean(), anyInt()); + doAnswer((invocation) -> { + return getUidForPackage(invocation.getArgument(0)); + }).when(mPackageManagerInt).getPackageUid(any(), anyLong(), eq(UserHandle.USER_SYSTEM)); + + final ActivityManagerService realAms = new ActivityManagerService( + new TestInjector(mContext), mServiceThreadRule.getThread()); + realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext); + realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper()); + realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal()); + realAms.mOomAdjuster = spy(realAms.mOomAdjuster); + realAms.mPackageManagerInt = mPackageManagerInt; + realAms.mUsageStatsService = mUsageStatsManagerInt; + realAms.mProcessesReady = true; + mAms = spy(realAms); + + mSkipPolicy = spy(new BroadcastSkipPolicy(mAms)); + doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any()); + doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any()); + + mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS); + } + + public void tearDown() throws Exception { + mHandlerThread.quit(); + } + + static int getUidForPackage(@NonNull String packageName) { + switch (packageName) { + case PACKAGE_ANDROID: return android.os.Process.SYSTEM_UID; + case PACKAGE_PHONE: return android.os.Process.PHONE_UID; + case PACKAGE_RED: return android.os.Process.FIRST_APPLICATION_UID + 1; + case PACKAGE_GREEN: return android.os.Process.FIRST_APPLICATION_UID + 2; + case PACKAGE_BLUE: return android.os.Process.FIRST_APPLICATION_UID + 3; + case PACKAGE_YELLOW: return android.os.Process.FIRST_APPLICATION_UID + 4; + case PACKAGE_ORANGE: return android.os.Process.FIRST_APPLICATION_UID + 5; + default: throw new IllegalArgumentException(); + } + } + + static int getUidForPackage(@NonNull String packageName, int userId) { + return UserHandle.getUid(userId, getUidForPackage(packageName)); + } + + private class TestInjector extends ActivityManagerService.Injector { + TestInjector(Context context) { + super(context); + } + + @Override + public AppOpsService getAppOpsService(File recentAccessesFile, File storageFile, + Handler handler) { + return mAppOpsService; + } + + @Override + public Handler getUiHandler(ActivityManagerService service) { + return mHandlerThread.getThreadHandler(); + } + + @Override + public ProcessList getProcessList(ActivityManagerService service) { + return mProcessList; + } + } + + abstract String getTag(); + + static ApplicationInfo makeApplicationInfo(String packageName) { + return makeApplicationInfo(packageName, packageName, UserHandle.USER_SYSTEM); + } + + static ApplicationInfo makeApplicationInfo(String packageName, String processName, int userId) { + final ApplicationInfo ai = new ApplicationInfo(); + ai.packageName = packageName; + ai.processName = processName; + ai.uid = getUidForPackage(packageName, userId); + return ai; + } + + static ResolveInfo withPriority(ResolveInfo info, int priority) { + info.priority = priority; + return info; + } + + static BroadcastFilter withPriority(BroadcastFilter filter, int priority) { + filter.setPriority(priority); + return filter; + } + + static ResolveInfo makeManifestReceiver(String packageName, String name) { + return makeManifestReceiver(packageName, name, UserHandle.USER_SYSTEM); + } + + static ResolveInfo makeManifestReceiver(String packageName, String name, int userId) { + return makeManifestReceiver(packageName, packageName, name, userId); + } + + static ResolveInfo makeManifestReceiver(String packageName, String processName, + String name, int userId) { + final ResolveInfo ri = new ResolveInfo(); + ri.activityInfo = new ActivityInfo(); + ri.activityInfo.packageName = packageName; + ri.activityInfo.processName = processName; + ri.activityInfo.name = name; + ri.activityInfo.applicationInfo = makeApplicationInfo(packageName, processName, userId); + return ri; + } + + BroadcastFilter makeRegisteredReceiver(ProcessRecord app) { + return makeRegisteredReceiver(app, 0); + } + + BroadcastFilter makeRegisteredReceiver(ProcessRecord app, int priority) { + final ReceiverList receiverList = mRegisteredReceivers.get(app.getPid()); + return makeRegisteredReceiver(receiverList, priority); + } + + static BroadcastFilter makeRegisteredReceiver(ReceiverList receiverList, int priority) { + final IntentFilter filter = new IntentFilter(); + filter.setPriority(priority); + final BroadcastFilter res = new BroadcastFilter(filter, receiverList, + receiverList.app.info.packageName, null, null, null, receiverList.uid, + receiverList.userId, false, false, true); + receiverList.add(res); + return res; + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java index ff04728912ef..2378416f8bd0 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java @@ -31,17 +31,6 @@ import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_ORDERE import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_PRIORITIZED; import static com.android.server.am.BroadcastProcessQueue.insertIntoRunnableList; import static com.android.server.am.BroadcastProcessQueue.removeFromRunnableList; -import static com.android.server.am.BroadcastQueueTest.CLASS_BLUE; -import static com.android.server.am.BroadcastQueueTest.CLASS_GREEN; -import static com.android.server.am.BroadcastQueueTest.CLASS_RED; -import static com.android.server.am.BroadcastQueueTest.CLASS_YELLOW; -import static com.android.server.am.BroadcastQueueTest.PACKAGE_BLUE; -import static com.android.server.am.BroadcastQueueTest.PACKAGE_GREEN; -import static com.android.server.am.BroadcastQueueTest.PACKAGE_RED; -import static com.android.server.am.BroadcastQueueTest.PACKAGE_YELLOW; -import static com.android.server.am.BroadcastQueueTest.getUidForPackage; -import static com.android.server.am.BroadcastQueueTest.makeManifestReceiver; -import static com.android.server.am.BroadcastQueueTest.withPriority; import static com.android.server.am.BroadcastRecord.isReceiverEquals; import static com.google.common.truth.Truth.assertThat; @@ -74,17 +63,15 @@ import android.appwidget.AppWidgetManager; import android.content.IIntentReceiver; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; import android.media.AudioManager; import android.os.Bundle; import android.os.BundleMerger; import android.os.DropBoxManager; -import android.os.HandlerThread; import android.os.Process; import android.os.SystemClock; -import android.os.TestLooperManager; import android.os.UserHandle; -import android.provider.Settings; import android.util.IndentingPrintWriter; import android.util.Pair; @@ -108,11 +95,12 @@ import java.util.List; import java.util.Objects; @SmallTest -public final class BroadcastQueueModernImplTest { +public final class BroadcastQueueModernImplTest extends BaseBroadcastQueueTest { + private static final String TAG = "BroadcastQueueModernImplTest"; + private static final int TEST_UID = android.os.Process.FIRST_APPLICATION_UID; private static final int TEST_UID2 = android.os.Process.FIRST_APPLICATION_UID + 1; - @Mock ActivityManagerService mAms; @Mock ProcessRecord mProcess; @Mock BroadcastProcessQueue mQueue1; @@ -120,11 +108,6 @@ public final class BroadcastQueueModernImplTest { @Mock BroadcastProcessQueue mQueue3; @Mock BroadcastProcessQueue mQueue4; - HandlerThread mHandlerThread; - TestLooperManager mLooper; - - BroadcastConstants mConstants; - private BroadcastSkipPolicy mSkipPolicy; BroadcastQueueModernImpl mImpl; BroadcastProcessQueue mHead; @@ -136,22 +119,12 @@ public final class BroadcastQueueModernImplTest { @Before public void setUp() throws Exception { - mHandlerThread = new HandlerThread(getClass().getSimpleName()); - mHandlerThread.start(); - - // Pause all event processing until a test chooses to resume - mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() - .acquireLooperManager(mHandlerThread.getLooper())); + super.setUp(); - mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS); mConstants.DELAY_URGENT_MILLIS = -120_000; mConstants.DELAY_NORMAL_MILLIS = 10_000; mConstants.DELAY_CACHED_MILLIS = 120_000; - mSkipPolicy = spy(new BroadcastSkipPolicy(mAms)); - doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any()); - doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any()); - final BroadcastHistory emptyHistory = new BroadcastHistory(mConstants) { public void addBroadcastToHistoryLocked(BroadcastRecord original) { // Ignored @@ -169,7 +142,12 @@ public final class BroadcastQueueModernImplTest { @After public void tearDown() throws Exception { - mHandlerThread.quit(); + super.tearDown(); + } + + @Override + public String getTag() { + return TAG; } /** @@ -225,11 +203,6 @@ public final class BroadcastQueueModernImplTest { List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)), false); } - private BroadcastRecord makeOrderedBroadcastRecord(Intent intent) { - return makeBroadcastRecord(intent, BroadcastOptions.makeBasic(), - List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)), true); - } - private BroadcastRecord makeBroadcastRecord(Intent intent, List receivers) { return makeBroadcastRecord(intent, BroadcastOptions.makeBasic(), receivers, false); } @@ -246,8 +219,8 @@ public final class BroadcastQueueModernImplTest { private BroadcastRecord makeBroadcastRecord(Intent intent, BroadcastOptions options, List receivers, IIntentReceiver resultTo, boolean ordered) { - return new BroadcastRecord(mImpl, intent, mProcess, PACKAGE_RED, null, 21, 42, false, null, - null, null, null, AppOpsManager.OP_NONE, options, receivers, null, resultTo, + return new BroadcastRecord(mImpl, intent, mProcess, PACKAGE_RED, null, 21, TEST_UID, false, + null, null, null, null, AppOpsManager.OP_NONE, options, receivers, null, resultTo, Activity.RESULT_OK, null, null, ordered, false, false, UserHandle.USER_SYSTEM, BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN); } @@ -259,12 +232,12 @@ public final class BroadcastQueueModernImplTest { private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue, BroadcastRecord record, int recordIndex, long enqueueTime) { - queue.enqueueOrReplaceBroadcast(record, recordIndex, (r, i) -> { - throw new UnsupportedOperationException(); - }); record.enqueueTime = enqueueTime; record.enqueueRealTime = enqueueTime; record.enqueueClockTime = enqueueTime; + queue.enqueueOrReplaceBroadcast(record, recordIndex, (r, i) -> { + throw new UnsupportedOperationException(); + }); } @Test @@ -419,6 +392,7 @@ public final class BroadcastQueueModernImplTest { assertFalse(queue.isRunnable()); assertEquals(BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER, queue.getRunnableAtReason()); + assertTrue(queue.shouldBeDeferred()); assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); } @@ -445,6 +419,7 @@ public final class BroadcastQueueModernImplTest { assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt); assertTrue(queue.isRunnable()); assertEquals(BroadcastProcessQueue.REASON_CACHED, queue.getRunnableAtReason()); + assertTrue(queue.shouldBeDeferred()); assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); } @@ -526,11 +501,13 @@ public final class BroadcastQueueModernImplTest { queue.invalidateRunnableAt(); assertThat(queue.getRunnableAt()).isGreaterThan(airplaneRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); mConstants.MAX_PENDING_BROADCASTS = 1; queue.invalidateRunnableAt(); assertThat(queue.getRunnableAt()).isAtMost(airplaneRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_MAX_PENDING, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); } @Test @@ -549,10 +526,12 @@ public final class BroadcastQueueModernImplTest { queue.setProcessAndUidState(mProcess, true, false); assertThat(queue.getRunnableAt()).isLessThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_FOREGROUND, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); queue.setProcessAndUidState(mProcess, false, false); assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); } @Test @@ -570,6 +549,7 @@ public final class BroadcastQueueModernImplTest { assertThat(queue.getRunnableAt()).isLessThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_TOP_PROCESS, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); doReturn(ActivityManager.PROCESS_STATE_SERVICE).when(mProcess).getSetProcState(); queue.setProcessAndUidState(mProcess, false, false); @@ -580,6 +560,7 @@ public final class BroadcastQueueModernImplTest { List.of(makeMockRegisteredReceiver())), 0); assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); } @Test @@ -594,16 +575,19 @@ public final class BroadcastQueueModernImplTest { assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); doReturn(true).when(mProcess).isPersistent(); queue.setProcessAndUidState(mProcess, false, false); assertThat(queue.getRunnableAt()).isLessThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_PERSISTENT, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); doReturn(false).when(mProcess).isPersistent(); queue.setProcessAndUidState(mProcess, false, false); assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); } @Test @@ -618,6 +602,31 @@ public final class BroadcastQueueModernImplTest { assertThat(queue.getRunnableAt()).isEqualTo(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_CORE_UID, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); + } + + @Test + public void testRunnableAt_freezableCoreUid() { + final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, + "com.android.bluetooth", Process.BLUETOOTH_UID); + + // Mark the process as freezable + queue.setProcessAndUidState(mProcess, false, true); + final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); + final BroadcastOptions options = BroadcastOptions.makeWithDeferUntilActive(true); + final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, options, + List.of(makeMockRegisteredReceiver()), false); + enqueueOrReplaceBroadcast(queue, timeTickRecord, 0); + + assertEquals(Long.MAX_VALUE, queue.getRunnableAt()); + assertEquals(BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER, + queue.getRunnableAtReason()); + assertTrue(queue.shouldBeDeferred()); + + queue.setProcessAndUidState(mProcess, false, false); + assertThat(queue.getRunnableAt()).isEqualTo(timeTickRecord.enqueueTime); + assertEquals(BroadcastProcessQueue.REASON_CORE_UID, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); } /** @@ -1553,6 +1562,216 @@ public final class BroadcastQueueModernImplTest { verifyPendingRecords(redQueue, List.of(userPresent, timeTick)); } + @Test + public void testDeliveryDeferredForCached() throws Exception { + final ProcessRecord greenProcess = makeProcessRecord(makeApplicationInfo(PACKAGE_GREEN)); + final ProcessRecord redProcess = makeProcessRecord(makeApplicationInfo(PACKAGE_RED)); + + final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); + final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, + List.of(makeRegisteredReceiver(greenProcess, 0))); + + final Intent batteryChanged = new Intent(Intent.ACTION_BATTERY_CHANGED); + final BroadcastOptions optionsBatteryChanged = + BroadcastOptions.makeWithDeferUntilActive(true); + final BroadcastRecord batteryChangedRecord = makeBroadcastRecord(batteryChanged, + optionsBatteryChanged, + List.of(makeRegisteredReceiver(greenProcess, 10), + makeRegisteredReceiver(redProcess, 0)), + false /* ordered */); + + mImpl.enqueueBroadcastLocked(timeTickRecord); + mImpl.enqueueBroadcastLocked(batteryChangedRecord); + + final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN, + getUidForPackage(PACKAGE_GREEN)); + final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED, + getUidForPackage(PACKAGE_RED)); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, greenQueue.getRunnableAtReason()); + assertFalse(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_BLOCKED, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // Simulate process state change + greenQueue.setProcessAndUidState(greenProcess, false /* uidForeground */, + true /* processFreezable */); + greenQueue.updateDeferredStates(mImpl.mBroadcastConsumerDeferApply, + mImpl.mBroadcastConsumerDeferClear); + + assertEquals(BroadcastProcessQueue.REASON_CACHED, greenQueue.getRunnableAtReason()); + assertTrue(greenQueue.shouldBeDeferred()); + // Once the broadcasts to green process are deferred, broadcasts to red process + // shouldn't be blocked anymore. + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // All broadcasts to green process should be deferred. + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_DEFERRED, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + + final Intent packageChanged = new Intent(Intent.ACTION_PACKAGE_CHANGED); + final BroadcastRecord packageChangedRecord = makeBroadcastRecord(packageChanged, + List.of(makeRegisteredReceiver(greenProcess, 0))); + mImpl.enqueueBroadcastLocked(packageChangedRecord); + + assertEquals(BroadcastProcessQueue.REASON_CACHED, greenQueue.getRunnableAtReason()); + assertTrue(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // All broadcasts to the green process, including the newly enqueued one, should be + // deferred. + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_DEFERRED, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + + // Simulate process state change + greenQueue.setProcessAndUidState(greenProcess, false /* uidForeground */, + false /* processFreezable */); + greenQueue.updateDeferredStates(mImpl.mBroadcastConsumerDeferApply, + mImpl.mBroadcastConsumerDeferClear); + + assertEquals(BroadcastProcessQueue.REASON_NORMAL, greenQueue.getRunnableAtReason()); + assertFalse(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + } + + @Test + public void testDeliveryDeferredForCached_withInfiniteDeferred() throws Exception { + final ProcessRecord greenProcess = makeProcessRecord(makeApplicationInfo(PACKAGE_GREEN)); + final ProcessRecord redProcess = makeProcessRecord(makeApplicationInfo(PACKAGE_RED)); + + final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); + final BroadcastOptions optionsTimeTick = BroadcastOptions.makeWithDeferUntilActive(true); + final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, optionsTimeTick, + List.of(makeRegisteredReceiver(greenProcess, 0)), false /* ordered */); + + final Intent batteryChanged = new Intent(Intent.ACTION_BATTERY_CHANGED); + final BroadcastOptions optionsBatteryChanged = + BroadcastOptions.makeWithDeferUntilActive(true); + final BroadcastRecord batteryChangedRecord = makeBroadcastRecord(batteryChanged, + optionsBatteryChanged, + List.of(makeRegisteredReceiver(greenProcess, 10), + makeRegisteredReceiver(redProcess, 0)), + false /* ordered */); + + mImpl.enqueueBroadcastLocked(timeTickRecord); + mImpl.enqueueBroadcastLocked(batteryChangedRecord); + + final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN, + getUidForPackage(PACKAGE_GREEN)); + final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED, + getUidForPackage(PACKAGE_RED)); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, greenQueue.getRunnableAtReason()); + assertFalse(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_BLOCKED, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // Simulate process state change + greenQueue.setProcessAndUidState(greenProcess, false /* uidForeground */, + true /* processFreezable */); + greenQueue.updateDeferredStates(mImpl.mBroadcastConsumerDeferApply, + mImpl.mBroadcastConsumerDeferClear); + + assertEquals(BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER, + greenQueue.getRunnableAtReason()); + assertTrue(greenQueue.shouldBeDeferred()); + // Once the broadcasts to green process are deferred, broadcasts to red process + // shouldn't be blocked anymore. + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // All broadcasts to green process should be deferred. + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_DEFERRED, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + + final Intent packageChanged = new Intent(Intent.ACTION_PACKAGE_CHANGED); + final BroadcastOptions optionsPackageChanged = + BroadcastOptions.makeWithDeferUntilActive(true); + final BroadcastRecord packageChangedRecord = makeBroadcastRecord(packageChanged, + optionsPackageChanged, + List.of(makeRegisteredReceiver(greenProcess, 0)), false /* ordered */); + mImpl.enqueueBroadcastLocked(packageChangedRecord); + + assertEquals(BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER, + greenQueue.getRunnableAtReason()); + assertTrue(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // All broadcasts to the green process, including the newly enqueued one, should be + // deferred. + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_DEFERRED, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + + // Simulate process state change + greenQueue.setProcessAndUidState(greenProcess, false /* uidForeground */, + false /* processFreezable */); + greenQueue.updateDeferredStates(mImpl.mBroadcastConsumerDeferApply, + mImpl.mBroadcastConsumerDeferClear); + + assertEquals(BroadcastProcessQueue.REASON_NORMAL, greenQueue.getRunnableAtReason()); + assertFalse(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + } + + // TODO: Reuse BroadcastQueueTest.makeActiveProcessRecord() + private ProcessRecord makeProcessRecord(ApplicationInfo info) { + final ProcessRecord r = spy(new ProcessRecord(mAms, info, info.processName, info.uid)); + r.setPid(mNextPid.incrementAndGet()); + return r; + } + + BroadcastFilter makeRegisteredReceiver(ProcessRecord app, int priority) { + final IIntentReceiver receiver = mock(IIntentReceiver.class); + final ReceiverList receiverList = new ReceiverList(mAms, app, app.getPid(), app.info.uid, + UserHandle.getUserId(app.info.uid), receiver); + return makeRegisteredReceiver(receiverList, priority); + } + private Intent createPackageChangedIntent(int uid, List<String> componentNameList) { final Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED); packageChangedIntent.putExtra(Intent.EXTRA_UID, uid); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java index 73eb237fa9e7..e91472670c2d 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java @@ -62,58 +62,36 @@ import android.app.BroadcastOptions; import android.app.IApplicationThread; import android.app.UidObserver; import android.app.usage.UsageEvents.Event; -import android.app.usage.UsageStatsManagerInternal; import android.content.ComponentName; -import android.content.Context; import android.content.IIntentReceiver; import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; -import android.content.pm.ResolveInfo; import android.os.Binder; import android.os.Bundle; import android.os.DeadObjectException; -import android.os.Handler; -import android.os.HandlerThread; import android.os.IBinder; import android.os.PowerExemptionManager; import android.os.SystemClock; -import android.os.TestLooperManager; import android.os.UserHandle; -import android.provider.Settings; import android.util.Log; import android.util.Pair; -import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import androidx.test.filters.MediumTest; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.server.AlarmManagerInternal; -import com.android.server.DropBoxManagerInternal; -import com.android.server.LocalServices; -import com.android.server.am.ActivityManagerService.Injector; -import com.android.server.appop.AppOpsService; -import com.android.server.wm.ActivityTaskManagerService; - import org.junit.After; import org.junit.Assume; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.mockito.ArgumentMatcher; import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.verification.VerificationMode; -import java.io.File; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.Writer; @@ -125,7 +103,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; import java.util.function.UnaryOperator; @@ -135,13 +113,9 @@ import java.util.function.UnaryOperator; @MediumTest @RunWith(Parameterized.class) @SuppressWarnings("GuardedBy") -public class BroadcastQueueTest { +public class BroadcastQueueTest extends BaseBroadcastQueueTest { private static final String TAG = "BroadcastQueueTest"; - @Rule - public final ApplicationExitInfoTest.ServiceThreadRule - mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule(); - private final Impl mImpl; private enum Impl { @@ -149,30 +123,8 @@ public class BroadcastQueueTest { MODERN, } - private Context mContext; - private HandlerThread mHandlerThread; - private TestLooperManager mLooper; - private AtomicInteger mNextPid; - - @Mock - private AppOpsService mAppOpsService; - @Mock - private ProcessList mProcessList; - @Mock - private DropBoxManagerInternal mDropBoxManagerInt; - @Mock - private PackageManagerInternal mPackageManagerInt; - @Mock - private UsageStatsManagerInternal mUsageStatsManagerInt; - @Mock - private AlarmManagerInternal mAlarmManagerInt; - - private ActivityManagerService mAms; private BroadcastQueue mQueue; - BroadcastConstants mConstants; - private BroadcastSkipPolicy mSkipPolicy; private UidObserver mUidObserver; - private UidObserver mUidCachedStateObserver; /** * Desired behavior of the next @@ -182,11 +134,6 @@ public class BroadcastQueueTest { ProcessStartBehavior.SUCCESS); /** - * Map from PID to registered registered runtime receivers. - */ - private SparseArray<ReceiverList> mRegisteredReceivers = new SparseArray<>(); - - /** * Collection of all active processes during current test run. */ private List<ProcessRecord> mActiveProcesses = new ArrayList<>(); @@ -207,41 +154,8 @@ public class BroadcastQueueTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + super.setUp(); - mHandlerThread = new HandlerThread(TAG); - mHandlerThread.start(); - - // Pause all event processing until a test chooses to resume - mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() - .acquireLooperManager(mHandlerThread.getLooper())); - - mNextPid = new AtomicInteger(100); - - LocalServices.removeServiceForTest(DropBoxManagerInternal.class); - LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt); - LocalServices.removeServiceForTest(PackageManagerInternal.class); - LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt); - LocalServices.removeServiceForTest(AlarmManagerInternal.class); - LocalServices.addService(AlarmManagerInternal.class, mAlarmManagerInt); - doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent(); - doNothing().when(mPackageManagerInt).setPackageStoppedState(any(), anyBoolean(), anyInt()); - doAnswer((invocation) -> { - return getUidForPackage(invocation.getArgument(0)); - }).when(mPackageManagerInt).getPackageUid(any(), anyLong(), eq(UserHandle.USER_SYSTEM)); - - final ActivityManagerService realAms = new ActivityManagerService( - new TestInjector(mContext), mServiceThreadRule.getThread()); - realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext); - realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper()); - realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal()); - realAms.mOomAdjuster = spy(realAms.mOomAdjuster); - realAms.mPackageManagerInt = mPackageManagerInt; - realAms.mUsageStatsService = mUsageStatsManagerInt; - realAms.mProcessesReady = true; - mAms = spy(realAms); doAnswer((invocation) -> { Log.v(TAG, "Intercepting startProcessLocked() for " + Arrays.toString(invocation.getArguments())); @@ -320,21 +234,11 @@ public class BroadcastQueueTest { return null; }).when(mAms).registerUidObserver(any(), anyInt(), eq(ActivityManager.PROCESS_STATE_TOP), any()); - doAnswer((invocation) -> { - mUidCachedStateObserver = invocation.getArgument(0); - return null; - }).when(mAms).registerUidObserver(any(), anyInt(), - eq(ActivityManager.PROCESS_STATE_LAST_ACTIVITY), any()); - mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS); - mConstants.TIMEOUT = 100; + mConstants.TIMEOUT = 200; mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT = 0; mConstants.PENDING_COLD_START_CHECK_INTERVAL_MILLIS = 500; - mSkipPolicy = spy(new BroadcastSkipPolicy(mAms)); - doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any()); - doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any()); - final BroadcastHistory emptyHistory = new BroadcastHistory(mConstants) { public void addBroadcastToHistoryLocked(BroadcastRecord original) { // Ignored @@ -357,7 +261,7 @@ public class BroadcastQueueTest { @After public void tearDown() throws Exception { - mHandlerThread.quit(); + super.tearDown(); // Verify that all processes have finished handling broadcasts for (ProcessRecord app : mActiveProcesses) { @@ -368,26 +272,9 @@ public class BroadcastQueueTest { } } - private class TestInjector extends Injector { - TestInjector(Context context) { - super(context); - } - - @Override - public AppOpsService getAppOpsService(File recentAccessesFile, File storageFile, - Handler handler) { - return mAppOpsService; - } - - @Override - public Handler getUiHandler(ActivityManagerService service) { - return mHandlerThread.getThreadHandler(); - } - - @Override - public ProcessList getProcessList(ActivityManagerService service) { - return mProcessList; - } + @Override + public String getTag() { + return TAG; } private enum ProcessStartBehavior { @@ -533,62 +420,6 @@ public class BroadcastQueueTest { return Pair.create(app.getPid(), intent.getAction()); } - static ApplicationInfo makeApplicationInfo(String packageName) { - return makeApplicationInfo(packageName, packageName, UserHandle.USER_SYSTEM); - } - - static ApplicationInfo makeApplicationInfo(String packageName, String processName, int userId) { - final ApplicationInfo ai = new ApplicationInfo(); - ai.packageName = packageName; - ai.processName = processName; - ai.uid = getUidForPackage(packageName, userId); - return ai; - } - - static ResolveInfo withPriority(ResolveInfo info, int priority) { - info.priority = priority; - return info; - } - - static BroadcastFilter withPriority(BroadcastFilter filter, int priority) { - filter.setPriority(priority); - return filter; - } - - static ResolveInfo makeManifestReceiver(String packageName, String name) { - return makeManifestReceiver(packageName, name, UserHandle.USER_SYSTEM); - } - - static ResolveInfo makeManifestReceiver(String packageName, String name, int userId) { - return makeManifestReceiver(packageName, packageName, name, userId); - } - - static ResolveInfo makeManifestReceiver(String packageName, String processName, String name, - int userId) { - final ResolveInfo ri = new ResolveInfo(); - ri.activityInfo = new ActivityInfo(); - ri.activityInfo.packageName = packageName; - ri.activityInfo.processName = processName; - ri.activityInfo.name = name; - ri.activityInfo.applicationInfo = makeApplicationInfo(packageName, processName, userId); - return ri; - } - - private BroadcastFilter makeRegisteredReceiver(ProcessRecord app) { - return makeRegisteredReceiver(app, 0); - } - - private BroadcastFilter makeRegisteredReceiver(ProcessRecord app, int priority) { - final ReceiverList receiverList = mRegisteredReceivers.get(app.getPid()); - final IntentFilter filter = new IntentFilter(); - filter.setPriority(priority); - final BroadcastFilter res = new BroadcastFilter(filter, receiverList, - receiverList.app.info.packageName, null, null, null, receiverList.uid, - receiverList.userId, false, false, true); - receiverList.add(res); - return res; - } - private BroadcastRecord makeBroadcastRecord(Intent intent, ProcessRecord callerApp, List<Object> receivers) { return makeBroadcastRecord(intent, callerApp, BroadcastOptions.makeBasic(), @@ -707,6 +538,9 @@ public class BroadcastQueueTest { private void waitForIdle() throws Exception { mLooper.release(); mQueue.waitForIdle(LOG_WRITER_INFO); + final CountDownLatch latch = new CountDownLatch(1); + mHandlerThread.getThreadHandler().post(latch::countDown); + latch.await(); mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() .acquireLooperManager(mHandlerThread.getLooper())); } @@ -772,41 +606,6 @@ public class BroadcastQueueTest { eq(userId), anyInt(), anyInt(), any()); } - static final int USER_GUEST = 11; - - static final String PACKAGE_ANDROID = "android"; - static final String PACKAGE_PHONE = "com.android.phone"; - static final String PACKAGE_RED = "com.example.red"; - static final String PACKAGE_GREEN = "com.example.green"; - static final String PACKAGE_BLUE = "com.example.blue"; - static final String PACKAGE_YELLOW = "com.example.yellow"; - static final String PACKAGE_ORANGE = "com.example.orange"; - - static final String PROCESS_SYSTEM = "system"; - - static final String CLASS_RED = "com.example.red.Red"; - static final String CLASS_GREEN = "com.example.green.Green"; - static final String CLASS_BLUE = "com.example.blue.Blue"; - static final String CLASS_YELLOW = "com.example.yellow.Yellow"; - static final String CLASS_ORANGE = "com.example.orange.Orange"; - - static int getUidForPackage(@NonNull String packageName) { - switch (packageName) { - case PACKAGE_ANDROID: return android.os.Process.SYSTEM_UID; - case PACKAGE_PHONE: return android.os.Process.PHONE_UID; - case PACKAGE_RED: return android.os.Process.FIRST_APPLICATION_UID + 1; - case PACKAGE_GREEN: return android.os.Process.FIRST_APPLICATION_UID + 2; - case PACKAGE_BLUE: return android.os.Process.FIRST_APPLICATION_UID + 3; - case PACKAGE_YELLOW: return android.os.Process.FIRST_APPLICATION_UID + 4; - case PACKAGE_ORANGE: return android.os.Process.FIRST_APPLICATION_UID + 5; - default: throw new IllegalArgumentException(); - } - } - - static int getUidForPackage(@NonNull String packageName, int userId) { - return UserHandle.getUid(userId, getUidForPackage(packageName)); - } - /** * Baseline verification of common debugging infrastructure, mostly to make * sure it doesn't crash. @@ -2342,6 +2141,7 @@ public class BroadcastQueueTest { mUidObserver.onUidStateChanged(receiverGreenApp.info.uid, ActivityManager.PROCESS_STATE_TOP, 0, ActivityManager.PROCESS_CAPABILITY_NONE); + waitForIdle(); final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); @@ -2375,6 +2175,7 @@ public class BroadcastQueueTest { mUidObserver.onUidStateChanged(receiverGreenApp.info.uid, ActivityManager.PROCESS_STATE_TOP, 0, ActivityManager.PROCESS_CAPABILITY_NONE); + waitForIdle(); final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java index dc1c6d57dfdb..74d664fe7977 100644 --- a/services/tests/mockingservicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java @@ -75,7 +75,7 @@ public class UserBackupManagerServiceTest { private static final String TEST_PACKAGE = "package1"; private static final String[] TEST_PACKAGES = new String[] { TEST_PACKAGE }; private static final String TEST_TRANSPORT = "transport"; - private static final int WORKER_THREAD_TIMEOUT_MILLISECONDS = 1; + private static final int WORKER_THREAD_TIMEOUT_MILLISECONDS = 100; @Mock Context mContext; @Mock IBackupManagerMonitor mBackupManagerMonitor; diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java index 7cd88196bf1b..d68791589282 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java @@ -320,11 +320,20 @@ public final class UserManagerServiceTest { @Test public void testGetBootUser_Headless_ThrowsIfOnlySystemUserExists() throws Exception { setSystemUserHeadless(true); + removeNonSystemUsers(); assertThrows(UserManager.CheckedUserOperationException.class, () -> mUmi.getBootUser(/* waitUntilSet= */ false)); } + private void removeNonSystemUsers() { + for (UserInfo user : mUms.getUsers(true)) { + if (!user.getUserHandle().isSystem()) { + mUms.removeUserInfo(user.id); + } + } + } + private void mockCurrentUser(@UserIdInt int userId) { mockGetLocalService(ActivityManagerInternal.class, mActivityManagerInternal); diff --git a/services/tests/mockingservicestests/src/com/android/server/power/OWNERS b/services/tests/mockingservicestests/src/com/android/server/power/OWNERS index fb62520ff57b..37396f392551 100644 --- a/services/tests/mockingservicestests/src/com/android/server/power/OWNERS +++ b/services/tests/mockingservicestests/src/com/android/server/power/OWNERS @@ -1,3 +1,3 @@ include /services/core/java/com/android/server/power/OWNERS -per-file ThermalManagerServiceMockingTest.java=wvw@google.com,xwxw@google.com +per-file ThermalManagerServiceMockingTest.java=file:/THERMAL_OWNERS diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index f770f8c4571e..e656cf30e8e8 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -65,6 +65,7 @@ android_test { "ActivityContext", "coretests-aidl", "securebox", + "flag-junit", ], libs: [ diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java index f88afe7839c3..a78f2dcf2ab2 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java @@ -41,6 +41,8 @@ import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; +import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.Flags; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.IBiometricServiceReceiver; @@ -53,6 +55,7 @@ import android.hardware.iris.IIrisService; import android.os.Binder; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; +import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -84,6 +87,8 @@ public class AuthServiceTest { @Rule public MockitoRule mockitorule = MockitoJUnit.rule(); + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Mock private Context mContext; @Mock @@ -418,6 +423,37 @@ public class AuthServiceTest { eq(callback)); } + @Test(expected = UnsupportedOperationException.class) + public void testGetLastAuthenticationTime_flaggedOff_throwsUnsupportedOperationException() + throws Exception { + mSetFlagsRule.disableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME); + setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */); + + mAuthService = new AuthService(mContext, mInjector); + mAuthService.onStart(); + + mAuthService.mImpl.getLastAuthenticationTime(0, + BiometricManager.Authenticators.BIOMETRIC_STRONG); + } + + @Test + public void testGetLastAuthenticationTime_flaggedOn_callsBiometricService() + throws Exception { + mSetFlagsRule.enableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME); + setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */); + + mAuthService = new AuthService(mContext, mInjector); + mAuthService.onStart(); + + final int userId = 0; + final int authenticators = BiometricManager.Authenticators.BIOMETRIC_STRONG; + + mAuthService.mImpl.getLastAuthenticationTime(userId, authenticators); + + waitForIdle(); + verify(mBiometricService).getLastAuthenticationTime(eq(userId), eq(authenticators)); + } + private static void setInternalAndTestBiometricPermissions( Context context, boolean hasPermission) { for (String p : List.of(TEST_BIOMETRIC, MANAGE_BIOMETRIC, USE_BIOMETRIC_INTERNAL)) { diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java index 6f4791af43f0..14a567a08165 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java @@ -18,7 +18,6 @@ package com.android.server.biometrics; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricManager.Authenticators; -import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG; import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTHENTICATED_PENDING_SYSUI; @@ -61,6 +60,7 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; +import android.hardware.biometrics.Flags; import android.hardware.biometrics.IBiometricAuthenticator; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; import android.hardware.biometrics.IBiometricSensorReceiver; @@ -70,12 +70,17 @@ import android.hardware.biometrics.IBiometricSysuiReceiver; import android.hardware.biometrics.PromptInfo; import android.hardware.display.DisplayManagerGlobal; import android.hardware.fingerprint.FingerprintManager; +import android.hardware.keymaster.HardwareAuthenticatorType; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.os.UserManager; import android.platform.test.annotations.Presubmit; +import android.platform.test.flag.junit.SetFlagsRule; +import android.security.GateKeeper; import android.security.KeyStore; +import android.security.authorization.IKeystoreAuthorization; +import android.service.gatekeeper.IGateKeeperService; import android.view.Display; import android.view.DisplayInfo; import android.view.WindowManager; @@ -91,6 +96,7 @@ import com.android.server.biometrics.sensors.AuthSessionCoordinator; import com.android.server.biometrics.sensors.LockoutTracker; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.AdditionalMatchers; import org.mockito.ArgumentCaptor; @@ -104,6 +110,9 @@ import java.util.Random; @SmallTest public class BiometricServiceTest { + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + private static final String TEST_PACKAGE_NAME = "test_package"; private static final long TEST_REQUEST_ID = 44; @@ -155,10 +164,16 @@ public class BiometricServiceTest { @Mock private BiometricCameraManager mBiometricCameraManager; + @Mock + private IKeystoreAuthorization mKeystoreAuthService; + + @Mock + private IGateKeeperService mGateKeeperService; + BiometricContextProvider mBiometricContextProvider; @Before - public void setUp() { + public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); resetReceivers(); @@ -196,6 +211,9 @@ public class BiometricServiceTest { mStatusBarService, null /* handler */, mAuthSessionCoordinator); when(mInjector.getBiometricContext(any())).thenReturn(mBiometricContextProvider); + when(mInjector.getKeystoreAuthorizationService()).thenReturn(mKeystoreAuthService); + when(mInjector.getGateKeeperService()).thenReturn(mGateKeeperService); + when(mGateKeeperService.getSecureUserId(anyInt())).thenReturn(42L); final String[] config = { "0:2:15", // ID0:Fingerprint:Strong @@ -1612,6 +1630,44 @@ public class BiometricServiceTest { verifyNoMoreInteractions(callback); } + @Test(expected = UnsupportedOperationException.class) + public void testGetLastAuthenticationTime_flagOff_throwsUnsupportedOperationException() + throws RemoteException { + mSetFlagsRule.disableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME); + + mBiometricService = new BiometricService(mContext, mInjector); + mBiometricService.mImpl.getLastAuthenticationTime(0, Authenticators.BIOMETRIC_STRONG); + } + + @Test + public void testGetLastAuthenticationTime_flagOn_callsKeystoreAuthorization() + throws RemoteException { + mSetFlagsRule.enableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME); + + final int[] hardwareAuthenticators = new int[] { + HardwareAuthenticatorType.PASSWORD, + HardwareAuthenticatorType.FINGERPRINT + }; + + final int userId = 0; + final long secureUserId = mGateKeeperService.getSecureUserId(userId); + + assertNotEquals(GateKeeper.INVALID_SECURE_USER_ID, secureUserId); + + final long expectedResult = 31337L; + + when(mKeystoreAuthService.getLastAuthTime(eq(secureUserId), eq(hardwareAuthenticators))) + .thenReturn(expectedResult); + + mBiometricService = new BiometricService(mContext, mInjector); + + final long result = mBiometricService.mImpl.getLastAuthenticationTime(userId, + Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL); + + assertEquals(expectedResult, result); + verify(mKeystoreAuthService).getLastAuthTime(eq(secureUserId), eq(hardwareAuthenticators)); + } + // Helper methods private int invokeCanAuthenticate(BiometricService service, int authenticators) diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java index d52b7ea38725..6a2800949dd0 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -27,6 +27,8 @@ import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC import static com.google.common.truth.Truth.assertThat; +import static junit.framework.Assert.assertEquals; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -1648,4 +1650,24 @@ public class HdmiCecLocalDeviceTvTest { assertThat(mHdmiControlService.isSystemAudioActivated()).isTrue(); } + + @Test + public void newDeviceConnectedIfOnlyOneGiveOsdNameSent() { + mHdmiControlService.getHdmiCecNetwork().clearDeviceList(); + assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false)) + .isEmpty(); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_PLAYBACK_2, 0x1000, HdmiDeviceInfo.DEVICE_PLAYBACK); + HdmiCecMessage giveOsdName = HdmiCecMessageBuilder.buildGiveOsdNameCommand( + ADDR_TV, ADDR_PLAYBACK_2); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + mTestLooper.dispatchAll(); + + // Wait until HdmiCecNetwork or NewDeviceAction is in progress + mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); + + // TV should only send <Give Osd Name> once + assertEquals(1, Collections.frequency(mNativeWrapper.getResultMessages(), giveOsdName)); + } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java index 1c33d0de4568..18961c0feef9 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java @@ -34,6 +34,7 @@ import android.service.gatekeeper.IGateKeeperService; import com.android.internal.widget.LockscreenCredential; import com.android.server.ServiceThread; +import com.android.server.locksettings.SyntheticPasswordManager.SyntheticPassword; import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager; import com.android.server.pm.UserManagerInternal; @@ -203,6 +204,10 @@ public class LockSettingsServiceTestable extends LockSettingsService { } @Override + void initKeystoreSuperKeys(int userId, SyntheticPassword sp, boolean allowExisting) { + } + + @Override protected boolean isCredentialSharableWithParent(int userId) { UserInfo userInfo = mUserManager.getUserInfo(userId); return userInfo.isCloneProfile() || userInfo.isManagedProfile(); diff --git a/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java b/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java index 949f8e7a6ab0..0e881efd4cdf 100644 --- a/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java @@ -221,7 +221,7 @@ public class LockdownVpnTrackerTest { callCallbacksForNetworkConnect(defaultCallback, mNetwork); // Vpn is starting - verify(mVpn).startLegacyVpnPrivileged(mProfile, mNetwork, TEST_CELL_LP); + verify(mVpn).startLegacyVpnPrivileged(mProfile); verify(mNotificationManager).notify(any(), eq(SystemMessage.NOTE_VPN_STATUS), argThat(notification -> isExpectedNotification(notification, R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected))); @@ -242,7 +242,7 @@ public class LockdownVpnTrackerTest { // LockdownVpnTracker#handleStateChangedLocked. This is a bug. // TODO: consider fixing this. verify(mVpn, never()).stopVpnRunnerPrivileged(); - verify(mVpn, never()).startLegacyVpnPrivileged(any(), any(), any()); + verify(mVpn, never()).startLegacyVpnPrivileged(any()); verify(mNotificationManager, never()).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS)); } @@ -302,7 +302,7 @@ public class LockdownVpnTrackerTest { // Vpn is restarted. verify(mVpn).stopVpnRunnerPrivileged(); - verify(mVpn).startLegacyVpnPrivileged(mProfile, mNetwork2, wifiLp); + verify(mVpn).startLegacyVpnPrivileged(mProfile); verify(mNotificationManager, never()).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS)); verify(mNotificationManager).notify(any(), eq(SystemMessage.NOTE_VPN_STATUS), argThat(notification -> isExpectedNotification(notification, 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 af144cf49a46..13dc12032e7d 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java @@ -57,6 +57,7 @@ import android.util.ArrayMap; import androidx.test.runner.AndroidJUnit4; import com.android.internal.app.IBatteryStats; +import com.android.modules.utils.build.SdkLevel; import org.junit.After; import org.junit.Before; @@ -263,7 +264,11 @@ public class NetworkManagementServiceTest { verify(mCm).addUidToMeteredNetworkDenyList(TEST_UID); mNMService.setDataSaverModeEnabled(true); - verify(mNetdService).bandwidthEnableDataSaver(true); + if (SdkLevel.isAtLeastV()) { + verify(mCm).setDataSaverEnabled(true); + } else { + verify(mNetdService).bandwidthEnableDataSaver(true); + } mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, false); assertTrue("Should be true since data saver is on and the uid is not allowlisted", @@ -279,7 +284,11 @@ public class NetworkManagementServiceTest { mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, false); verify(mCm).removeUidFromMeteredNetworkAllowList(TEST_UID); mNMService.setDataSaverModeEnabled(false); - verify(mNetdService).bandwidthEnableDataSaver(false); + if (SdkLevel.isAtLeastV()) { + verify(mCm).setDataSaverEnabled(false); + } else { + verify(mNetdService).bandwidthEnableDataSaver(false); + } assertFalse("Network should not be restricted when data saver is off", mNMService.isNetworkRestricted(TEST_UID)); } diff --git a/services/tests/servicestests/src/com/android/server/power/OWNERS b/services/tests/servicestests/src/com/android/server/power/OWNERS index ef4c0bf71cd7..fe93ebbf3d8c 100644 --- a/services/tests/servicestests/src/com/android/server/power/OWNERS +++ b/services/tests/servicestests/src/com/android/server/power/OWNERS @@ -1,3 +1,3 @@ include /services/core/java/com/android/server/power/OWNERS -per-file ThermalManagerServiceTest.java=wvw@google.com, xwxw@google.com
\ No newline at end of file +per-file ThermalManagerServiceTest.java=file:/THERMAL_OWNERS diff --git a/services/tests/servicestests/src/com/android/server/utils/OWNERS b/services/tests/servicestests/src/com/android/server/utils/OWNERS index 5e2482825c74..f5b19a1c40ae 100644 --- a/services/tests/servicestests/src/com/android/server/utils/OWNERS +++ b/services/tests/servicestests/src/com/android/server/utils/OWNERS @@ -1,2 +1,5 @@ per-file EventLoggerTest.java = file:/platform/frameworks/av:/media/janitors/media_solutions_OWNERS per-file EventLoggerTest.java = jmtrivi@google.com + +# Bug component : 158088 = per-file AnrTimer*.java +per-file AnrTimer*.java = file:/PERFORMANCE_OWNERS diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index 0ccb0d0b2ef5..9e0d69bfdf6e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -1040,14 +1040,25 @@ public class RecentTasksTest extends WindowTestsBase { // If the task has a non-stopped activity, the removal will wait for its onDestroy. final Task task = tasks.get(0); + final ActivityRecord bottom = new ActivityBuilder(mAtm).setTask(task).build(); final ActivityRecord top = new ActivityBuilder(mAtm).setTask(task).build(); - top.lastVisibleTime = 123; + bottom.lastVisibleTime = top.lastVisibleTime = 123; top.setState(ActivityRecord.State.RESUMED, "test"); mRecentTasks.removeTasksByPackageName(task.getBasePackageName(), TEST_USER_0_ID); assertTrue(task.mKillProcessesOnDestroyed); top.setState(ActivityRecord.State.DESTROYING, "test"); + bottom.destroyed("test"); + assertTrue("Wait for all destroyed", task.mKillProcessesOnDestroyed); top.destroyed("test"); - assertFalse(task.mKillProcessesOnDestroyed); + assertFalse("Consume kill", task.mKillProcessesOnDestroyed); + + // If the process is died, the state should be cleared. + final Task lastTask = tasks.get(0); + lastTask.intent.setComponent(top.mActivityComponent); + lastTask.addChild(top); + lastTask.mKillProcessesOnDestroyed = true; + top.handleAppDied(); + assertFalse(lastTask.mKillProcessesOnDestroyed); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index 3bc6450ae591..b92cc64194e6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -870,7 +870,7 @@ public class RootWindowContainerTests extends WindowTestsBase { new TestDisplayContent.Builder(mAtm, 1000, 1500) .setSystemDecorations(true).build(); - // Use invalid user id to let StorageManager.isUserKeyUnlocked() return false. + // Use invalid user id to let StorageManager.isCeStorageUnlocked() return false. final int currentUser = mRootWindowContainer.mCurrentUser; mRootWindowContainer.mCurrentUser = -1; diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java index 3ec6f425a37a..973ab846fa4a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java @@ -448,7 +448,6 @@ public class ZOrderingTests extends WindowTestsBase { mDisplayContent.updateImeParent(); // Ime should on top of the popup IME layering target window. - mDisplayContent.assignChildLayers(mTransaction); assertWindowHigher(mImeWindow, popupImeTargetWin); } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java index 216f45acd5bd..d722f2f1aa0c 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java @@ -279,6 +279,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection, mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection, Context.BIND_AUTO_CREATE | Context.BIND_TREAT_LIKE_ACTIVITY | Context.BIND_SCHEDULE_LIKE_TOP_APP + | Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, new UserHandle(mUser)); } diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index c152a41c8694..25bd14f63573 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -2951,11 +2951,11 @@ public final class Call { for(String key : bundle.keySet()) { if (key != null) { - final Object value = bundle.get(key); - final Object newValue = newBundle.get(key); if (!newBundle.containsKey(key)) { return false; } + final Object value = bundle.get(key); + final Object newValue = newBundle.get(key); if (value instanceof Bundle && newValue instanceof Bundle) { if (!areBundlesEqual((Bundle) value, (Bundle) newValue)) { return false; diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index a72f7806d3ea..89ef523c2c71 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -2352,6 +2352,11 @@ public class TelecomManager { * <p> * <b>Note</b>: {@link android.app.Notification.CallStyle} notifications should be posted after * the call is placed in order for the notification to be non-dismissible. + * <p><b>Note</b>: Call Forwarding MMI codes can only be dialed by applications that are + * configured as the user defined default dialer or system dialer role. If a call containing a + * call forwarding MMI code is placed by an application that is not in one of these roles, the + * dialer will be launched with a UI showing the MMI code already populated so that the user can + * confirm the action before the call is placed. * @param address The address to make the call to. * @param extras Bundle of extras to use with the call. */ diff --git a/telephony/OWNERS b/telephony/OWNERS index 3158ad8fc58e..287aa653ef9a 100644 --- a/telephony/OWNERS +++ b/telephony/OWNERS @@ -7,10 +7,12 @@ rgreenwalt@google.com tgunn@google.com huiwang@google.com jayachandranc@google.com -chinmayd@google.com amruthr@google.com sasindran@google.com # Requiring TL ownership for new carrier config keys. per-file CarrierConfigManager.java=set noparent per-file CarrierConfigManager.java=amruthr@google.com,tgunn@google.com,rgreenwalt@google.com,satk@google.com + +#Domain Selection is jointly owned, add additional owners for domain selection specific files +per-file TransportSelectorCallback.java,WwanSelectorCallback.java,DomainSelectionService.java,DomainSelectionService.aidl,DomainSelector.java,EmergencyRegResult.java,EmergencyRegResult.aidl,IDomainSelectionServiceController.aidl,IDomainSelector.aidl,ITransportSelectorCallback.aidl,ITransportSelectorResultCallback.aidl,IWwanSelectorCallback.aidl,IWwanSelectorResultCallback.aidl=hwangoo@google.com,forestchoi@google.com,avinashmp@google.com,mkoon@google.com,seheele@google.com,radhikaagrawal@google.com diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt index f61cce666cca..daaab3314679 100644 --- a/test-mock/api/current.txt +++ b/test-mock/api/current.txt @@ -156,6 +156,7 @@ package android.test.mock { method @Deprecated public int getInt(int); method @Deprecated public long getLong(int); method @Deprecated public android.net.Uri getNotificationUri(); + method @Deprecated public java.util.List<android.net.Uri> getNotificationUris(); method @Deprecated public int getPosition(); method @Deprecated public short getShort(int); method @Deprecated public String getString(int); @@ -179,6 +180,7 @@ package android.test.mock { method @Deprecated public android.os.Bundle respond(android.os.Bundle); method @Deprecated public void setExtras(android.os.Bundle); method @Deprecated public void setNotificationUri(android.content.ContentResolver, android.net.Uri); + method @Deprecated public void setNotificationUris(android.content.ContentResolver, java.util.List<android.net.Uri>); method @Deprecated public void unregisterContentObserver(android.database.ContentObserver); method @Deprecated public void unregisterDataSetObserver(android.database.DataSetObserver); } diff --git a/tests/HwAccelerationTest/OWNERS b/tests/HwAccelerationTest/OWNERS deleted file mode 100644 index c88a9f82c347..000000000000 --- a/tests/HwAccelerationTest/OWNERS +++ /dev/null @@ -1 +0,0 @@ -include /libs/hwui/OWNERS diff --git a/tests/NetworkSecurityConfigTest/OWNERS b/tests/NetworkSecurityConfigTest/OWNERS index aa87958f1d53..90e1bed9fb26 100644 --- a/tests/NetworkSecurityConfigTest/OWNERS +++ b/tests/NetworkSecurityConfigTest/OWNERS @@ -1 +1,2 @@ include /services/core/java/com/android/server/net/OWNERS +include /core/java/android/security/net/OWNERS diff --git a/tests/SmokeTestApps/Android.bp b/tests/SmokeTestApps/Android.bp index 3505fe1c4afb..38ee8ac99747 100644 --- a/tests/SmokeTestApps/Android.bp +++ b/tests/SmokeTestApps/Android.bp @@ -11,4 +11,7 @@ android_test { name: "SmokeTestTriggerApps", srcs: ["src/**/*.java"], sdk_version: "current", + errorprone: { + enabled: false, + }, } diff --git a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt index 1dfd5c06167b..d0e56268a27d 100644 --- a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt +++ b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt @@ -93,7 +93,7 @@ class GrantAndRevokeTrustTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) + @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) fun grantCannotActivelyUnlockDevice() { // On automotive, trust agents can actively unlock the device. assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) @@ -120,7 +120,7 @@ class GrantAndRevokeTrustTest { } @Test - @RequiresFlagsDisabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) + @RequiresFlagsDisabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) fun grantCouldCauseWrongDeviceLockedStateDueToBug() { // On automotive, trust agents can actively unlock the device. assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) diff --git a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt index 5a8f82827253..01218099f34c 100644 --- a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt +++ b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt @@ -36,7 +36,8 @@ import org.junit.runners.model.Statement class LockStateTrackingRule : TestRule { private val context: Context = getApplicationContext() private val windowManager = checkNotNull(WindowManagerGlobal.getWindowManagerService()) - private val keyguardManager = context.getSystemService(KeyguardManager::class.java) as KeyguardManager + private val keyguardManager = + context.getSystemService(KeyguardManager::class.java) as KeyguardManager @Volatile lateinit var trustState: TrustState private set @@ -63,7 +64,7 @@ class LockStateTrackingRule : TestRule { wait("not trusted") { trustState.trusted == false } } - // TODO(b/299298338) remove this when removing FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS + // TODO(b/299298338) remove this when removing FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2 fun assertUnlockedButNotReally() { wait("device unlocked") { !keyguardManager.isDeviceLocked } wait("not trusted") { trustState.trusted == false } @@ -87,7 +88,7 @@ class LockStateTrackingRule : TestRule { trustGrantedMessages: MutableList<String> ) { Log.d(TAG, "Device became trusted=$enabled") - trustState = trustState.copy(trusted=enabled) + trustState = trustState.copy(trusted = enabled) } } diff --git a/tests/HwAccelerationTest/.classpath b/tests/graphics/HwAccelerationTest/.classpath index 609aa00ebc43..609aa00ebc43 100644 --- a/tests/HwAccelerationTest/.classpath +++ b/tests/graphics/HwAccelerationTest/.classpath diff --git a/tests/HwAccelerationTest/.gitignore b/tests/graphics/HwAccelerationTest/.gitignore index f178f174effb..f178f174effb 100644 --- a/tests/HwAccelerationTest/.gitignore +++ b/tests/graphics/HwAccelerationTest/.gitignore diff --git a/tests/HwAccelerationTest/Android.bp b/tests/graphics/HwAccelerationTest/Android.bp index 51848f2857c9..51848f2857c9 100644 --- a/tests/HwAccelerationTest/Android.bp +++ b/tests/graphics/HwAccelerationTest/Android.bp diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/graphics/HwAccelerationTest/AndroidManifest.xml index 80c7a21dc11b..db3a992b9c7b 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/graphics/HwAccelerationTest/AndroidManifest.xml @@ -789,6 +789,15 @@ </intent-filter> </activity> + <activity android:name="BackdropBlurActivity" + android:label="RenderEffect/BackdropBlur" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="com.android.test.hwui.TEST"/> + </intent-filter> + </activity> + <activity android:name="BlurActivity" android:label="RenderEffect/Blur" android:exported="true"> diff --git a/tests/HwAccelerationTest/default.properties b/tests/graphics/HwAccelerationTest/default.properties index da2dcdd13172..da2dcdd13172 100644 --- a/tests/HwAccelerationTest/default.properties +++ b/tests/graphics/HwAccelerationTest/default.properties diff --git a/tests/HwAccelerationTest/jni/Android.bp b/tests/graphics/HwAccelerationTest/jni/Android.bp index 8edddab0ad1f..8edddab0ad1f 100644 --- a/tests/HwAccelerationTest/jni/Android.bp +++ b/tests/graphics/HwAccelerationTest/jni/Android.bp diff --git a/tests/HwAccelerationTest/jni/native-lib.cpp b/tests/graphics/HwAccelerationTest/jni/native-lib.cpp index 407d4bf76336..407d4bf76336 100644 --- a/tests/HwAccelerationTest/jni/native-lib.cpp +++ b/tests/graphics/HwAccelerationTest/jni/native-lib.cpp diff --git a/tests/HwAccelerationTest/res/anim/accelerate_interpolator_2.xml b/tests/graphics/HwAccelerationTest/res/anim/accelerate_interpolator_2.xml index e4a8d480a28b..e4a8d480a28b 100644 --- a/tests/HwAccelerationTest/res/anim/accelerate_interpolator_2.xml +++ b/tests/graphics/HwAccelerationTest/res/anim/accelerate_interpolator_2.xml diff --git a/tests/HwAccelerationTest/res/anim/fade_in.xml b/tests/graphics/HwAccelerationTest/res/anim/fade_in.xml index 34310f53fc54..34310f53fc54 100644 --- a/tests/HwAccelerationTest/res/anim/fade_in.xml +++ b/tests/graphics/HwAccelerationTest/res/anim/fade_in.xml diff --git a/tests/HwAccelerationTest/res/anim/fade_out.xml b/tests/graphics/HwAccelerationTest/res/anim/fade_out.xml index 9832c322ff65..9832c322ff65 100644 --- a/tests/HwAccelerationTest/res/anim/fade_out.xml +++ b/tests/graphics/HwAccelerationTest/res/anim/fade_out.xml diff --git a/tests/HwAccelerationTest/res/anim/slide_off_left.xml b/tests/graphics/HwAccelerationTest/res/anim/slide_off_left.xml index f05de3937586..f05de3937586 100644 --- a/tests/HwAccelerationTest/res/anim/slide_off_left.xml +++ b/tests/graphics/HwAccelerationTest/res/anim/slide_off_left.xml diff --git a/tests/HwAccelerationTest/res/drawable-hdpi/appwidget_background.xml b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/appwidget_background.xml index abbb9e69af94..abbb9e69af94 100644 --- a/tests/HwAccelerationTest/res/drawable-hdpi/appwidget_background.xml +++ b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/appwidget_background.xml diff --git a/tests/HwAccelerationTest/res/drawable-hdpi/icon.png b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/icon.png Binary files differindex 60fbdf5d0403..60fbdf5d0403 100644 --- a/tests/HwAccelerationTest/res/drawable-hdpi/icon.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/icon.png diff --git a/tests/HwAccelerationTest/res/drawable-hdpi/sunset1.jpg b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/sunset1.jpg Binary files differindex 086c05542836..086c05542836 100644 --- a/tests/HwAccelerationTest/res/drawable-hdpi/sunset1.jpg +++ b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/sunset1.jpg diff --git a/tests/HwAccelerationTest/res/drawable-hdpi/sunset2.png b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/sunset2.png Binary files differindex 3258ee745389..3258ee745389 100644 --- a/tests/HwAccelerationTest/res/drawable-hdpi/sunset2.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/sunset2.png diff --git a/tests/HwAccelerationTest/res/drawable-hdpi/sunset3.png b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/sunset3.png Binary files differindex 6508b27a1452..6508b27a1452 100644 --- a/tests/HwAccelerationTest/res/drawable-hdpi/sunset3.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/sunset3.png diff --git a/tests/HwAccelerationTest/res/drawable-hdpi/widget_header.png b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/widget_header.png Binary files differindex cd9ec4488486..cd9ec4488486 100644 --- a/tests/HwAccelerationTest/res/drawable-hdpi/widget_header.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-hdpi/widget_header.png diff --git a/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_maximized.9.png b/tests/graphics/HwAccelerationTest/res/drawable-mdpi/expander_ic_maximized.9.png Binary files differindex d5c32766cece..d5c32766cece 100644 --- a/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_maximized.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-mdpi/expander_ic_maximized.9.png diff --git a/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_minimized.9.png b/tests/graphics/HwAccelerationTest/res/drawable-mdpi/expander_ic_minimized.9.png Binary files differindex 4515b42177bb..4515b42177bb 100644 --- a/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_minimized.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-mdpi/expander_ic_minimized.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/appwidget_bg.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/appwidget_bg.9.png Binary files differindex 80491912d80b..80491912d80b 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/appwidget_bg.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/appwidget_bg.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/appwidget_bg_focus.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/appwidget_bg_focus.9.png Binary files differindex c81f67582110..c81f67582110 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/appwidget_bg_focus.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/appwidget_bg_focus.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/appwidget_bg_press.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/appwidget_bg_press.9.png Binary files differindex d060b77556bb..d060b77556bb 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/appwidget_bg_press.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/appwidget_bg_press.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/green_gradient.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/green_gradient.9.png Binary files differindex a535678ab531..a535678ab531 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/green_gradient.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/green_gradient.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/large_photo.jpg b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/large_photo.jpg Binary files differindex e23dbb093f39..e23dbb093f39 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/large_photo.jpg +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/large_photo.jpg diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/patch.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/patch.9.png Binary files differindex e3b3639e86f2..e3b3639e86f2 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/patch.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/patch.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/patch2.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/patch2.9.png Binary files differindex f65a35592cd4..f65a35592cd4 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/patch2.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/patch2.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.png Binary files differindex 089704e90869..089704e90869 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.png Binary files differindex 385dbc4a62f6..385dbc4a62f6 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.png Binary files differindex f1510b247065..f1510b247065 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scratches.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/scratches.png Binary files differindex cc8adf15f4f0..cc8adf15f4f0 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/scratches.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/scratches.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.png Binary files differindex 4208c6f78fde..4208c6f78fde 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.png Binary files differindex b25fb2f18231..b25fb2f18231 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.png Binary files differindex 25129c69600b..25129c69600b 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.png Binary files differindex 1505e0eeefa4..1505e0eeefa4 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/spot_mask.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/spot_mask.png Binary files differindex 89537594e1a6..89537594e1a6 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/spot_mask.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/spot_mask.png diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/very_large_photo.jpg b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/very_large_photo.jpg Binary files differindex 6e1a866dfb00..6e1a866dfb00 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/very_large_photo.jpg +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/very_large_photo.jpg diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/weather_2.jpg b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/weather_2.jpg Binary files differindex b5aff104207a..b5aff104207a 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/weather_2.jpg +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/weather_2.jpg diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/widget_title_bg.9.png b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/widget_title_bg.9.png Binary files differindex 79615c237ffe..79615c237ffe 100644 --- a/tests/HwAccelerationTest/res/drawable-nodpi/widget_title_bg.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable-nodpi/widget_title_bg.9.png diff --git a/tests/HwAccelerationTest/res/drawable/appwidget_background.xml b/tests/graphics/HwAccelerationTest/res/drawable/appwidget_background.xml index abbb9e69af94..abbb9e69af94 100644 --- a/tests/HwAccelerationTest/res/drawable/appwidget_background.xml +++ b/tests/graphics/HwAccelerationTest/res/drawable/appwidget_background.xml diff --git a/tests/HwAccelerationTest/res/drawable/appwidget_bg.9.png b/tests/graphics/HwAccelerationTest/res/drawable/appwidget_bg.9.png Binary files differindex 80491912d80b..80491912d80b 100644 --- a/tests/HwAccelerationTest/res/drawable/appwidget_bg.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/appwidget_bg.9.png diff --git a/tests/HwAccelerationTest/res/drawable/appwidget_bg_focus.9.png b/tests/graphics/HwAccelerationTest/res/drawable/appwidget_bg_focus.9.png Binary files differindex c81f67582110..c81f67582110 100644 --- a/tests/HwAccelerationTest/res/drawable/appwidget_bg_focus.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/appwidget_bg_focus.9.png diff --git a/tests/HwAccelerationTest/res/drawable/appwidget_bg_press.9.png b/tests/graphics/HwAccelerationTest/res/drawable/appwidget_bg_press.9.png Binary files differindex d060b77556bb..d060b77556bb 100644 --- a/tests/HwAccelerationTest/res/drawable/appwidget_bg_press.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/appwidget_bg_press.9.png diff --git a/tests/HwAccelerationTest/res/drawable/btn_toggle_off.9.png b/tests/graphics/HwAccelerationTest/res/drawable/btn_toggle_off.9.png Binary files differindex 26ee1c2e9259..26ee1c2e9259 100644 --- a/tests/HwAccelerationTest/res/drawable/btn_toggle_off.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/btn_toggle_off.9.png diff --git a/tests/HwAccelerationTest/res/drawable/btn_toggle_on.9.png b/tests/graphics/HwAccelerationTest/res/drawable/btn_toggle_on.9.png Binary files differindex 53e95af9697d..53e95af9697d 100644 --- a/tests/HwAccelerationTest/res/drawable/btn_toggle_on.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/btn_toggle_on.9.png diff --git a/tests/HwAccelerationTest/res/drawable/default_wallpaper.png b/tests/graphics/HwAccelerationTest/res/drawable/default_wallpaper.png Binary files differindex 91ad252507e5..91ad252507e5 100644 --- a/tests/HwAccelerationTest/res/drawable/default_wallpaper.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/default_wallpaper.png diff --git a/tests/HwAccelerationTest/res/drawable/gradient.xml b/tests/graphics/HwAccelerationTest/res/drawable/gradient.xml index 756db0b23dbf..756db0b23dbf 100644 --- a/tests/HwAccelerationTest/res/drawable/gradient.xml +++ b/tests/graphics/HwAccelerationTest/res/drawable/gradient.xml diff --git a/tests/HwAccelerationTest/res/drawable/green_gradient.9.png b/tests/graphics/HwAccelerationTest/res/drawable/green_gradient.9.png Binary files differindex a535678ab531..a535678ab531 100644 --- a/tests/HwAccelerationTest/res/drawable/green_gradient.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/green_gradient.9.png diff --git a/tests/HwAccelerationTest/res/drawable/icon.png b/tests/graphics/HwAccelerationTest/res/drawable/icon.png Binary files differindex cb40a1988b52..cb40a1988b52 100644 --- a/tests/HwAccelerationTest/res/drawable/icon.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/icon.png diff --git a/tests/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml b/tests/graphics/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml index 9eb54b729b1d..9eb54b729b1d 100644 --- a/tests/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml +++ b/tests/graphics/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml diff --git a/tests/HwAccelerationTest/res/drawable/robot.png b/tests/graphics/HwAccelerationTest/res/drawable/robot.png Binary files differindex 8a9e6984be96..8a9e6984be96 100644 --- a/tests/HwAccelerationTest/res/drawable/robot.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/robot.png diff --git a/tests/graphics/HwAccelerationTest/res/drawable/robot_repeated.xml b/tests/graphics/HwAccelerationTest/res/drawable/robot_repeated.xml new file mode 100644 index 000000000000..bbb15b71c3a5 --- /dev/null +++ b/tests/graphics/HwAccelerationTest/res/drawable/robot_repeated.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<bitmap xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/robot" + android:tileMode="repeat" android:gravity="fill" />
\ No newline at end of file diff --git a/tests/HwAccelerationTest/res/drawable/round_rect_background.xml b/tests/graphics/HwAccelerationTest/res/drawable/round_rect_background.xml index 14d40736b3b9..14d40736b3b9 100644 --- a/tests/HwAccelerationTest/res/drawable/round_rect_background.xml +++ b/tests/graphics/HwAccelerationTest/res/drawable/round_rect_background.xml diff --git a/tests/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml b/tests/graphics/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml index 0cc56bfa4260..0cc56bfa4260 100644 --- a/tests/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml +++ b/tests/graphics/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml diff --git a/tests/HwAccelerationTest/res/drawable/sunset1.jpg b/tests/graphics/HwAccelerationTest/res/drawable/sunset1.jpg Binary files differindex 3b4e056b70d0..3b4e056b70d0 100644 --- a/tests/HwAccelerationTest/res/drawable/sunset1.jpg +++ b/tests/graphics/HwAccelerationTest/res/drawable/sunset1.jpg diff --git a/tests/HwAccelerationTest/res/drawable/sunset2.png b/tests/graphics/HwAccelerationTest/res/drawable/sunset2.png Binary files differindex 3258ee745389..3258ee745389 100644 --- a/tests/HwAccelerationTest/res/drawable/sunset2.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/sunset2.png diff --git a/tests/HwAccelerationTest/res/drawable/sunset3.png b/tests/graphics/HwAccelerationTest/res/drawable/sunset3.png Binary files differindex 6508b27a1452..6508b27a1452 100644 --- a/tests/HwAccelerationTest/res/drawable/sunset3.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/sunset3.png diff --git a/tests/HwAccelerationTest/res/drawable/widget_header.png b/tests/graphics/HwAccelerationTest/res/drawable/widget_header.png Binary files differindex 0297dd109bdf..0297dd109bdf 100644 --- a/tests/HwAccelerationTest/res/drawable/widget_header.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/widget_header.png diff --git a/tests/HwAccelerationTest/res/drawable/widget_title_bg.9.png b/tests/graphics/HwAccelerationTest/res/drawable/widget_title_bg.9.png Binary files differindex 79615c237ffe..79615c237ffe 100644 --- a/tests/HwAccelerationTest/res/drawable/widget_title_bg.9.png +++ b/tests/graphics/HwAccelerationTest/res/drawable/widget_title_bg.9.png diff --git a/tests/HwAccelerationTest/res/layout/_advanced_blend.xml b/tests/graphics/HwAccelerationTest/res/layout/_advanced_blend.xml index 5b6fd3c2624a..5b6fd3c2624a 100644 --- a/tests/HwAccelerationTest/res/layout/_advanced_blend.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/_advanced_blend.xml diff --git a/tests/HwAccelerationTest/res/layout/_advanced_gradient.xml b/tests/graphics/HwAccelerationTest/res/layout/_advanced_gradient.xml index 5e32ed2ec7cb..5e32ed2ec7cb 100644 --- a/tests/HwAccelerationTest/res/layout/_advanced_gradient.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/_advanced_gradient.xml diff --git a/tests/HwAccelerationTest/res/layout/_layers.xml b/tests/graphics/HwAccelerationTest/res/layout/_layers.xml index 25c76ac710cf..25c76ac710cf 100644 --- a/tests/HwAccelerationTest/res/layout/_layers.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/_layers.xml diff --git a/tests/HwAccelerationTest/res/layout/_lines.xml b/tests/graphics/HwAccelerationTest/res/layout/_lines.xml index c24dc25af9ac..c24dc25af9ac 100644 --- a/tests/HwAccelerationTest/res/layout/_lines.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/_lines.xml diff --git a/tests/HwAccelerationTest/res/layout/_newlayers.xml b/tests/graphics/HwAccelerationTest/res/layout/_newlayers.xml index 5c37e371aeff..5c37e371aeff 100644 --- a/tests/HwAccelerationTest/res/layout/_newlayers.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/_newlayers.xml diff --git a/tests/HwAccelerationTest/res/layout/_paths.xml b/tests/graphics/HwAccelerationTest/res/layout/_paths.xml index 34baf8474b6c..34baf8474b6c 100644 --- a/tests/HwAccelerationTest/res/layout/_paths.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/_paths.xml diff --git a/tests/HwAccelerationTest/res/layout/_shaders.xml b/tests/graphics/HwAccelerationTest/res/layout/_shaders.xml index 070ac1291f2c..070ac1291f2c 100644 --- a/tests/HwAccelerationTest/res/layout/_shaders.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/_shaders.xml diff --git a/tests/HwAccelerationTest/res/layout/colored_shadows_activity.xml b/tests/graphics/HwAccelerationTest/res/layout/colored_shadows_activity.xml index 18633250cfcb..18633250cfcb 100644 --- a/tests/HwAccelerationTest/res/layout/colored_shadows_activity.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/colored_shadows_activity.xml diff --git a/tests/HwAccelerationTest/res/layout/colored_shadows_row.xml b/tests/graphics/HwAccelerationTest/res/layout/colored_shadows_row.xml index 61b075974926..61b075974926 100644 --- a/tests/HwAccelerationTest/res/layout/colored_shadows_row.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/colored_shadows_row.xml diff --git a/tests/HwAccelerationTest/res/layout/date_picker.xml b/tests/graphics/HwAccelerationTest/res/layout/date_picker.xml index 742a03bfd1c5..742a03bfd1c5 100644 --- a/tests/HwAccelerationTest/res/layout/date_picker.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/date_picker.xml diff --git a/tests/HwAccelerationTest/res/layout/flipper_item.xml b/tests/graphics/HwAccelerationTest/res/layout/flipper_item.xml index 43a7bbfc2deb..43a7bbfc2deb 100644 --- a/tests/HwAccelerationTest/res/layout/flipper_item.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/flipper_item.xml diff --git a/tests/HwAccelerationTest/res/layout/form.xml b/tests/graphics/HwAccelerationTest/res/layout/form.xml index 0b17db186cd0..0b17db186cd0 100644 --- a/tests/HwAccelerationTest/res/layout/form.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/form.xml diff --git a/tests/HwAccelerationTest/res/layout/image_filter_activity.xml b/tests/graphics/HwAccelerationTest/res/layout/image_filter_activity.xml index a0ee67ae0bef..a0ee67ae0bef 100644 --- a/tests/HwAccelerationTest/res/layout/image_filter_activity.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/image_filter_activity.xml diff --git a/tests/HwAccelerationTest/res/layout/labels.xml b/tests/graphics/HwAccelerationTest/res/layout/labels.xml index 695a2cc09db5..695a2cc09db5 100644 --- a/tests/HwAccelerationTest/res/layout/labels.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/labels.xml diff --git a/tests/HwAccelerationTest/res/layout/list_activity.xml b/tests/graphics/HwAccelerationTest/res/layout/list_activity.xml index 1a5d3d9202e2..1a5d3d9202e2 100644 --- a/tests/HwAccelerationTest/res/layout/list_activity.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/list_activity.xml diff --git a/tests/HwAccelerationTest/res/layout/pen_stylus.xml b/tests/graphics/HwAccelerationTest/res/layout/pen_stylus.xml index 37aafed208fb..37aafed208fb 100644 --- a/tests/HwAccelerationTest/res/layout/pen_stylus.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/pen_stylus.xml diff --git a/tests/HwAccelerationTest/res/layout/projection.xml b/tests/graphics/HwAccelerationTest/res/layout/projection.xml index b6e4c5ef6ad2..b6e4c5ef6ad2 100644 --- a/tests/HwAccelerationTest/res/layout/projection.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/projection.xml diff --git a/tests/HwAccelerationTest/res/layout/projection_clipping.xml b/tests/graphics/HwAccelerationTest/res/layout/projection_clipping.xml index 1ea9f9cd49f6..1ea9f9cd49f6 100644 --- a/tests/HwAccelerationTest/res/layout/projection_clipping.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/projection_clipping.xml diff --git a/tests/HwAccelerationTest/res/layout/scrolling_stretch_surfaceview.xml b/tests/graphics/HwAccelerationTest/res/layout/scrolling_stretch_surfaceview.xml index 77f5e60dc091..77f5e60dc091 100644 --- a/tests/HwAccelerationTest/res/layout/scrolling_stretch_surfaceview.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/scrolling_stretch_surfaceview.xml diff --git a/tests/HwAccelerationTest/res/layout/stack.xml b/tests/graphics/HwAccelerationTest/res/layout/stack.xml index b4d2d73a1c90..b4d2d73a1c90 100644 --- a/tests/HwAccelerationTest/res/layout/stack.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/stack.xml diff --git a/tests/HwAccelerationTest/res/layout/stack_item.xml b/tests/graphics/HwAccelerationTest/res/layout/stack_item.xml index 35040186b0e6..35040186b0e6 100644 --- a/tests/HwAccelerationTest/res/layout/stack_item.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/stack_item.xml diff --git a/tests/HwAccelerationTest/res/layout/stretch_layout.xml b/tests/graphics/HwAccelerationTest/res/layout/stretch_layout.xml index 81e0c019490f..81e0c019490f 100644 --- a/tests/HwAccelerationTest/res/layout/stretch_layout.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/stretch_layout.xml diff --git a/tests/HwAccelerationTest/res/layout/text_fade.xml b/tests/graphics/HwAccelerationTest/res/layout/text_fade.xml index 08a70b3a3e71..08a70b3a3e71 100644 --- a/tests/HwAccelerationTest/res/layout/text_fade.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/text_fade.xml diff --git a/tests/HwAccelerationTest/res/layout/text_large.xml b/tests/graphics/HwAccelerationTest/res/layout/text_large.xml index 85b374ce0c0f..85b374ce0c0f 100644 --- a/tests/HwAccelerationTest/res/layout/text_large.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/text_large.xml diff --git a/tests/HwAccelerationTest/res/layout/text_medium.xml b/tests/graphics/HwAccelerationTest/res/layout/text_medium.xml index 8e195e661169..8e195e661169 100644 --- a/tests/HwAccelerationTest/res/layout/text_medium.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/text_medium.xml diff --git a/tests/HwAccelerationTest/res/layout/text_small.xml b/tests/graphics/HwAccelerationTest/res/layout/text_small.xml index 45eee609db6b..45eee609db6b 100644 --- a/tests/HwAccelerationTest/res/layout/text_small.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/text_small.xml diff --git a/tests/HwAccelerationTest/res/layout/transforms_and_animations.xml b/tests/graphics/HwAccelerationTest/res/layout/transforms_and_animations.xml index 1595502f6db9..1595502f6db9 100644 --- a/tests/HwAccelerationTest/res/layout/transforms_and_animations.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/transforms_and_animations.xml diff --git a/tests/HwAccelerationTest/res/layout/view_layer_invalidation.xml b/tests/graphics/HwAccelerationTest/res/layout/view_layer_invalidation.xml index 7df8bb6046b6..7df8bb6046b6 100644 --- a/tests/HwAccelerationTest/res/layout/view_layer_invalidation.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/view_layer_invalidation.xml diff --git a/tests/HwAccelerationTest/res/layout/view_layers.xml b/tests/graphics/HwAccelerationTest/res/layout/view_layers.xml index e0cdc78d2ae9..e0cdc78d2ae9 100644 --- a/tests/HwAccelerationTest/res/layout/view_layers.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/view_layers.xml diff --git a/tests/HwAccelerationTest/res/layout/view_layers_3.xml b/tests/graphics/HwAccelerationTest/res/layout/view_layers_3.xml index a820f5f2c43f..a820f5f2c43f 100644 --- a/tests/HwAccelerationTest/res/layout/view_layers_3.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/view_layers_3.xml diff --git a/tests/HwAccelerationTest/res/layout/view_layers_4.xml b/tests/graphics/HwAccelerationTest/res/layout/view_layers_4.xml index 54367379855a..54367379855a 100644 --- a/tests/HwAccelerationTest/res/layout/view_layers_4.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/view_layers_4.xml diff --git a/tests/HwAccelerationTest/res/layout/view_layers_5.xml b/tests/graphics/HwAccelerationTest/res/layout/view_layers_5.xml index 5baf5835dd8b..5baf5835dd8b 100644 --- a/tests/HwAccelerationTest/res/layout/view_layers_5.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/view_layers_5.xml diff --git a/tests/HwAccelerationTest/res/layout/view_properties.xml b/tests/graphics/HwAccelerationTest/res/layout/view_properties.xml index d7ed8192b3c4..d7ed8192b3c4 100644 --- a/tests/HwAccelerationTest/res/layout/view_properties.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/view_properties.xml diff --git a/tests/HwAccelerationTest/res/layout/view_runtime_shader.xml b/tests/graphics/HwAccelerationTest/res/layout/view_runtime_shader.xml index b91377d1ab49..b91377d1ab49 100644 --- a/tests/HwAccelerationTest/res/layout/view_runtime_shader.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/view_runtime_shader.xml diff --git a/tests/HwAccelerationTest/res/layout/widget.xml b/tests/graphics/HwAccelerationTest/res/layout/widget.xml index 503facedbf28..503facedbf28 100644 --- a/tests/HwAccelerationTest/res/layout/widget.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/widget.xml diff --git a/tests/HwAccelerationTest/res/layout/z_ordering.xml b/tests/graphics/HwAccelerationTest/res/layout/z_ordering.xml index 970c5fd6e275..970c5fd6e275 100644 --- a/tests/HwAccelerationTest/res/layout/z_ordering.xml +++ b/tests/graphics/HwAccelerationTest/res/layout/z_ordering.xml diff --git a/tests/HwAccelerationTest/res/raw/colorgrid_video.mp4 b/tests/graphics/HwAccelerationTest/res/raw/colorgrid_video.mp4 Binary files differindex 1be8bee39fd4..1be8bee39fd4 100644 --- a/tests/HwAccelerationTest/res/raw/colorgrid_video.mp4 +++ b/tests/graphics/HwAccelerationTest/res/raw/colorgrid_video.mp4 diff --git a/tests/HwAccelerationTest/res/values/strings.xml b/tests/graphics/HwAccelerationTest/res/values/strings.xml index 69e58aab18bf..69e58aab18bf 100644 --- a/tests/HwAccelerationTest/res/values/strings.xml +++ b/tests/graphics/HwAccelerationTest/res/values/strings.xml diff --git a/tests/HwAccelerationTest/res/values/styles.xml b/tests/graphics/HwAccelerationTest/res/values/styles.xml index 55f4dd697907..55f4dd697907 100644 --- a/tests/HwAccelerationTest/res/values/styles.xml +++ b/tests/graphics/HwAccelerationTest/res/values/styles.xml diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedBlendActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/AdvancedBlendActivity.java index a83005b4440b..a83005b4440b 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedBlendActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/AdvancedBlendActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java index b0b54eb83149..b0b54eb83149 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Alpha8BitmapActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Alpha8BitmapActivity.java index 5fe512e55072..5fe512e55072 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/Alpha8BitmapActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Alpha8BitmapActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java index 37661828da22..37661828da22 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Animated3dActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Animated3dActivity.java index f632c8372c35..f632c8372c35 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/Animated3dActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Animated3dActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AssetsAtlasActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/AssetsAtlasActivity.java index cbf99dc46a45..cbf99dc46a45 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/AssetsAtlasActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/AssetsAtlasActivity.java diff --git a/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BackdropBlurActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BackdropBlurActivity.java new file mode 100644 index 000000000000..8086b29df7cd --- /dev/null +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BackdropBlurActivity.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.hwui; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.Outline; +import android.graphics.RenderEffect; +import android.graphics.Shader; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewOutlineProvider; +import android.view.animation.DecelerateInterpolator; +import android.widget.FrameLayout; +import android.widget.ScrollView; + +@SuppressWarnings({"UnusedDeclaration"}) +public class BackdropBlurActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final ScrollView scrollView = new ScrollView(this); + final FrameLayout innerFrame = new FrameLayout(this); + final View backgroundView = new View(this); + backgroundView.setBackgroundResource(R.drawable.robot_repeated); + innerFrame.addView(backgroundView, ViewGroup.LayoutParams.MATCH_PARENT, 10000); + scrollView.addView(innerFrame, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + + final FrameLayout contentView = new FrameLayout(this); + contentView.addView(scrollView, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + contentView.addView(new BackdropBlurView(this), 300, 300); + setContentView(contentView); + } + + private static class BackdropBlurView extends View { + private final float mBlurRadius = 60f; + private final float mSaturation = 1.8f; + + private float mDownOffsetX; + private float mDownOffsetY; + + BackdropBlurView(Context c) { + super(c); + + // init RenderEffect. + final RenderEffect blurEffect = RenderEffect.createBlurEffect( + mBlurRadius, mBlurRadius, + null, Shader.TileMode.MIRROR // TileMode.MIRROR is better for blur. + ); + + final ColorMatrix colorMatrix = new ColorMatrix(); + colorMatrix.setSaturation(mSaturation); + final RenderEffect effect = RenderEffect.createColorFilterEffect( + new ColorMatrixColorFilter(colorMatrix), blurEffect + ); + setBackdropRenderEffect(effect); + + // clip to a round outline. + setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View v, Outline outline) { + outline.setOval(0, 0, v.getWidth(), v.getHeight()); + } + }); + setClipToOutline(true); + + animate().setInterpolator(new DecelerateInterpolator(2.0f)); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + canvas.drawColor(0x99F0F0F0); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + mDownOffsetX = event.getRawX() - getTranslationX(); + mDownOffsetY = event.getRawY() - getTranslationY(); + animate().scaleX(1.5f).scaleY(1.5f).start(); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + animate().scaleX(1f).scaleY(1f).start(); + break; + case MotionEvent.ACTION_MOVE: + setTranslationX(event.getRawX() - mDownOffsetX); + setTranslationY(event.getRawY() - mDownOffsetY); + break; + } + return true; + } + } +} diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java index 4d28f5125ff2..4d28f5125ff2 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BigGradientActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java index 69d34a590a46..69d34a590a46 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshLayerActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshLayerActivity.java index ac59a4bcca19..ac59a4bcca19 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshLayerActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshLayerActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMutateActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapMutateActivity.java index 0d825d7c60ed..0d825d7c60ed 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMutateActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapMutateActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapTransitionView.kt b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapTransitionView.kt index 3af54503d469..3af54503d469 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapTransitionView.kt +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapTransitionView.kt diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Bitmaps3dActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Bitmaps3dActivity.java index baa1cb916864..baa1cb916864 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/Bitmaps3dActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Bitmaps3dActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapsActivity.java index 607a1738c13a..607a1738c13a 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapsAlphaActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapsAlphaActivity.java index ef49c7fd00a9..ef49c7fd00a9 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapsAlphaActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapsAlphaActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapsRectActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapsRectActivity.java index b192209e7823..b192209e7823 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapsRectActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapsRectActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapsSkewActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapsSkewActivity.java index 099c0dde4eac..099c0dde4eac 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapsSkewActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BitmapsSkewActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BlurActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BlurActivity.java index e4ca7881f796..e4ca7881f796 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/BlurActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/BlurActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CanvasTextureViewActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/CanvasTextureViewActivity.java index bd2f68f77f28..bd2f68f77f28 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/CanvasTextureViewActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/CanvasTextureViewActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java index 571f623aea99..571f623aea99 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java index 1c82e9bbdf9b..1c82e9bbdf9b 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipOutlineActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ClipOutlineActivity.java index 23bb6b4a4a0c..23bb6b4a4a0c 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipOutlineActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ClipOutlineActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegion2Activity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ClipRegion2Activity.java index fe4d602a62d1..fe4d602a62d1 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegion2Activity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ClipRegion2Activity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegion3Activity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ClipRegion3Activity.java index 6fd03fb992e5..6fd03fb992e5 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegion3Activity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ClipRegion3Activity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegionActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ClipRegionActivity.java index 774811e5bf10..774811e5bf10 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegionActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ClipRegionActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorBitmapActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ColorBitmapActivity.java index e2d17cdbe9e6..e2d17cdbe9e6 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorBitmapActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ColorBitmapActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersActivity.java index 09d63d6eda17..09d63d6eda17 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java index fafe60b46676..fafe60b46676 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java index d4bc2a6d3317..d4bc2a6d3317 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java index 901d90eed70a..901d90eed70a 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java index 5ad7fb9027a2..5ad7fb9027a2 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java index 492d158ec5ef..492d158ec5ef 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePickerActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/DatePickerActivity.java index 5482ee2b656f..5482ee2b656f 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePickerActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/DatePickerActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DisplayListLayersActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/DisplayListLayersActivity.java index ec91c35dce0f..ec91c35dce0f 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/DisplayListLayersActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/DisplayListLayersActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java index 220016aa8ab7..220016aa8ab7 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java index c4b0072eaff8..c4b0072eaff8 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/FramebufferBlendActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/FramebufferBlendActivity.java index 1556baec0c9c..1556baec0c9c 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/FramebufferBlendActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/FramebufferBlendActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/FrontBufferedLayer.kt b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/FrontBufferedLayer.kt index ebec22e29d69..ebec22e29d69 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/FrontBufferedLayer.kt +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/FrontBufferedLayer.kt diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLDepthTestActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GLDepthTestActivity.java index 1bb6d0ca8591..1bb6d0ca8591 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLDepthTestActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GLDepthTestActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java index 733e44f28130..733e44f28130 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java index 038434a72de2..038434a72de2 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java index 6fe2cb472a97..6fe2cb472a97 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GlyphCacheActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GlyphCacheActivity.java index e89b2948062b..e89b2948062b 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GlyphCacheActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GlyphCacheActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java index a73eab579d12..a73eab579d12 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GradientStopsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java index fbe7856f32ec..fbe7856f32ec 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareBufferRendererActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/HardwareBufferRendererActivity.java index e4de434f1ed2..e4de434f1ed2 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareBufferRendererActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/HardwareBufferRendererActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasSurfaceViewActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasSurfaceViewActivity.java index 2bfe994aa1b7..2bfe994aa1b7 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasSurfaceViewActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasSurfaceViewActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasTextureViewActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasTextureViewActivity.java index 63a6efa712fb..63a6efa712fb 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasTextureViewActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasTextureViewActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/HwTests.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/HwTests.java index b1c32a88c353..b1c32a88c353 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/HwTests.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/HwTests.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LabelsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/LabelsActivity.java index bae0500f39e9..bae0500f39e9 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/LabelsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/LabelsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LayersActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/LayersActivity.java index 9d5cd284301a..9d5cd284301a 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/LayersActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/LayersActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java index 584ab596836c..584ab596836c 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java index eed0ec890b8f..eed0ec890b8f 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java index 134c2e045449..134c2e045449 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LooperAcceleration.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/LooperAcceleration.java index 20d8e11cbe45..20d8e11cbe45 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/LooperAcceleration.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/LooperAcceleration.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MarqueeActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MarqueeActivity.java index 715cdbb226cb..715cdbb226cb 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MarqueeActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MarqueeActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MatrixActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MatrixActivity.java index 1906b9d5dd91..1906b9d5dd91 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MatrixActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MatrixActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MaxBitmapSizeActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MaxBitmapSizeActivity.java index b3b42dcdf157..b3b42dcdf157 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MaxBitmapSizeActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MaxBitmapSizeActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java index ae3dcb834687..ae3dcb834687 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java index 01ca2fcdbb86..01ca2fcdbb86 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MipMapActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MipMapActivity.java index 1034649b6cb2..1034649b6cb2 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MipMapActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MipMapActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java index 0c42387ee693..0c42387ee693 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MoreShadersActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MoreShadersActivity.java index 1847f43b7ea0..1847f43b7ea0 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MoreShadersActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MoreShadersActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java index fa25b45c2b06..fa25b45c2b06 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiLayersActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MultiLayersActivity.java index eb8a0a926af8..eb8a0a926af8 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiLayersActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MultiLayersActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java index e7d7f2b11801..e7d7f2b11801 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java index 08d5d4fff50a..08d5d4fff50a 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/NewLayersActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/NewLayersActivity.java index 2509d367fe30..2509d367fe30 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/NewLayersActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/NewLayersActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/NinePatchesActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/NinePatchesActivity.java index 7410f79363b3..7410f79363b3 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/NinePatchesActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/NinePatchesActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/NoAATextActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/NoAATextActivity.java index 5bd2f583c4c8..5bd2f583c4c8 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/NoAATextActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/NoAATextActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/OpaqueActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/OpaqueActivity.java index af45f299bec3..af45f299bec3 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/OpaqueActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/OpaqueActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PaintDrawFilterActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PaintDrawFilterActivity.java index 85232720f436..85232720f436 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PaintDrawFilterActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PaintDrawFilterActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java index 5cede6540410..5cede6540410 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathOffsetActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PathOffsetActivity.java index fa73de157cf7..fa73de157cf7 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathOffsetActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PathOffsetActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathOpsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PathOpsActivity.java index b9927ac08523..b9927ac08523 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathOpsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PathOpsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PathsActivity.java index c241a6243011..c241a6243011 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PathsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java index c1e7f4ad156c..c1e7f4ad156c 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PenStylusActivity.kt b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PenStylusActivity.kt index 1445b1db801e..1445b1db801e 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PenStylusActivity.kt +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PenStylusActivity.kt diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PictureCaptureDemo.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PictureCaptureDemo.java index 15568ac72227..15568ac72227 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PictureCaptureDemo.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PictureCaptureDemo.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PixelCopyWindow.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PixelCopyWindow.java index a039fba14f65..a039fba14f65 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PixelCopyWindow.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PixelCopyWindow.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PointsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PointsActivity.java index b3fb7a1b47d2..b3fb7a1b47d2 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PointsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PointsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java index 1c868d233339..1c868d233339 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java index 2ad034cd143e..2ad034cd143e 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java index 4eb40722f6dd..4eb40722f6dd 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java index 9abd7ea5f361..9abd7ea5f361 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/QuickRejectActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/QuickRejectActivity.java index 5192bfe84fef..5192bfe84fef 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/QuickRejectActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/QuickRejectActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RenderEffectShaderActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/RenderEffectShaderActivity.java index 661d48a84768..661d48a84768 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/RenderEffectShaderActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/RenderEffectShaderActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RenderEffectViewActivity.kt b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/RenderEffectViewActivity.kt index 3c71b96c6c31..3c71b96c6c31 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/RenderEffectViewActivity.kt +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/RenderEffectViewActivity.kt diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ResizeActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ResizeActivity.java index 04f9de184038..04f9de184038 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ResizeActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ResizeActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java index 1216fc43640e..1216fc43640e 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java index b78907c46744..b78907c46744 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Rotate3dTextActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Rotate3dTextActivity.java index 0368b2fffc06..0368b2fffc06 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/Rotate3dTextActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Rotate3dTextActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RotationActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/RotationActivity.java index 5c309b4431bf..5c309b4431bf 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/RotationActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/RotationActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ScaledPathsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScaledPathsActivity.java index deb4b6b87fe4..deb4b6b87fe4 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ScaledPathsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScaledPathsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ScaledTextActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScaledTextActivity.java index a4e9b52f4290..a4e9b52f4290 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ScaledTextActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScaledTextActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ScrollingStretchSurfaceViewActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScrollingStretchSurfaceViewActivity.java index 040bff5d74d8..040bff5d74d8 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ScrollingStretchSurfaceViewActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScrollingStretchSurfaceViewActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java index 1d18f61986ba..1d18f61986ba 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java index 61dca784ce5e..61dca784ce5e 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ShapesActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SimplePatchActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/SimplePatchActivity.java index a9b4d1c3cefb..a9b4d1c3cefb 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/SimplePatchActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/SimplePatchActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SimplePathsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/SimplePathsActivity.java index c3e18a3c08ff..c3e18a3c08ff 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/SimplePathsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/SimplePathsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SingleFrameTextureViewTestActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/SingleFrameTextureViewTestActivity.java index 4d3826b68247..4d3826b68247 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/SingleFrameTextureViewTestActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/SingleFrameTextureViewTestActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java index a3f4ddc382d4..a3f4ddc382d4 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java index 262b0e93671b..262b0e93671b 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java index 2990c9e59fec..2990c9e59fec 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java index acb872cd23b8..acb872cd23b8 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SurfaceViewAlphaActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/SurfaceViewAlphaActivity.java index 01fe6ae0518b..01fe6ae0518b 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/SurfaceViewAlphaActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/SurfaceViewAlphaActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TJunctionActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TJunctionActivity.java index d2bcae9645b9..d2bcae9645b9 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TJunctionActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TJunctionActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java index 4a1f5a24ba2b..4a1f5a24ba2b 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java index d307ef871b97..d307ef871b97 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextGammaActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextGammaActivity.java index f40b89dc0d36..f40b89dc0d36 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextGammaActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextGammaActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextOnPathActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextOnPathActivity.java index ceccfaa9cd0f..ceccfaa9cd0f 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextOnPathActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextOnPathActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextPathActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextPathActivity.java index 35a1fc92b468..35a1fc92b468 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextPathActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextPathActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java index 6d8c43c00acf..6d8c43c00acf 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ThinPatchesActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ThinPatchesActivity.java index 656f2b143654..656f2b143654 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ThinPatchesActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ThinPatchesActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java index 9e3e950f0850..9e3e950f0850 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Transform3dActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Transform3dActivity.java index 6df66e6bbd9a..6df66e6bbd9a 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/Transform3dActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/Transform3dActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java index b5a5e025e757..b5a5e025e757 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java index deb8585a95f5..deb8585a95f5 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java index b87be8058d81..b87be8058d81 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewFlipperActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewFlipperActivity.java index 0e244fc0a31b..0e244fc0a31b 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewFlipperActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewFlipperActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java index a261fb729a65..a261fb729a65 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java index 07dc0a1b5df0..07dc0a1b5df0 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java index a037d70ef845..a037d70ef845 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java index 96cf43e48778..96cf43e48778 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java index 1f3f874744db..1f3f874744db 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java index 715da201458b..715da201458b 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java index 9ae38119cac6..9ae38119cac6 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/XfermodeActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/XfermodeActivity.java index 411077f04f93..411077f04f93 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/XfermodeActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/XfermodeActivity.java diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java index 08979bce8f73..08979bce8f73 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java diff --git a/tests/SilkFX/OWNERS b/tests/graphics/OWNERS index c88a9f82c347..fb7fc14640b1 100644 --- a/tests/SilkFX/OWNERS +++ b/tests/graphics/OWNERS @@ -1 +1,3 @@ +# Bug component: 1075130 + include /libs/hwui/OWNERS diff --git a/tests/RenderThreadTest/Android.bp b/tests/graphics/RenderThreadTest/Android.bp index b18b04edb4c4..b18b04edb4c4 100644 --- a/tests/RenderThreadTest/Android.bp +++ b/tests/graphics/RenderThreadTest/Android.bp diff --git a/tests/RenderThreadTest/AndroidManifest.xml b/tests/graphics/RenderThreadTest/AndroidManifest.xml index 22a4e43c988c..22a4e43c988c 100644 --- a/tests/RenderThreadTest/AndroidManifest.xml +++ b/tests/graphics/RenderThreadTest/AndroidManifest.xml diff --git a/tests/RenderThreadTest/res/drawable-hdpi/ic_launcher.png b/tests/graphics/RenderThreadTest/res/drawable-hdpi/ic_launcher.png Binary files differindex 96a442e5b8e9..96a442e5b8e9 100644 --- a/tests/RenderThreadTest/res/drawable-hdpi/ic_launcher.png +++ b/tests/graphics/RenderThreadTest/res/drawable-hdpi/ic_launcher.png diff --git a/tests/RenderThreadTest/res/drawable-mdpi/ic_launcher.png b/tests/graphics/RenderThreadTest/res/drawable-mdpi/ic_launcher.png Binary files differindex 359047dfa4ed..359047dfa4ed 100644 --- a/tests/RenderThreadTest/res/drawable-mdpi/ic_launcher.png +++ b/tests/graphics/RenderThreadTest/res/drawable-mdpi/ic_launcher.png diff --git a/tests/RenderThreadTest/res/drawable-xhdpi/ic_launcher.png b/tests/graphics/RenderThreadTest/res/drawable-xhdpi/ic_launcher.png Binary files differindex 71c6d760f051..71c6d760f051 100644 --- a/tests/RenderThreadTest/res/drawable-xhdpi/ic_launcher.png +++ b/tests/graphics/RenderThreadTest/res/drawable-xhdpi/ic_launcher.png diff --git a/tests/RenderThreadTest/res/drawable-xhdpi/starry_night_bg.jpg b/tests/graphics/RenderThreadTest/res/drawable-xhdpi/starry_night_bg.jpg Binary files differindex 14d6027bf006..14d6027bf006 100644 --- a/tests/RenderThreadTest/res/drawable-xhdpi/starry_night_bg.jpg +++ b/tests/graphics/RenderThreadTest/res/drawable-xhdpi/starry_night_bg.jpg diff --git a/tests/RenderThreadTest/res/layout/activity_main.xml b/tests/graphics/RenderThreadTest/res/layout/activity_main.xml index 1fd545946f3c..1fd545946f3c 100644 --- a/tests/RenderThreadTest/res/layout/activity_main.xml +++ b/tests/graphics/RenderThreadTest/res/layout/activity_main.xml diff --git a/tests/RenderThreadTest/res/layout/activity_sub.xml b/tests/graphics/RenderThreadTest/res/layout/activity_sub.xml index 713cee49de53..713cee49de53 100644 --- a/tests/RenderThreadTest/res/layout/activity_sub.xml +++ b/tests/graphics/RenderThreadTest/res/layout/activity_sub.xml diff --git a/tests/RenderThreadTest/res/layout/item_layout.xml b/tests/graphics/RenderThreadTest/res/layout/item_layout.xml index 5bdb1ac422f5..5bdb1ac422f5 100644 --- a/tests/RenderThreadTest/res/layout/item_layout.xml +++ b/tests/graphics/RenderThreadTest/res/layout/item_layout.xml diff --git a/tests/RenderThreadTest/res/values/strings.xml b/tests/graphics/RenderThreadTest/res/values/strings.xml index f782e98f43f8..f782e98f43f8 100644 --- a/tests/RenderThreadTest/res/values/strings.xml +++ b/tests/graphics/RenderThreadTest/res/values/strings.xml diff --git a/tests/RenderThreadTest/res/values/styles.xml b/tests/graphics/RenderThreadTest/res/values/styles.xml index f6b5d6aa6dbc..f6b5d6aa6dbc 100644 --- a/tests/RenderThreadTest/res/values/styles.xml +++ b/tests/graphics/RenderThreadTest/res/values/styles.xml diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/graphics/RenderThreadTest/src/com/example/renderthread/MainActivity.java index 65b7549f22d1..65b7549f22d1 100644 --- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java +++ b/tests/graphics/RenderThreadTest/src/com/example/renderthread/MainActivity.java diff --git a/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java b/tests/graphics/RenderThreadTest/src/com/example/renderthread/SubActivity.java index 22fc6911f7df..22fc6911f7df 100644 --- a/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java +++ b/tests/graphics/RenderThreadTest/src/com/example/renderthread/SubActivity.java diff --git a/tests/SilkFX/Android.bp b/tests/graphics/SilkFX/Android.bp index 1e467db44545..1e467db44545 100644 --- a/tests/SilkFX/Android.bp +++ b/tests/graphics/SilkFX/Android.bp diff --git a/tests/SilkFX/AndroidManifest.xml b/tests/graphics/SilkFX/AndroidManifest.xml index c293589bdbaf..c293589bdbaf 100644 --- a/tests/SilkFX/AndroidManifest.xml +++ b/tests/graphics/SilkFX/AndroidManifest.xml diff --git a/tests/SilkFX/assets/gainmaps/city_night.jpg b/tests/graphics/SilkFX/assets/gainmaps/city_night.jpg Binary files differindex ba26ed6a5780..ba26ed6a5780 100644 --- a/tests/SilkFX/assets/gainmaps/city_night.jpg +++ b/tests/graphics/SilkFX/assets/gainmaps/city_night.jpg diff --git a/tests/SilkFX/assets/gainmaps/desert_palms.jpg b/tests/graphics/SilkFX/assets/gainmaps/desert_palms.jpg Binary files differindex 048178670a96..048178670a96 100644 --- a/tests/SilkFX/assets/gainmaps/desert_palms.jpg +++ b/tests/graphics/SilkFX/assets/gainmaps/desert_palms.jpg diff --git a/tests/SilkFX/assets/gainmaps/desert_sunset.jpg b/tests/graphics/SilkFX/assets/gainmaps/desert_sunset.jpg Binary files differindex 919a1574a4b9..919a1574a4b9 100644 --- a/tests/SilkFX/assets/gainmaps/desert_sunset.jpg +++ b/tests/graphics/SilkFX/assets/gainmaps/desert_sunset.jpg diff --git a/tests/SilkFX/assets/gainmaps/desert_wanda.jpg b/tests/graphics/SilkFX/assets/gainmaps/desert_wanda.jpg Binary files differindex f5a2ef9c53ea..f5a2ef9c53ea 100644 --- a/tests/SilkFX/assets/gainmaps/desert_wanda.jpg +++ b/tests/graphics/SilkFX/assets/gainmaps/desert_wanda.jpg diff --git a/tests/graphics/SilkFX/assets/gainmaps/fountain_night.jpg b/tests/graphics/SilkFX/assets/gainmaps/fountain_night.jpg Binary files differnew file mode 100644 index 000000000000..d8b2d759e4c0 --- /dev/null +++ b/tests/graphics/SilkFX/assets/gainmaps/fountain_night.jpg diff --git a/tests/SilkFX/assets/gainmaps/grand_canyon.jpg b/tests/graphics/SilkFX/assets/gainmaps/grand_canyon.jpg Binary files differindex 2f605bbb0a7e..2f605bbb0a7e 100644 --- a/tests/SilkFX/assets/gainmaps/grand_canyon.jpg +++ b/tests/graphics/SilkFX/assets/gainmaps/grand_canyon.jpg diff --git a/tests/SilkFX/assets/gainmaps/lamps.jpg b/tests/graphics/SilkFX/assets/gainmaps/lamps.jpg Binary files differindex 768665f643cb..768665f643cb 100644 --- a/tests/SilkFX/assets/gainmaps/lamps.jpg +++ b/tests/graphics/SilkFX/assets/gainmaps/lamps.jpg diff --git a/tests/SilkFX/assets/gainmaps/mountain_lake.jpg b/tests/graphics/SilkFX/assets/gainmaps/mountain_lake.jpg Binary files differindex b7981fdca6da..b7981fdca6da 100644 --- a/tests/SilkFX/assets/gainmaps/mountain_lake.jpg +++ b/tests/graphics/SilkFX/assets/gainmaps/mountain_lake.jpg diff --git a/tests/SilkFX/assets/gainmaps/mountains.jpg b/tests/graphics/SilkFX/assets/gainmaps/mountains.jpg Binary files differindex fe69993e0706..fe69993e0706 100644 --- a/tests/SilkFX/assets/gainmaps/mountains.jpg +++ b/tests/graphics/SilkFX/assets/gainmaps/mountains.jpg diff --git a/tests/SilkFX/assets/gainmaps/sunflower.jpg b/tests/graphics/SilkFX/assets/gainmaps/sunflower.jpg Binary files differindex 4b17614d66bf..4b17614d66bf 100644 --- a/tests/SilkFX/assets/gainmaps/sunflower.jpg +++ b/tests/graphics/SilkFX/assets/gainmaps/sunflower.jpg diff --git a/tests/SilkFX/assets/gainmaps/train_station_night.jpg b/tests/graphics/SilkFX/assets/gainmaps/train_station_night.jpg Binary files differindex ecd45ee1e629..ecd45ee1e629 100644 --- a/tests/SilkFX/assets/gainmaps/train_station_night.jpg +++ b/tests/graphics/SilkFX/assets/gainmaps/train_station_night.jpg diff --git a/tests/SilkFX/res/drawable-hdpi/background1.jpeg b/tests/graphics/SilkFX/res/drawable-hdpi/background1.jpeg Binary files differindex dcdfa7b850bc..dcdfa7b850bc 100644 --- a/tests/SilkFX/res/drawable-hdpi/background1.jpeg +++ b/tests/graphics/SilkFX/res/drawable-hdpi/background1.jpeg diff --git a/tests/SilkFX/res/drawable-hdpi/background2.jpeg b/tests/graphics/SilkFX/res/drawable-hdpi/background2.jpeg Binary files differindex dc7ce84e6784..dc7ce84e6784 100644 --- a/tests/SilkFX/res/drawable-hdpi/background2.jpeg +++ b/tests/graphics/SilkFX/res/drawable-hdpi/background2.jpeg diff --git a/tests/SilkFX/res/drawable-hdpi/background3.jpeg b/tests/graphics/SilkFX/res/drawable-hdpi/background3.jpeg Binary files differindex 12b3429e3920..12b3429e3920 100644 --- a/tests/SilkFX/res/drawable-hdpi/background3.jpeg +++ b/tests/graphics/SilkFX/res/drawable-hdpi/background3.jpeg diff --git a/tests/SilkFX/res/drawable-hdpi/noise.png b/tests/graphics/SilkFX/res/drawable-hdpi/noise.png Binary files differindex 053995dad760..053995dad760 100644 --- a/tests/SilkFX/res/drawable-hdpi/noise.png +++ b/tests/graphics/SilkFX/res/drawable-hdpi/noise.png diff --git a/tests/SilkFX/res/drawable-nodpi/blue_sweep_gradient.xml b/tests/graphics/SilkFX/res/drawable-nodpi/blue_sweep_gradient.xml index c183c5deab4f..c183c5deab4f 100644 --- a/tests/SilkFX/res/drawable-nodpi/blue_sweep_gradient.xml +++ b/tests/graphics/SilkFX/res/drawable-nodpi/blue_sweep_gradient.xml diff --git a/tests/SilkFX/res/drawable-nodpi/dark_gradient.xml b/tests/graphics/SilkFX/res/drawable-nodpi/dark_gradient.xml index f20dd424c617..f20dd424c617 100644 --- a/tests/SilkFX/res/drawable-nodpi/dark_gradient.xml +++ b/tests/graphics/SilkFX/res/drawable-nodpi/dark_gradient.xml diff --git a/tests/SilkFX/res/drawable-nodpi/dark_notification.png b/tests/graphics/SilkFX/res/drawable-nodpi/dark_notification.png Binary files differindex 6de6c2ae785c..6de6c2ae785c 100644 --- a/tests/SilkFX/res/drawable-nodpi/dark_notification.png +++ b/tests/graphics/SilkFX/res/drawable-nodpi/dark_notification.png diff --git a/tests/SilkFX/res/drawable-nodpi/green_sweep_gradient.xml b/tests/graphics/SilkFX/res/drawable-nodpi/green_sweep_gradient.xml index c600d0f66325..c600d0f66325 100644 --- a/tests/SilkFX/res/drawable-nodpi/green_sweep_gradient.xml +++ b/tests/graphics/SilkFX/res/drawable-nodpi/green_sweep_gradient.xml diff --git a/tests/SilkFX/res/drawable-nodpi/grey_sweep_gradient.xml b/tests/graphics/SilkFX/res/drawable-nodpi/grey_sweep_gradient.xml index d0c17fa2e1b9..d0c17fa2e1b9 100644 --- a/tests/SilkFX/res/drawable-nodpi/grey_sweep_gradient.xml +++ b/tests/graphics/SilkFX/res/drawable-nodpi/grey_sweep_gradient.xml diff --git a/tests/SilkFX/res/drawable-nodpi/light_gradient.xml b/tests/graphics/SilkFX/res/drawable-nodpi/light_gradient.xml index c75f925647e7..c75f925647e7 100644 --- a/tests/SilkFX/res/drawable-nodpi/light_gradient.xml +++ b/tests/graphics/SilkFX/res/drawable-nodpi/light_gradient.xml diff --git a/tests/SilkFX/res/drawable-nodpi/light_notification.png b/tests/graphics/SilkFX/res/drawable-nodpi/light_notification.png Binary files differindex 81a67cd3d388..81a67cd3d388 100644 --- a/tests/SilkFX/res/drawable-nodpi/light_notification.png +++ b/tests/graphics/SilkFX/res/drawable-nodpi/light_notification.png diff --git a/tests/SilkFX/res/drawable-nodpi/red_sweep_gradient.xml b/tests/graphics/SilkFX/res/drawable-nodpi/red_sweep_gradient.xml index e3b834a46406..e3b834a46406 100644 --- a/tests/SilkFX/res/drawable-nodpi/red_sweep_gradient.xml +++ b/tests/graphics/SilkFX/res/drawable-nodpi/red_sweep_gradient.xml diff --git a/tests/SilkFX/res/drawable/background_blur_drawable.xml b/tests/graphics/SilkFX/res/drawable/background_blur_drawable.xml index 173ca99bdfdf..173ca99bdfdf 100644 --- a/tests/SilkFX/res/drawable/background_blur_drawable.xml +++ b/tests/graphics/SilkFX/res/drawable/background_blur_drawable.xml diff --git a/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml b/tests/graphics/SilkFX/res/drawable/blur_activity_background_drawable_white.xml index bd8942d46383..bd8942d46383 100644 --- a/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml +++ b/tests/graphics/SilkFX/res/drawable/blur_activity_background_drawable_white.xml diff --git a/tests/SilkFX/res/layout-television/activity_glass.xml b/tests/graphics/SilkFX/res/layout-television/activity_glass.xml index 1f566860da3d..1f566860da3d 100644 --- a/tests/SilkFX/res/layout-television/activity_glass.xml +++ b/tests/graphics/SilkFX/res/layout-television/activity_glass.xml diff --git a/tests/SilkFX/res/layout/activity_background_blur.xml b/tests/graphics/SilkFX/res/layout/activity_background_blur.xml index f13c0883cb01..f13c0883cb01 100644 --- a/tests/SilkFX/res/layout/activity_background_blur.xml +++ b/tests/graphics/SilkFX/res/layout/activity_background_blur.xml diff --git a/tests/SilkFX/res/layout/activity_glass.xml b/tests/graphics/SilkFX/res/layout/activity_glass.xml index aa09f276d5c8..aa09f276d5c8 100644 --- a/tests/SilkFX/res/layout/activity_glass.xml +++ b/tests/graphics/SilkFX/res/layout/activity_glass.xml diff --git a/tests/SilkFX/res/layout/bling_notifications.xml b/tests/graphics/SilkFX/res/layout/bling_notifications.xml index 6d266b701a68..6d266b701a68 100644 --- a/tests/SilkFX/res/layout/bling_notifications.xml +++ b/tests/graphics/SilkFX/res/layout/bling_notifications.xml diff --git a/tests/SilkFX/res/layout/color_grid.xml b/tests/graphics/SilkFX/res/layout/color_grid.xml index 37242eee7195..37242eee7195 100644 --- a/tests/SilkFX/res/layout/color_grid.xml +++ b/tests/graphics/SilkFX/res/layout/color_grid.xml diff --git a/tests/SilkFX/res/layout/color_mode_controls.xml b/tests/graphics/SilkFX/res/layout/color_mode_controls.xml index c0c0bab8a605..c0c0bab8a605 100644 --- a/tests/SilkFX/res/layout/color_mode_controls.xml +++ b/tests/graphics/SilkFX/res/layout/color_mode_controls.xml diff --git a/tests/SilkFX/res/layout/common_base.xml b/tests/graphics/SilkFX/res/layout/common_base.xml index c0eaf9bc1476..c0eaf9bc1476 100644 --- a/tests/SilkFX/res/layout/common_base.xml +++ b/tests/graphics/SilkFX/res/layout/common_base.xml diff --git a/tests/SilkFX/res/layout/gainmap_decode_test.xml b/tests/graphics/SilkFX/res/layout/gainmap_decode_test.xml index e7ef61f8dac1..e7ef61f8dac1 100644 --- a/tests/SilkFX/res/layout/gainmap_decode_test.xml +++ b/tests/graphics/SilkFX/res/layout/gainmap_decode_test.xml diff --git a/tests/SilkFX/res/layout/gainmap_image.xml b/tests/graphics/SilkFX/res/layout/gainmap_image.xml index b0ed9147585e..b0ed9147585e 100644 --- a/tests/SilkFX/res/layout/gainmap_image.xml +++ b/tests/graphics/SilkFX/res/layout/gainmap_image.xml diff --git a/tests/SilkFX/res/layout/gainmap_metadata.xml b/tests/graphics/SilkFX/res/layout/gainmap_metadata.xml index 4cc3e0cbdb83..4cc3e0cbdb83 100644 --- a/tests/SilkFX/res/layout/gainmap_metadata.xml +++ b/tests/graphics/SilkFX/res/layout/gainmap_metadata.xml diff --git a/tests/SilkFX/res/layout/gainmap_transform_test.xml b/tests/graphics/SilkFX/res/layout/gainmap_transform_test.xml index 5aeb53661cbc..5aeb53661cbc 100644 --- a/tests/SilkFX/res/layout/gainmap_transform_test.xml +++ b/tests/graphics/SilkFX/res/layout/gainmap_transform_test.xml diff --git a/tests/SilkFX/res/layout/gradient_sweep.xml b/tests/graphics/SilkFX/res/layout/gradient_sweep.xml index 261022a40380..261022a40380 100644 --- a/tests/SilkFX/res/layout/gradient_sweep.xml +++ b/tests/graphics/SilkFX/res/layout/gradient_sweep.xml diff --git a/tests/SilkFX/res/layout/hdr_glows.xml b/tests/graphics/SilkFX/res/layout/hdr_glows.xml index b6050645866a..b6050645866a 100644 --- a/tests/SilkFX/res/layout/hdr_glows.xml +++ b/tests/graphics/SilkFX/res/layout/hdr_glows.xml diff --git a/tests/SilkFX/res/layout/hdr_image_viewer.xml b/tests/graphics/SilkFX/res/layout/hdr_image_viewer.xml index 9816430cd915..9816430cd915 100644 --- a/tests/SilkFX/res/layout/hdr_image_viewer.xml +++ b/tests/graphics/SilkFX/res/layout/hdr_image_viewer.xml diff --git a/tests/SilkFX/res/values/style.xml b/tests/graphics/SilkFX/res/values/style.xml index 66edbb5c9382..66edbb5c9382 100644 --- a/tests/SilkFX/res/values/style.xml +++ b/tests/graphics/SilkFX/res/values/style.xml diff --git a/tests/SilkFX/src/com/android/test/silkfx/Main.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/Main.kt index 59a6078376cf..59a6078376cf 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/Main.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/Main.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/app/BaseDemoActivity.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/app/BaseDemoActivity.kt index 89011b51b8d6..89011b51b8d6 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/app/BaseDemoActivity.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/app/BaseDemoActivity.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/app/CommonDemoActivity.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/app/CommonDemoActivity.kt index e56ce40463f4..e56ce40463f4 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/app/CommonDemoActivity.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/app/CommonDemoActivity.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/app/HdrImageViewer.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/app/HdrImageViewer.kt index 7302169f4d1b..7302169f4d1b 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/app/HdrImageViewer.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/app/HdrImageViewer.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/app/WindowObserver.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/app/WindowObserver.kt index 3d989a54cf27..3d989a54cf27 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/app/WindowObserver.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/app/WindowObserver.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/common/BaseDrawingView.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/common/BaseDrawingView.kt index f88e6b01483b..f88e6b01483b 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/common/BaseDrawingView.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/common/BaseDrawingView.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt index 56ab755af47b..56ab755af47b 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/common/HDRIndicator.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/common/HDRIndicator.kt index f42161f63811..f42161f63811 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/common/HDRIndicator.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/common/HDRIndicator.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt index 4ad21faec9d4..4ad21faec9d4 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/ColorGrid.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/ColorGrid.kt index 6920f832333f..6920f832333f 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/hdr/ColorGrid.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/ColorGrid.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt index 585320aee615..585320aee615 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt index 7cf69b7780d9..7cf69b7780d9 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapMetadataEditor.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GainmapMetadataEditor.kt index 1a79a11a3718..1a79a11a3718 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapMetadataEditor.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GainmapMetadataEditor.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt index 20984fae2133..20984fae2133 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GlowActivity.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GlowActivity.kt index 64dbb22ace43..64dbb22ace43 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GlowActivity.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GlowActivity.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GlowingCard.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GlowingCard.kt index b388bb659685..b388bb659685 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GlowingCard.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/GlowingCard.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/RadialGlow.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/RadialGlow.kt index 20acb4919c78..20acb4919c78 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/hdr/RadialGlow.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/hdr/RadialGlow.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt index 4d38660e6029..4d38660e6029 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt index dde245ff9baf..dde245ff9baf 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt b/tests/graphics/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt index 41baeadf7a8c..41baeadf7a8c 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt +++ b/tests/graphics/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt diff --git a/tests/VectorDrawableTest/Android.bp b/tests/graphics/VectorDrawableTest/Android.bp index 9da7c5fdbb17..9da7c5fdbb17 100644 --- a/tests/VectorDrawableTest/Android.bp +++ b/tests/graphics/VectorDrawableTest/Android.bp diff --git a/tests/VectorDrawableTest/AndroidManifest.xml b/tests/graphics/VectorDrawableTest/AndroidManifest.xml index 5334dac57ca2..5334dac57ca2 100644 --- a/tests/VectorDrawableTest/AndroidManifest.xml +++ b/tests/graphics/VectorDrawableTest/AndroidManifest.xml diff --git a/tests/VectorDrawableTest/OWNERS b/tests/graphics/VectorDrawableTest/OWNERS index 27e16681899e..27e16681899e 100644 --- a/tests/VectorDrawableTest/OWNERS +++ b/tests/graphics/VectorDrawableTest/OWNERS diff --git a/tests/VectorDrawableTest/res/anim/alpha_animation_progress_bar.xml b/tests/graphics/VectorDrawableTest/res/anim/alpha_animation_progress_bar.xml index 867abc7744a1..867abc7744a1 100644 --- a/tests/VectorDrawableTest/res/anim/alpha_animation_progress_bar.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/alpha_animation_progress_bar.xml diff --git a/tests/VectorDrawableTest/res/anim/animation_favorite.xml b/tests/graphics/VectorDrawableTest/res/anim/animation_favorite.xml index 13bd6f5e00fe..13bd6f5e00fe 100644 --- a/tests/VectorDrawableTest/res/anim/animation_favorite.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/animation_favorite.xml diff --git a/tests/VectorDrawableTest/res/anim/animation_favorite02.xml b/tests/graphics/VectorDrawableTest/res/anim/animation_favorite02.xml index 15d3b8eb530e..15d3b8eb530e 100644 --- a/tests/VectorDrawableTest/res/anim/animation_favorite02.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/animation_favorite02.xml diff --git a/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml b/tests/graphics/VectorDrawableTest/res/anim/animation_grouping_1_01.xml index 8ab79a5c6256..8ab79a5c6256 100644 --- a/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/animation_grouping_1_01.xml diff --git a/tests/VectorDrawableTest/res/anim/animation_grouping_1_02.xml b/tests/graphics/VectorDrawableTest/res/anim/animation_grouping_1_02.xml index ae63203184c2..ae63203184c2 100644 --- a/tests/VectorDrawableTest/res/anim/animation_grouping_1_02.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/animation_grouping_1_02.xml diff --git a/tests/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect1_scale.xml b/tests/graphics/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect1_scale.xml index 73472205db38..73472205db38 100644 --- a/tests/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect1_scale.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect1_scale.xml diff --git a/tests/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect1_translate.xml b/tests/graphics/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect1_translate.xml index 4781ba83ca36..4781ba83ca36 100644 --- a/tests/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect1_translate.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect1_translate.xml diff --git a/tests/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect2_scale.xml b/tests/graphics/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect2_scale.xml index a61af8f7a78c..a61af8f7a78c 100644 --- a/tests/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect2_scale.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect2_scale.xml diff --git a/tests/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect2_translate.xml b/tests/graphics/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect2_translate.xml index 31fa7950922c..31fa7950922c 100644 --- a/tests/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect2_translate.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/animation_linear_progress_bar_rect2_translate.xml diff --git a/tests/VectorDrawableTest/res/anim/blink.xml b/tests/graphics/VectorDrawableTest/res/anim/blink.xml index 714f4911939a..714f4911939a 100644 --- a/tests/VectorDrawableTest/res/anim/blink.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/blink.xml diff --git a/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_fill_outlines.xml b/tests/graphics/VectorDrawableTest/res/anim/ic_hourglass_animation_fill_outlines.xml index 17499d5a7f74..17499d5a7f74 100644 --- a/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_fill_outlines.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/ic_hourglass_animation_fill_outlines.xml diff --git a/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_hourglass_frame.xml b/tests/graphics/VectorDrawableTest/res/anim/ic_hourglass_animation_hourglass_frame.xml index 17499d5a7f74..17499d5a7f74 100644 --- a/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_hourglass_frame.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/ic_hourglass_animation_hourglass_frame.xml diff --git a/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_mask_1.xml b/tests/graphics/VectorDrawableTest/res/anim/ic_hourglass_animation_mask_1.xml index 541792e3b41d..541792e3b41d 100644 --- a/tests/VectorDrawableTest/res/anim/ic_hourglass_animation_mask_1.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/ic_hourglass_animation_mask_1.xml diff --git a/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_arrows_1.xml b/tests/graphics/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_arrows_1.xml index 89b0f7bd5425..89b0f7bd5425 100644 --- a/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_arrows_1.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_arrows_1.xml diff --git a/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_1.xml b/tests/graphics/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_1.xml index 47e1e7145b7d..47e1e7145b7d 100644 --- a/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_1.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_1.xml diff --git a/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_2.xml b/tests/graphics/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_2.xml index f1126cfd618c..f1126cfd618c 100644 --- a/tests/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_2.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/ic_rotate_2_portrait_v2_animation_device_2.xml diff --git a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_cross_1.xml b/tests/graphics/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_cross_1.xml index 993493b007fe..993493b007fe 100644 --- a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_cross_1.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_cross_1.xml diff --git a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_ic_signal_airplane.xml b/tests/graphics/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_ic_signal_airplane.xml index 1bdfde6b3bb7..1bdfde6b3bb7 100644 --- a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_ic_signal_airplane.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_ic_signal_airplane.xml diff --git a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_mask_2.xml b/tests/graphics/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_mask_2.xml index 94b0a3241d4f..94b0a3241d4f 100644 --- a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_mask_2.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_mask_2.xml diff --git a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_path_1_1.xml b/tests/graphics/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_path_1_1.xml index 0a4a7c476c09..0a4a7c476c09 100644 --- a/tests/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_path_1_1.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/ic_signal_airplane_v2_animation_path_1_1.xml diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation01.xml b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation01.xml index d47e019bf4ad..d47e019bf4ad 100644 --- a/tests/VectorDrawableTest/res/anim/trim_path_animation01.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation01.xml diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation02.xml b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation02.xml index 5d688cf8261f..5d688cf8261f 100644 --- a/tests/VectorDrawableTest/res/anim/trim_path_animation02.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation02.xml diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation03.xml b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation03.xml index 0c1073e5b2cd..0c1073e5b2cd 100644 --- a/tests/VectorDrawableTest/res/anim/trim_path_animation03.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation03.xml diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation04.xml b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation04.xml index 4d0aae1c9314..4d0aae1c9314 100644 --- a/tests/VectorDrawableTest/res/anim/trim_path_animation04.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation04.xml diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation05.xml b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation05.xml index 92b1ab51ade8..92b1ab51ade8 100644 --- a/tests/VectorDrawableTest/res/anim/trim_path_animation05.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation05.xml diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation06.xml b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation06.xml index 1a81866669bc..1a81866669bc 100644 --- a/tests/VectorDrawableTest/res/anim/trim_path_animation06.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation06.xml diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation_progress_bar.xml b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation_progress_bar.xml index c9fd6767baff..c9fd6767baff 100644 --- a/tests/VectorDrawableTest/res/anim/trim_path_animation_progress_bar.xml +++ b/tests/graphics/VectorDrawableTest/res/anim/trim_path_animation_progress_bar.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear.xml index e0e3f03d64f5..e0e3f03d64f5 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_clamp.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear_clamp.xml index 6a24453c0198..6a24453c0198 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_linear_clamp.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear_clamp.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear_item.xml index cfb123603735..cfb123603735 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear_item.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml index 18274b9ec55a..18274b9ec55a 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap_mirror.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap_mirror.xml index d342bca32208..d342bca32208 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap_mirror.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap_mirror.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_repeat.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear_item_repeat.xml index afb45aa2eebe..afb45aa2eebe 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_repeat.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_linear_item_repeat.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial.xml index ef6fd70c67f7..ef6fd70c67f7 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_clamp.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial_clamp.xml index 64b32f6fba3f..64b32f6fba3f 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_radial_clamp.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial_clamp.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial_item.xml index c6cea7c5c698..c6cea7c5c698 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial_item.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_repeat.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial_item_repeat.xml index fb4346ad4abd..fb4346ad4abd 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_repeat.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial_item_repeat.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml index fefbe9f05eff..fefbe9f05eff 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short_mirror.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial_item_short_mirror.xml index 8b5ad7c826ac..8b5ad7c826ac 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short_mirror.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_radial_item_short_mirror.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep.xml index e1fbd10b7e91..e1fbd10b7e91 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_clamp.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep_clamp.xml index 80f39f3ee980..80f39f3ee980 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_clamp.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep_clamp.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml index 332b93894960..332b93894960 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml index 3931288c5c25..3931288c5c25 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long_mirror.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep_item_long_mirror.xml index 0890bd6fc733..0890bd6fc733 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long_mirror.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep_item_long_mirror.xml diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_repeat.xml b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep_item_repeat.xml index 2ec50148b44d..2ec50148b44d 100644 --- a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_repeat.xml +++ b/tests/graphics/VectorDrawableTest/res/color/fill_gradient_sweep_item_repeat.xml diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient.xml b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient.xml index cb324c9a7f4e..cb324c9a7f4e 100644 --- a/tests/VectorDrawableTest/res/color/stroke_gradient.xml +++ b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient.xml diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_clamp.xml b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient_clamp.xml index 3d746e720cf8..3d746e720cf8 100644 --- a/tests/VectorDrawableTest/res/color/stroke_gradient_clamp.xml +++ b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient_clamp.xml diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient_item.xml index 15d948c25899..15d948c25899 100644 --- a/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml +++ b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient_item.xml diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml index fda2b88bc3e1..fda2b88bc3e1 100644 --- a/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml +++ b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha_mirror.xml b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient_item_alpha_mirror.xml index 352a2fd463a8..352a2fd463a8 100644 --- a/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha_mirror.xml +++ b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient_item_alpha_mirror.xml diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item_repeat.xml b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient_item_repeat.xml index 42281d15dc0b..42281d15dc0b 100644 --- a/tests/VectorDrawableTest/res/color/stroke_gradient_item_repeat.xml +++ b/tests/graphics/VectorDrawableTest/res/color/stroke_gradient_item_repeat.xml diff --git a/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml b/tests/graphics/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml index 45d88b567ba2..45d88b567ba2 100644 --- a/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml +++ b/tests/graphics/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml diff --git a/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list_simple.xml b/tests/graphics/VectorDrawableTest/res/color/vector_icon_fill_state_list_simple.xml index 0e2467fa9d95..0e2467fa9d95 100644 --- a/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list_simple.xml +++ b/tests/graphics/VectorDrawableTest/res/color/vector_icon_fill_state_list_simple.xml diff --git a/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml b/tests/graphics/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml index 16251c8d50bd..16251c8d50bd 100644 --- a/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml +++ b/tests/graphics/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml diff --git a/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list_simple.xml b/tests/graphics/VectorDrawableTest/res/color/vector_icon_stroke_state_list_simple.xml index 7e6c8cea409a..7e6c8cea409a 100644 --- a/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list_simple.xml +++ b/tests/graphics/VectorDrawableTest/res/color/vector_icon_stroke_state_list_simple.xml diff --git a/tests/VectorDrawableTest/res/drawable-hdpi/icon.png b/tests/graphics/VectorDrawableTest/res/drawable-hdpi/icon.png Binary files differindex 60fbdf5d0403..60fbdf5d0403 100644 --- a/tests/VectorDrawableTest/res/drawable-hdpi/icon.png +++ b/tests/graphics/VectorDrawableTest/res/drawable-hdpi/icon.png diff --git a/tests/VectorDrawableTest/res/drawable-nodpi/bitmap_drawable01.jpg b/tests/graphics/VectorDrawableTest/res/drawable-nodpi/bitmap_drawable01.jpg Binary files differindex dc8c19716be5..dc8c19716be5 100644 --- a/tests/VectorDrawableTest/res/drawable-nodpi/bitmap_drawable01.jpg +++ b/tests/graphics/VectorDrawableTest/res/drawable-nodpi/bitmap_drawable01.jpg diff --git a/tests/VectorDrawableTest/res/drawable/animated_vector_drawable_attr_icon.xml b/tests/graphics/VectorDrawableTest/res/drawable/animated_vector_drawable_attr_icon.xml index 10a0970df29f..10a0970df29f 100644 --- a/tests/VectorDrawableTest/res/drawable/animated_vector_drawable_attr_icon.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/animated_vector_drawable_attr_icon.xml diff --git a/tests/VectorDrawableTest/res/drawable/animated_vector_drawable_attr_icon_animated.xml b/tests/graphics/VectorDrawableTest/res/drawable/animated_vector_drawable_attr_icon_animated.xml index 7e652296ee28..7e652296ee28 100644 --- a/tests/VectorDrawableTest/res/drawable/animated_vector_drawable_attr_icon_animated.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/animated_vector_drawable_attr_icon_animated.xml diff --git a/tests/VectorDrawableTest/res/drawable/animation_drawable_vector.xml b/tests/graphics/VectorDrawableTest/res/drawable/animation_drawable_vector.xml index a588960821ab..a588960821ab 100644 --- a/tests/VectorDrawableTest/res/drawable/animation_drawable_vector.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/animation_drawable_vector.xml diff --git a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml b/tests/graphics/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml index 8b0ceda4939f..8b0ceda4939f 100644 --- a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml diff --git a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable_favorite.xml b/tests/graphics/VectorDrawableTest/res/drawable/animation_vector_drawable_favorite.xml index 9d8381fd5e62..9d8381fd5e62 100644 --- a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable_favorite.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/animation_vector_drawable_favorite.xml diff --git a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable_grouping_1.xml b/tests/graphics/VectorDrawableTest/res/drawable/animation_vector_drawable_grouping_1.xml index 4a7e4f6d870f..4a7e4f6d870f 100644 --- a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable_grouping_1.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/animation_vector_drawable_grouping_1.xml diff --git a/tests/VectorDrawableTest/res/drawable/animation_vector_linear_progress_bar.xml b/tests/graphics/VectorDrawableTest/res/drawable/animation_vector_linear_progress_bar.xml index 05bf8335c2a7..05bf8335c2a7 100644 --- a/tests/VectorDrawableTest/res/drawable/animation_vector_linear_progress_bar.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/animation_vector_linear_progress_bar.xml diff --git a/tests/VectorDrawableTest/res/drawable/animation_vector_progress_bar.xml b/tests/graphics/VectorDrawableTest/res/drawable/animation_vector_progress_bar.xml index 4d46ee8f27d8..4d46ee8f27d8 100644 --- a/tests/VectorDrawableTest/res/drawable/animation_vector_progress_bar.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/animation_vector_progress_bar.xml diff --git a/tests/VectorDrawableTest/res/drawable/btn_radio_on_to_off_bundle.xml b/tests/graphics/VectorDrawableTest/res/drawable/btn_radio_on_to_off_bundle.xml index 4f05090f8b01..4f05090f8b01 100644 --- a/tests/VectorDrawableTest/res/drawable/btn_radio_on_to_off_bundle.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/btn_radio_on_to_off_bundle.xml diff --git a/tests/VectorDrawableTest/res/drawable/ic_hourglass.xml b/tests/graphics/VectorDrawableTest/res/drawable/ic_hourglass.xml index 5b409227456c..5b409227456c 100644 --- a/tests/VectorDrawableTest/res/drawable/ic_hourglass.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/ic_hourglass.xml diff --git a/tests/VectorDrawableTest/res/drawable/ic_hourglass_animation.xml b/tests/graphics/VectorDrawableTest/res/drawable/ic_hourglass_animation.xml index 3d87376c314d..3d87376c314d 100644 --- a/tests/VectorDrawableTest/res/drawable/ic_hourglass_animation.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/ic_hourglass_animation.xml diff --git a/tests/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2.xml b/tests/graphics/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2.xml index b549423f2db1..b549423f2db1 100644 --- a/tests/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2.xml diff --git a/tests/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2_animation.xml b/tests/graphics/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2_animation.xml index 199fbf8b884e..199fbf8b884e 100644 --- a/tests/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2_animation.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/ic_rotate_2_portrait_v2_animation.xml diff --git a/tests/VectorDrawableTest/res/drawable/ic_signal_airplane_v2.xml b/tests/graphics/VectorDrawableTest/res/drawable/ic_signal_airplane_v2.xml index 8b2a1a8e4346..8b2a1a8e4346 100644 --- a/tests/VectorDrawableTest/res/drawable/ic_signal_airplane_v2.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/ic_signal_airplane_v2.xml diff --git a/tests/VectorDrawableTest/res/drawable/ic_signal_airplane_v2_animation.xml b/tests/graphics/VectorDrawableTest/res/drawable/ic_signal_airplane_v2_animation.xml index bde2b38f871a..bde2b38f871a 100644 --- a/tests/VectorDrawableTest/res/drawable/ic_signal_airplane_v2_animation.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/ic_signal_airplane_v2_animation.xml diff --git a/tests/VectorDrawableTest/res/drawable/icon.png b/tests/graphics/VectorDrawableTest/res/drawable/icon.png Binary files differindex cb40a1988b52..cb40a1988b52 100644 --- a/tests/VectorDrawableTest/res/drawable/icon.png +++ b/tests/graphics/VectorDrawableTest/res/drawable/icon.png diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.xml b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_drawable04.xml index a0a801ca45d5..a0a801ca45d5 100644 --- a/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_drawable04.xml diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml index 3cf8e483eb51..3cf8e483eb51 100644 --- a/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml index 768fe39f26af..768fe39f26af 100644 --- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml index 96d378c26b47..96d378c26b47 100644 --- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02.xml b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable02.xml index 6a67b0232a4d..6a67b0232a4d 100644 --- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable02.xml diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml index b722da15d9d1..b722da15d9d1 100644 --- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml index e24dd1fc5b49..e24dd1fc5b49 100644 --- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml index e788bc261789..e788bc261789 100644 --- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable01.xml index 89afde22f635..89afde22f635 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable01.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable02.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable02.xml index f5d647ceaa8f..f5d647ceaa8f 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable02.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable02.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable03.xml index 7cddda177b39..7cddda177b39 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable03.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable04.xml index 0f3fb95f5d46..0f3fb95f5d46 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable04.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable05.xml index f94ecba1ffb8..f94ecba1ffb8 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable05.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable06.xml index 98b623572eb7..98b623572eb7 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable06.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable07.xml index 88c4a1eaea48..88c4a1eaea48 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable07.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable08.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable08.xml index 75529e2fd4ed..75529e2fd4ed 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable08.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable08.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable09.xml index 853a77000d4c..853a77000d4c 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable09.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable10.xml index 83ed194a14e4..83ed194a14e4 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable10.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable11.xml index b3d7d8eed349..b3d7d8eed349 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable11.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable12.xml index 69ae62c19aba..69ae62c19aba 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable12.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable13.xml index 2468a1b303cb..2468a1b303cb 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable13.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable14.xml index 01e24d302288..01e24d302288 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable14.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable15.xml index 4bab2e37898a..4bab2e37898a 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable15.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable16.xml index 107cda2ca233..107cda2ca233 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable16.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable17.xml index 801954986ab7..801954986ab7 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable17.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable18.xml index c93bdb94f646..c93bdb94f646 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable18.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable19.xml index 996b6beff8bf..996b6beff8bf 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable19.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable20.xml index 58021446bdc5..58021446bdc5 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable20.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable21.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable21.xml index 5626b44e4b50..5626b44e4b50 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable21.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable21.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable22.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable22.xml index 5b40d0d07013..5b40d0d07013 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable22.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable22.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable23.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable23.xml index 6ab6ffd2b1fb..6ab6ffd2b1fb 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable23.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable23.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable24.xml index f0b46994dc23..f0b46994dc23 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable24.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable25.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable25.xml index f46d14eb89f1..f46d14eb89f1 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable25.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable25.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable26.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable26.xml index 29cff525543b..29cff525543b 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable26.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable26.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable27.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable27.xml index b0f0cee86a73..b0f0cee86a73 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable27.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable27.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable28.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable28.xml index 2d2783b8f41e..2d2783b8f41e 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable28.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable28.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable29.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable29.xml index c0e9b2abba90..c0e9b2abba90 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable29.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable29.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable30.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable30.xml index 3dff196e96ec..3dff196e96ec 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable30.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable30.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml index f93486e70c56..f93486e70c56 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_group_clip.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_group_clip.xml index 9574d7e524c3..9574d7e524c3 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_group_clip.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_group_clip.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_grouping_1.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_grouping_1.xml index 7839ad19d0f1..7839ad19d0f1 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_grouping_1.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_grouping_1.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_linear_progress_bar.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_linear_progress_bar.xml index a6da114b511b..a6da114b511b 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_linear_progress_bar.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_linear_progress_bar.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_progress_bar.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_progress_bar.xml index 22cd9959ade8..22cd9959ade8 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_progress_bar.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_progress_bar.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml index 88bf777bdaea..88bf777bdaea 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml index 530c73b20e44..530c73b20e44 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml index 200eb617a9e8..200eb617a9e8 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale3.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_scale3.xml index a40fc9c21595..a40fc9c21595 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale3.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_drawable_scale3.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_create.xml index 0a6cedc5ced1..0a6cedc5ced1 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_create.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_delete.xml index 94c10dfd6656..94c10dfd6656 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_delete.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml index d5d86d80269b..d5d86d80269b 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml index 9754e4bed48b..9754e4bed48b 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml index d67aca7cdaec..d67aca7cdaec 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1_clamp.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_1_clamp.xml index 2fa440a84cff..2fa440a84cff 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1_clamp.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_1_clamp.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml index abf3c7a86b80..abf3c7a86b80 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2_repeat.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_2_repeat.xml index 5a43f804a6e0..5a43f804a6e0 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2_repeat.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_2_repeat.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml index 5f9726f72c03..5f9726f72c03 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3_mirror.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_3_mirror.xml index e8de7c2b1f5d..e8de7c2b1f5d 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3_mirror.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_gradient_3_mirror.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_heart.xml index 870e508319e2..870e508319e2 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_heart.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_schedule.xml index 3f79968d88a9..3f79968d88a9 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_schedule.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_settings.xml index 7bd6304f78e4..7bd6304f78e4 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_settings.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_simple.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_state_list_simple.xml index 9f08fe83015e..9f08fe83015e 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_simple.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_state_list_simple.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_theme.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_state_list_theme.xml index b1ed85025040..b1ed85025040 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_theme.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_icon_state_list_theme.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_test01.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_test01.xml index dd71ef0e88f5..dd71ef0e88f5 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_test01.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_test01.xml diff --git a/tests/VectorDrawableTest/res/drawable/vector_test02.xml b/tests/graphics/VectorDrawableTest/res/drawable/vector_test02.xml index e4f48de862fa..e4f48de862fa 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_test02.xml +++ b/tests/graphics/VectorDrawableTest/res/drawable/vector_test02.xml diff --git a/tests/VectorDrawableTest/res/interpolator/btn_radio_to_off_mtrl_animation_interpolator_0.xml b/tests/graphics/VectorDrawableTest/res/interpolator/btn_radio_to_off_mtrl_animation_interpolator_0.xml index d3728c475d9b..d3728c475d9b 100644 --- a/tests/VectorDrawableTest/res/interpolator/btn_radio_to_off_mtrl_animation_interpolator_0.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/btn_radio_to_off_mtrl_animation_interpolator_0.xml diff --git a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml b/tests/graphics/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml index 489596c4fe5b..489596c4fe5b 100644 --- a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/custom_path_interpolator.xml diff --git a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_favorite.xml b/tests/graphics/VectorDrawableTest/res/interpolator/custom_path_interpolator_favorite.xml index 3d125e490573..3d125e490573 100644 --- a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_favorite.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/custom_path_interpolator_favorite.xml diff --git a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_grouping_1_01.xml b/tests/graphics/VectorDrawableTest/res/interpolator/custom_path_interpolator_grouping_1_01.xml index 6877bd96285d..6877bd96285d 100644 --- a/tests/VectorDrawableTest/res/interpolator/custom_path_interpolator_grouping_1_01.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/custom_path_interpolator_grouping_1_01.xml diff --git a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_rotation_interpolator.xml b/tests/graphics/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_rotation_interpolator.xml index f798a84087c6..f798a84087c6 100644 --- a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_rotation_interpolator.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_rotation_interpolator.xml diff --git a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_scalex_interpolator.xml b/tests/graphics/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_scalex_interpolator.xml index 314cf448b9eb..314cf448b9eb 100644 --- a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_scalex_interpolator.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_arrows_1_scalex_interpolator.xml diff --git a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_1_rotation_interpolator.xml b/tests/graphics/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_1_rotation_interpolator.xml index f798a84087c6..f798a84087c6 100644 --- a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_1_rotation_interpolator.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_1_rotation_interpolator.xml diff --git a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_2_pathdata_interpolator.xml b/tests/graphics/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_2_pathdata_interpolator.xml index f798a84087c6..f798a84087c6 100644 --- a/tests/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_2_pathdata_interpolator.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/ic_rotate_2_portrait_v2_device_2_pathdata_interpolator.xml diff --git a/tests/VectorDrawableTest/res/interpolator/ic_signal_airplane_v2_path_1_1_pathdata_interpolator.xml b/tests/graphics/VectorDrawableTest/res/interpolator/ic_signal_airplane_v2_path_1_1_pathdata_interpolator.xml index 4917f770cae1..4917f770cae1 100644 --- a/tests/VectorDrawableTest/res/interpolator/ic_signal_airplane_v2_path_1_1_pathdata_interpolator.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/ic_signal_airplane_v2_path_1_1_pathdata_interpolator.xml diff --git a/tests/VectorDrawableTest/res/interpolator/trim_end_interpolator.xml b/tests/graphics/VectorDrawableTest/res/interpolator/trim_end_interpolator.xml index 54b5ebd7aa86..54b5ebd7aa86 100644 --- a/tests/VectorDrawableTest/res/interpolator/trim_end_interpolator.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/trim_end_interpolator.xml diff --git a/tests/VectorDrawableTest/res/interpolator/trim_start_interpolator.xml b/tests/graphics/VectorDrawableTest/res/interpolator/trim_start_interpolator.xml index c06c196088dd..c06c196088dd 100644 --- a/tests/VectorDrawableTest/res/interpolator/trim_start_interpolator.xml +++ b/tests/graphics/VectorDrawableTest/res/interpolator/trim_start_interpolator.xml diff --git a/tests/VectorDrawableTest/res/layout/activity_animated_vector_drawable_attr.xml b/tests/graphics/VectorDrawableTest/res/layout/activity_animated_vector_drawable_attr.xml index 92680d5da557..92680d5da557 100644 --- a/tests/VectorDrawableTest/res/layout/activity_animated_vector_drawable_attr.xml +++ b/tests/graphics/VectorDrawableTest/res/layout/activity_animated_vector_drawable_attr.xml diff --git a/tests/VectorDrawableTest/res/values/attrs.xml b/tests/graphics/VectorDrawableTest/res/values/attrs.xml index 98bf99217b11..98bf99217b11 100644 --- a/tests/VectorDrawableTest/res/values/attrs.xml +++ b/tests/graphics/VectorDrawableTest/res/values/attrs.xml diff --git a/tests/VectorDrawableTest/res/values/colors.xml b/tests/graphics/VectorDrawableTest/res/values/colors.xml index 6eb303649c39..6eb303649c39 100644 --- a/tests/VectorDrawableTest/res/values/colors.xml +++ b/tests/graphics/VectorDrawableTest/res/values/colors.xml diff --git a/tests/VectorDrawableTest/res/values/strings.xml b/tests/graphics/VectorDrawableTest/res/values/strings.xml index a550549faa37..a550549faa37 100644 --- a/tests/VectorDrawableTest/res/values/strings.xml +++ b/tests/graphics/VectorDrawableTest/res/values/strings.xml diff --git a/tests/VectorDrawableTest/res/values/styles.xml b/tests/graphics/VectorDrawableTest/res/values/styles.xml index 8adc03460d90..8adc03460d90 100644 --- a/tests/VectorDrawableTest/res/values/styles.xml +++ b/tests/graphics/VectorDrawableTest/res/values/styles.xml diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java index 538655552d28..538655552d28 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java index 47ca482b7771..47ca482b7771 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableDupPerf.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableDupPerf.java index 047e494a9551..047e494a9551 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableDupPerf.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableDupPerf.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java index 8f538aee78aa..8f538aee78aa 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/BitmapDrawableDupe.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/BitmapDrawableDupe.java index 36c8f2b4adf2..36c8f2b4adf2 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/BitmapDrawableDupe.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/BitmapDrawableDupe.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/BoundsCheckTest.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/BoundsCheckTest.java index e2d77ca7e40b..e2d77ca7e40b 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/BoundsCheckTest.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/BoundsCheckTest.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/ScaleDrawableTests.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/ScaleDrawableTests.java index c5be6c417f69..c5be6c417f69 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/ScaleDrawableTests.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/ScaleDrawableTests.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java index 0b3ea4d293d2..0b3ea4d293d2 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java index 85fc452add3e..85fc452add3e 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java index 93b06b6f047b..93b06b6f047b 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java index a00bc5e35c15..a00bc5e35c15 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java index 0d2d2e48e4c9..0d2d2e48e4c9 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java index 9d3eded60721..9d3eded60721 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java index 704d3d76bbec..704d3d76bbec 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java index 34301923b0b6..34301923b0b6 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java +++ b/tests/graphics/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java index a1a39ff173b4..59dc68900100 100644 --- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java +++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java @@ -117,6 +117,16 @@ public class VcnGatewayConnectionConfigTest { return buildTestConfig(UNDERLYING_NETWORK_TEMPLATES); } + // Public for use in VcnGatewayConnectionTest + public static VcnGatewayConnectionConfig.Builder newTestBuilderMinimal() { + final VcnGatewayConnectionConfig.Builder builder = newBuilder(); + for (int caps : EXPOSED_CAPS) { + builder.addExposedCapability(caps); + } + + return builder; + } + private static VcnGatewayConnectionConfig.Builder newBuilder() { // Append a unique identifier to the name prefix to guarantee that all created // VcnGatewayConnectionConfigs have a unique name (required by VcnConfig). @@ -125,6 +135,17 @@ public class VcnGatewayConnectionConfigTest { TUNNEL_CONNECTION_PARAMS); } + private static VcnGatewayConnectionConfig.Builder newBuilderMinimal() { + final VcnGatewayConnectionConfig.Builder builder = + new VcnGatewayConnectionConfig.Builder( + "newBuilderMinimal", TUNNEL_CONNECTION_PARAMS); + for (int caps : EXPOSED_CAPS) { + builder.addExposedCapability(caps); + } + + return builder; + } + private static VcnGatewayConnectionConfig buildTestConfigWithExposedCapsAndOptions( VcnGatewayConnectionConfig.Builder builder, Set<Integer> gatewayOptions, @@ -273,6 +294,7 @@ public class VcnGatewayConnectionConfigTest { assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis()); assertEquals(MAX_MTU, config.getMaxMtu()); + assertTrue(config.isSafeModeEnabled()); assertFalse( config.hasGatewayOption( @@ -290,6 +312,14 @@ public class VcnGatewayConnectionConfigTest { } @Test + public void testBuilderAndGettersSafeModeDisabled() { + final VcnGatewayConnectionConfig config = + newBuilderMinimal().setSafeModeEnabled(false).build(); + + assertFalse(config.isSafeModeEnabled()); + } + + @Test public void testPersistableBundle() { final VcnGatewayConnectionConfig config = buildTestConfig(); @@ -305,6 +335,14 @@ public class VcnGatewayConnectionConfigTest { } @Test + public void testPersistableBundleSafeModeDisabled() { + final VcnGatewayConnectionConfig config = + newBuilderMinimal().setSafeModeEnabled(false).build(); + + assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle())); + } + + @Test public void testParsePersistableBundleWithoutVcnUnderlyingNetworkTemplates() { PersistableBundle configBundle = buildTestConfig().toPersistableBundle(); configBundle.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, null); @@ -411,4 +449,18 @@ public class VcnGatewayConnectionConfigTest { assertEquals(config, configEqual); assertNotEquals(config, configNotEqual); } + + @Test + public void testSafeModeEnableDisableEquality() throws Exception { + final VcnGatewayConnectionConfig config = newBuilderMinimal().build(); + final VcnGatewayConnectionConfig configEqual = newBuilderMinimal().build(); + + assertEquals(config.isSafeModeEnabled(), configEqual.isSafeModeEnabled()); + + final VcnGatewayConnectionConfig configNotEqual = + newBuilderMinimal().setSafeModeEnabled(false).build(); + + assertEquals(config, configEqual); + assertNotEquals(config, configNotEqual); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index 302af523a4bd..f84616426389 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -75,6 +75,9 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback; +import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration; +import com.android.server.vcn.VcnGatewayConnection.VcnIkeSession; +import com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent; import com.android.server.vcn.routeselection.UnderlyingNetworkRecord; import com.android.server.vcn.util.MtuUtils; @@ -651,6 +654,74 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection verifySafeModeStateAndCallbackFired(2 /* invocationCount */, true /* isInSafeMode */); } + private void verifySetSafeModeAlarm( + boolean safeModeEnabledByCaller, + boolean safeModeConfigFlagEnabled, + boolean expectingSafeModeEnabled) + throws Exception { + final VcnGatewayConnectionConfig config = + VcnGatewayConnectionConfigTest.newTestBuilderMinimal() + .setSafeModeEnabled(safeModeEnabledByCaller) + .build(); + final VcnGatewayConnection.Dependencies deps = + mock(VcnGatewayConnection.Dependencies.class); + setUpWakeupMessage( + mSafeModeTimeoutAlarm, VcnGatewayConnection.SAFEMODE_TIMEOUT_ALARM, deps); + doReturn(safeModeConfigFlagEnabled).when(mFeatureFlags).safeModeConfig(); + + final VcnGatewayConnection connection = + new VcnGatewayConnection( + mVcnContext, + TEST_SUB_GRP, + TEST_SUBSCRIPTION_SNAPSHOT, + config, + mGatewayStatusCallback, + true /* isMobileDataEnabled */, + deps); + + connection.setSafeModeAlarm(); + + final int expectedCallCnt = expectingSafeModeEnabled ? 1 : 0; + verify(deps, times(expectedCallCnt)) + .newWakeupMessage( + eq(mVcnContext), + any(), + eq(VcnGatewayConnection.SAFEMODE_TIMEOUT_ALARM), + any()); + } + + @Test + public void testSafeModeEnabled_configFlagEnabled() throws Exception { + verifySetSafeModeAlarm( + true /* safeModeEnabledByCaller */, + true /* safeModeConfigFlagEnabled */, + true /* expectingSafeModeEnabled */); + } + + @Test + public void testSafeModeEnabled_configFlagDisabled() throws Exception { + verifySetSafeModeAlarm( + true /* safeModeEnabledByCaller */, + false /* safeModeConfigFlagEnabled */, + true /* expectingSafeModeEnabled */); + } + + @Test + public void testSafeModeDisabled_configFlagEnabled() throws Exception { + verifySetSafeModeAlarm( + false /* safeModeEnabledByCaller */, + true /* safeModeConfigFlagEnabled */, + false /* expectingSafeModeEnabled */); + } + + @Test + public void testSafeModeDisabled_configFlagDisabled() throws Exception { + verifySetSafeModeAlarm( + false /* safeModeEnabledByCaller */, + false /* safeModeConfigFlagEnabled */, + true /* expectingSafeModeEnabled */); + } + private Consumer<VcnNetworkAgent> setupNetworkAndGetUnwantedCallback() { triggerChildOpened(); mTestLooper.dispatchAll(); diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java index 5efbf598f941..edced87427c8 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java @@ -53,6 +53,7 @@ import android.net.ipsec.ike.ChildSessionCallback; import android.net.ipsec.ike.IkeSessionCallback; import android.net.ipsec.ike.IkeSessionConfiguration; import android.net.ipsec.ike.IkeSessionConnectionInfo; +import android.net.vcn.FeatureFlags; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnGatewayConnectionConfigTest; import android.os.ParcelUuid; @@ -165,6 +166,7 @@ public class VcnGatewayConnectionTestBase { @NonNull protected final Context mContext; @NonNull protected final TestLooper mTestLooper; @NonNull protected final VcnNetworkProvider mVcnNetworkProvider; + @NonNull protected final FeatureFlags mFeatureFlags; @NonNull protected final VcnContext mVcnContext; @NonNull protected final VcnGatewayConnectionConfig mConfig; @NonNull protected final VcnGatewayStatusCallback mGatewayStatusCallback; @@ -190,6 +192,7 @@ public class VcnGatewayConnectionTestBase { mContext = mock(Context.class); mTestLooper = new TestLooper(); mVcnNetworkProvider = mock(VcnNetworkProvider.class); + mFeatureFlags = mock(FeatureFlags.class); mVcnContext = mock(VcnContext.class); mConfig = VcnGatewayConnectionConfigTest.buildTestConfig(); mGatewayStatusCallback = mock(VcnGatewayStatusCallback.class); @@ -222,6 +225,7 @@ public class VcnGatewayConnectionTestBase { doReturn(mContext).when(mVcnContext).getContext(); doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper(); doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider(); + doReturn(mFeatureFlags).when(mVcnContext).getFeatureFlags(); doReturn(mUnderlyingNetworkController) .when(mDeps) @@ -241,8 +245,15 @@ public class VcnGatewayConnectionTestBase { doReturn(ELAPSED_REAL_TIME).when(mDeps).getElapsedRealTime(); } + protected void setUpWakeupMessage( + @NonNull WakeupMessage msg, + @NonNull String cmdName, + VcnGatewayConnection.Dependencies deps) { + doReturn(msg).when(deps).newWakeupMessage(eq(mVcnContext), any(), eq(cmdName), any()); + } + private void setUpWakeupMessage(@NonNull WakeupMessage msg, @NonNull String cmdName) { - doReturn(msg).when(mDeps).newWakeupMessage(eq(mVcnContext), any(), eq(cmdName), any()); + setUpWakeupMessage(msg, cmdName, mDeps); } @Before diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index 0d6dc3522d24..40cba3ed316f 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -119,9 +119,9 @@ cc_library_host_static { "io/Util.cpp", "io/ZipArchive.cpp", "link/AutoVersioner.cpp", + "link/FeatureFlagsFilter.cpp", "link/ManifestFixer.cpp", "link/NoDefaultResourceRemover.cpp", - "link/ProductFilter.cpp", "link/PrivateAttributeMover.cpp", "link/ReferenceLinker.cpp", "link/ResourceExcluder.cpp", @@ -134,6 +134,7 @@ cc_library_host_static { "optimize/ResourceFilter.cpp", "optimize/Obfuscator.cpp", "optimize/VersionCollapser.cpp", + "process/ProductFilter.cpp", "process/SymbolTable.cpp", "split/TableSplitter.cpp", "text/Printer.cpp", diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index 03f9715fb265..bb7b13a71412 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -45,6 +45,7 @@ #include "io/StringStream.h" #include "io/Util.h" #include "io/ZipArchive.h" +#include "process/ProductFilter.h" #include "trace/TraceBuffer.h" #include "util/Files.h" #include "util/Util.h" @@ -179,6 +180,15 @@ static bool CompileTable(IAaptContext* context, const CompileOptions& options, if (!res_parser.Parse(&xml_parser)) { return false; } + + if (options.product_.has_value()) { + if (!ProductFilter({*options.product_}, /* remove_default_config_values = */ true) + .Consume(context, &table)) { + context->GetDiagnostics()->Error(android::DiagMessage(path_data.source) + << "failed to filter product"); + return false; + } + } } if (options.pseudolocalize && translatable_file) { diff --git a/tools/aapt2/cmd/Compile.h b/tools/aapt2/cmd/Compile.h index 14a730a1b1a0..984d8901ac56 100644 --- a/tools/aapt2/cmd/Compile.h +++ b/tools/aapt2/cmd/Compile.h @@ -42,6 +42,7 @@ struct CompileOptions { // See comments on aapt::ResourceParserOptions. bool preserve_visibility_of_styleables = false; bool verbose = false; + std::optional<std::string> product_; }; /** Parses flags and compiles resources to be used in linking. */ @@ -76,6 +77,10 @@ class CompileCommand : public Command { AddOptionalFlag("--source-path", "Sets the compiled resource file source file path to the given string.", &options_.source_path); + AddOptionalFlag("--filter-product", + "Leave only resources specific to the given product. All " + "other resources (including defaults) are removed.", + &options_.product_); } int Action(const std::vector<std::string>& args) override; diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 97404fc69af2..cf4dd79e3d96 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -66,6 +66,7 @@ #include "optimize/ResourceDeduper.h" #include "optimize/VersionCollapser.h" #include "process/IResourceTableConsumer.h" +#include "process/ProductFilter.h" #include "process/SymbolTable.h" #include "split/TableSplitter.h" #include "trace/TraceBuffer.h" @@ -387,7 +388,7 @@ ResourceFileFlattener::ResourceFileFlattener(const ResourceFileFlattenerOptions& // Build up the rules for degrading newer attributes to older ones. // NOTE(adamlesinski): These rules are hardcoded right now, but they should be // generated from the attribute definitions themselves (b/62028956). - if (const SymbolTable::Symbol* s = symm->FindById(R::attr::paddingHorizontal)) { + if (symm->FindById(R::attr::paddingHorizontal)) { std::vector<ReplacementAttr> replacements{ {"paddingLeft", R::attr::paddingLeft, Attribute(android::ResTable_map::TYPE_DIMENSION)}, {"paddingRight", R::attr::paddingRight, Attribute(android::ResTable_map::TYPE_DIMENSION)}, @@ -396,7 +397,7 @@ ResourceFileFlattener::ResourceFileFlattener(const ResourceFileFlattenerOptions& util::make_unique<DegradeToManyRule>(std::move(replacements)); } - if (const SymbolTable::Symbol* s = symm->FindById(R::attr::paddingVertical)) { + if (symm->FindById(R::attr::paddingVertical)) { std::vector<ReplacementAttr> replacements{ {"paddingTop", R::attr::paddingTop, Attribute(android::ResTable_map::TYPE_DIMENSION)}, {"paddingBottom", R::attr::paddingBottom, Attribute(android::ResTable_map::TYPE_DIMENSION)}, @@ -405,7 +406,7 @@ ResourceFileFlattener::ResourceFileFlattener(const ResourceFileFlattenerOptions& util::make_unique<DegradeToManyRule>(std::move(replacements)); } - if (const SymbolTable::Symbol* s = symm->FindById(R::attr::layout_marginHorizontal)) { + if (symm->FindById(R::attr::layout_marginHorizontal)) { std::vector<ReplacementAttr> replacements{ {"layout_marginLeft", R::attr::layout_marginLeft, Attribute(android::ResTable_map::TYPE_DIMENSION)}, @@ -416,7 +417,7 @@ ResourceFileFlattener::ResourceFileFlattener(const ResourceFileFlattenerOptions& util::make_unique<DegradeToManyRule>(std::move(replacements)); } - if (const SymbolTable::Symbol* s = symm->FindById(R::attr::layout_marginVertical)) { + if (symm->FindById(R::attr::layout_marginVertical)) { std::vector<ReplacementAttr> replacements{ {"layout_marginTop", R::attr::layout_marginTop, Attribute(android::ResTable_map::TYPE_DIMENSION)}, @@ -2127,7 +2128,7 @@ class Linker { << "can't select products when building static library"); } } else { - ProductFilter product_filter(options_.products); + ProductFilter product_filter(options_.products, /* remove_default_config_values = */ false); if (!product_filter.Consume(context_, &final_table_)) { context_->GetDiagnostics()->Error(android::DiagMessage() << "failed stripping products"); return 1; @@ -2512,6 +2513,28 @@ int LinkCommand::Action(const std::vector<std::string>& args) { } } + // Parse the feature flag values. An argument that starts with '@' points to a file to read flag + // values from. + std::vector<std::string> all_feature_flags_args; + for (const std::string& arg : feature_flags_args_) { + if (util::StartsWith(arg, "@")) { + const std::string path = arg.substr(1, arg.size() - 1); + std::string error; + if (!file::AppendArgsFromFile(path, &all_feature_flags_args, &error)) { + context.GetDiagnostics()->Error(android::DiagMessage(path) << error); + return 1; + } + } else { + all_feature_flags_args.push_back(arg); + } + } + + for (const std::string& arg : all_feature_flags_args) { + if (ParseFeatureFlagsParameter(arg, context.GetDiagnostics(), &options_.feature_flag_values)) { + return 1; + } + } + if (context.GetPackageType() != PackageType::kStaticLib && stable_id_file_path_) { if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path_.value(), &options_.stable_id_map)) { diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index 1b1e93bd480a..26713fd92264 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -17,11 +17,17 @@ #ifndef AAPT2_LINK_H #define AAPT2_LINK_H +#include <optional> #include <regex> +#include <string> +#include <unordered_map> +#include <unordered_set> +#include <vector> #include "Command.h" #include "Resource.h" #include "androidfw/IDiagnostics.h" +#include "cmd/Util.h" #include "format/binary/TableFlattener.h" #include "format/proto/ProtoSerialize.h" #include "link/ManifestFixer.h" @@ -72,6 +78,7 @@ struct LinkOptions { bool use_sparse_encoding = false; std::unordered_set<std::string> extensions_to_not_compress; std::optional<std::regex> regex_to_not_compress; + FeatureFlagValues feature_flag_values; // Static lib options. bool no_static_lib_packages = false; @@ -323,6 +330,7 @@ class LinkCommand : public Command { "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_); } int Action(const std::vector<std::string>& args) override; @@ -347,6 +355,7 @@ class LinkCommand : public Command { std::optional<std::string> stable_id_file_path_; std::vector<std::string> split_args_; std::optional<std::string> trace_folder_; + std::vector<std::string> feature_flags_args_; }; }// namespace aapt diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp index a92f24b82547..678d84628015 100644 --- a/tools/aapt2/cmd/Util.cpp +++ b/tools/aapt2/cmd/Util.cpp @@ -113,6 +113,56 @@ std::unique_ptr<IConfigFilter> ParseConfigFilterParameters(const std::vector<std return std::move(filter); } +bool ParseFeatureFlagsParameter(StringPiece arg, android::IDiagnostics* diag, + FeatureFlagValues* out_feature_flag_values) { + if (arg.empty()) { + return true; + } + + for (StringPiece flag_and_value : util::Tokenize(arg, ',')) { + std::vector<std::string> parts = util::Split(flag_and_value, '='); + if (parts.empty()) { + continue; + } + + if (parts.size() > 2) { + diag->Error(android::DiagMessage() + << "Invalid feature flag and optional value '" << flag_and_value + << "'. Must be in the format 'flag_name[=true|false]"); + return false; + } + + StringPiece flag_name = util::TrimWhitespace(parts[0]); + if (flag_name.empty()) { + diag->Error(android::DiagMessage() << "No name given for one or more flags in: " << arg); + return false; + } + + std::optional<bool> flag_value = {}; + if (parts.size() == 2) { + StringPiece str_flag_value = util::TrimWhitespace(parts[1]); + if (!str_flag_value.empty()) { + flag_value = ResourceUtils::ParseBool(parts[1]); + if (!flag_value.has_value()) { + diag->Error(android::DiagMessage() << "Invalid value for feature flag '" << flag_and_value + << "'. Value must be 'true' or 'false'"); + return false; + } + } + } + + if (auto [it, inserted] = + out_feature_flag_values->try_emplace(std::string(flag_name), flag_value); + !inserted) { + // We are allowing the same flag to appear multiple times, last value wins. + diag->Note(android::DiagMessage() + << "Value for feature flag '" << flag_name << "' was given more than once"); + it->second = flag_value; + } + } + return true; +} + // Adjust the SplitConstraints so that their SDK version is stripped if it // is less than or equal to the minSdk. Otherwise the resources that have had // their SDK version stripped due to minSdk won't ever match. diff --git a/tools/aapt2/cmd/Util.h b/tools/aapt2/cmd/Util.h index 712c07b71695..9ece5dd4d720 100644 --- a/tools/aapt2/cmd/Util.h +++ b/tools/aapt2/cmd/Util.h @@ -17,8 +17,13 @@ #ifndef AAPT_SPLIT_UTIL_H #define AAPT_SPLIT_UTIL_H +#include <functional> +#include <map> +#include <memory> +#include <optional> #include <regex> #include <set> +#include <string> #include <unordered_set> #include "AppInfo.h" @@ -32,6 +37,8 @@ namespace aapt { +using FeatureFlagValues = std::map<std::string, std::optional<bool>, std::less<>>; + // Parses a configuration density (ex. hdpi, xxhdpi, 234dpi, anydpi, etc). // Returns Nothing and logs a human friendly error message if the string was not legal. std::optional<uint16_t> ParseTargetDensityParameter(android::StringPiece arg, @@ -48,6 +55,13 @@ bool ParseSplitParameter(android::StringPiece arg, android::IDiagnostics* diag, std::unique_ptr<IConfigFilter> ParseConfigFilterParameters(const std::vector<std::string>& args, android::IDiagnostics* diag); +// Parses a feature flags parameter, which can contain one or more pairs of flag names and optional +// values, and fills in `out_feature_flag_values` with the parsed values. The pairs in the argument +// are separated by ',' and the name is separated from the value by '=' if there is a value given. +// Example arg: "flag1=true,flag2=false,flag3=,flag4" where flag3 and flag4 have no given value. +bool ParseFeatureFlagsParameter(android::StringPiece arg, android::IDiagnostics* diag, + FeatureFlagValues* out_feature_flag_values); + // Adjust the SplitConstraints so that their SDK version is stripped if it // is less than or equal to the min_sdk. Otherwise the resources that have had // their SDK version stripped due to min_sdk won't ever match. diff --git a/tools/aapt2/cmd/Util_test.cpp b/tools/aapt2/cmd/Util_test.cpp index 139bfbcd0f41..723d87ed0af3 100644 --- a/tools/aapt2/cmd/Util_test.cpp +++ b/tools/aapt2/cmd/Util_test.cpp @@ -25,6 +25,7 @@ #include "util/Files.h" using ::android::ConfigDescription; +using testing::Pair; using testing::UnorderedElementsAre; namespace aapt { @@ -354,6 +355,51 @@ TEST (UtilTest, ParseSplitParameters) { EXPECT_CONFIG_EQ(constraints, expected_configuration); } +TEST(UtilTest, ParseFeatureFlagsParameter_Empty) { + auto diagnostics = test::ContextBuilder().Build()->GetDiagnostics(); + FeatureFlagValues feature_flag_values; + ASSERT_TRUE(ParseFeatureFlagsParameter("", diagnostics, &feature_flag_values)); + EXPECT_TRUE(feature_flag_values.empty()); +} + +TEST(UtilTest, ParseFeatureFlagsParameter_TooManyParts) { + auto diagnostics = test::ContextBuilder().Build()->GetDiagnostics(); + FeatureFlagValues feature_flag_values; + ASSERT_FALSE(ParseFeatureFlagsParameter("foo=bar=baz", diagnostics, &feature_flag_values)); +} + +TEST(UtilTest, ParseFeatureFlagsParameter_NoNameGiven) { + auto diagnostics = test::ContextBuilder().Build()->GetDiagnostics(); + FeatureFlagValues feature_flag_values; + ASSERT_FALSE(ParseFeatureFlagsParameter("foo=true,=false", diagnostics, &feature_flag_values)); +} + +TEST(UtilTest, ParseFeatureFlagsParameter_InvalidValue) { + auto diagnostics = test::ContextBuilder().Build()->GetDiagnostics(); + FeatureFlagValues feature_flag_values; + ASSERT_FALSE(ParseFeatureFlagsParameter("foo=true,bar=42", diagnostics, &feature_flag_values)); +} + +TEST(UtilTest, ParseFeatureFlagsParameter_DuplicateFlag) { + auto diagnostics = test::ContextBuilder().Build()->GetDiagnostics(); + FeatureFlagValues feature_flag_values; + ASSERT_TRUE( + ParseFeatureFlagsParameter("foo=true,bar=true,foo=false", diagnostics, &feature_flag_values)); + EXPECT_THAT(feature_flag_values, UnorderedElementsAre(Pair("foo", std::optional<bool>(false)), + Pair("bar", std::optional<bool>(true)))); +} + +TEST(UtilTest, ParseFeatureFlagsParameter_Valid) { + auto diagnostics = test::ContextBuilder().Build()->GetDiagnostics(); + FeatureFlagValues feature_flag_values; + ASSERT_TRUE(ParseFeatureFlagsParameter("foo= true, bar =FALSE,baz=, quux", diagnostics, + &feature_flag_values)); + EXPECT_THAT(feature_flag_values, + UnorderedElementsAre(Pair("foo", std::optional<bool>(true)), + Pair("bar", std::optional<bool>(false)), + Pair("baz", std::nullopt), Pair("quux", std::nullopt))); +} + TEST (UtilTest, AdjustSplitConstraintsForMinSdk) { std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); diff --git a/tools/aapt2/link/FeatureFlagsFilter.cpp b/tools/aapt2/link/FeatureFlagsFilter.cpp new file mode 100644 index 000000000000..fdf3f74d4e18 --- /dev/null +++ b/tools/aapt2/link/FeatureFlagsFilter.cpp @@ -0,0 +1,104 @@ +/* + * 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. + */ + +#include "link/FeatureFlagsFilter.h" + +#include <string_view> + +#include "androidfw/IDiagnostics.h" +#include "androidfw/Source.h" +#include "util/Util.h" +#include "xml/XmlDom.h" +#include "xml/XmlUtil.h" + +using ::aapt::xml::Element; +using ::aapt::xml::Node; +using ::aapt::xml::NodeCast; + +namespace aapt { + +class FlagsVisitor : public xml::Visitor { + public: + explicit FlagsVisitor(android::IDiagnostics* diagnostics, + const FeatureFlagValues& feature_flag_values, + const FeatureFlagsFilterOptions& options) + : diagnostics_(diagnostics), feature_flag_values_(feature_flag_values), options_(options) { + } + + void Visit(xml::Element* node) override { + std::erase_if(node->children, + [this](std::unique_ptr<xml::Node>& node) { return ShouldRemove(node); }); + VisitChildren(node); + } + + bool HasError() const { + return has_error_; + } + + private: + bool ShouldRemove(std::unique_ptr<xml::Node>& node) { + if (const auto* el = NodeCast<Element>(node.get())) { + auto* attr = el->FindAttribute(xml::kSchemaAndroid, "featureFlag"); + if (attr == nullptr) { + return false; + } + + bool negated = false; + std::string_view flag_name = util::TrimWhitespace(attr->value); + if (flag_name.starts_with('!')) { + negated = true; + flag_name = flag_name.substr(1); + } + + if (auto it = feature_flag_values_.find(std::string(flag_name)); + it != feature_flag_values_.end()) { + if (it->second.has_value()) { + if (options_.remove_disabled_elements) { + // Remove if flag==true && attr=="!flag" (negated) OR flag==false && attr=="flag" + return *it->second == negated; + } + } else if (options_.flags_must_have_value) { + diagnostics_->Error(android::DiagMessage(node->line_number) + << "attribute 'android:featureFlag' has flag '" << flag_name + << "' without a true/false value from --feature_flags parameter"); + has_error_ = true; + return false; + } + } else if (options_.fail_on_unrecognized_flags) { + diagnostics_->Error(android::DiagMessage(node->line_number) + << "attribute 'android:featureFlag' has flag '" << flag_name + << "' not found in flags from --feature_flags parameter"); + has_error_ = true; + return false; + } + } + + return false; + } + + android::IDiagnostics* diagnostics_; + const FeatureFlagValues& feature_flag_values_; + const FeatureFlagsFilterOptions& options_; + bool has_error_ = false; +}; + +bool FeatureFlagsFilter::Consume(IAaptContext* context, xml::XmlResource* doc) { + FlagsVisitor visitor(context->GetDiagnostics(), feature_flag_values_, options_); + doc->root->Accept(&visitor); + return !visitor.HasError(); +} + +} // namespace aapt diff --git a/tools/aapt2/link/FeatureFlagsFilter.h b/tools/aapt2/link/FeatureFlagsFilter.h new file mode 100644 index 000000000000..1d342a71b996 --- /dev/null +++ b/tools/aapt2/link/FeatureFlagsFilter.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + +#pragma once + +#include <optional> +#include <string> +#include <unordered_map> +#include <utility> + +#include "android-base/macros.h" +#include "cmd/Util.h" +#include "process/IResourceTableConsumer.h" + +namespace aapt { + +struct FeatureFlagsFilterOptions { + // If true, elements whose featureFlag values are false (i.e., disabled feature) will be removed. + bool remove_disabled_elements = true; + + // If true, `Consume()` will return false (error) if a flag was found that is not in + // `feature_flag_values`. + bool fail_on_unrecognized_flags = true; + + // If true, `Consume()` will return false (error) if a flag was found whose value in + // `feature_flag_values` is not defined (std::nullopt). + bool flags_must_have_value = true; +}; + +// Looks for the `android:featureFlag` attribute in each XML element, validates the flag names and +// values, and removes elements according to the values in `feature_flag_values`. An element will be +// removed if the flag's given value is FALSE. A "!" before the flag name in the attribute indicates +// a boolean NOT operation, i.e., an element will be removed if the flag's given value is TRUE. For +// example, if the XML is the following: +// +// <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> +// <permission android:name="FOO" android:featureFlag="!flag" +// android:protectionLevel="normal" /> +// <permission android:name="FOO" android:featureFlag="flag" +// android:protectionLevel="dangerous" /> +// </manifest> +// +// If `feature_flag_values` contains {"flag", true}, then the <permission> element with +// protectionLevel="normal" will be removed, and the <permission> element with +// protectionLevel="normal" will be kept. +// +// The `Consume()` function will return false if there is an invalid flag found (see +// FeatureFlagsFilterOptions for customizing the filter's validation behavior). Do not use the XML +// further if there are errors as there may be elements removed already. +class FeatureFlagsFilter : public IXmlResourceConsumer { + public: + explicit FeatureFlagsFilter(FeatureFlagValues feature_flag_values, + FeatureFlagsFilterOptions options) + : feature_flag_values_(std::move(feature_flag_values)), options_(options) { + } + + bool Consume(IAaptContext* context, xml::XmlResource* doc) override; + + private: + DISALLOW_COPY_AND_ASSIGN(FeatureFlagsFilter); + + const FeatureFlagValues feature_flag_values_; + const FeatureFlagsFilterOptions options_; +}; + +} // namespace aapt diff --git a/tools/aapt2/link/FeatureFlagsFilter_test.cpp b/tools/aapt2/link/FeatureFlagsFilter_test.cpp new file mode 100644 index 000000000000..53086cc30f18 --- /dev/null +++ b/tools/aapt2/link/FeatureFlagsFilter_test.cpp @@ -0,0 +1,236 @@ +/* + * 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. + */ + +#include "link/FeatureFlagsFilter.h" + +#include <string_view> + +#include "test/Test.h" + +using ::testing::IsNull; +using ::testing::NotNull; + +namespace aapt { + +// Returns null if there was an error from FeatureFlagsFilter. +std::unique_ptr<xml::XmlResource> VerifyWithOptions(std::string_view str, + const FeatureFlagValues& feature_flag_values, + const FeatureFlagsFilterOptions& options) { + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(str); + FeatureFlagsFilter filter(feature_flag_values, options); + if (filter.Consume(test::ContextBuilder().Build().get(), doc.get())) { + return doc; + } + return {}; +} + +// Returns null if there was an error from FeatureFlagsFilter. +std::unique_ptr<xml::XmlResource> Verify(std::string_view str, + const FeatureFlagValues& feature_flag_values) { + return VerifyWithOptions(str, feature_flag_values, {}); +} + +TEST(FeatureFlagsFilterTest, NoFeatureFlagAttributes) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" /> + </manifest>)EOF", + {{"flag", false}}); + ASSERT_THAT(doc, NotNull()); + auto root = doc->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, NotNull()); +} +TEST(FeatureFlagsFilterTest, RemoveElementWithDisabledFlag) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag="flag" /> + </manifest>)EOF", + {{"flag", false}}); + ASSERT_THAT(doc, NotNull()); + auto root = doc->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, IsNull()); +} + +TEST(FeatureFlagsFilterTest, RemoveElementWithNegatedEnabledFlag) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag="!flag" /> + </manifest>)EOF", + {{"flag", true}}); + ASSERT_THAT(doc, NotNull()); + auto root = doc->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, IsNull()); +} + +TEST(FeatureFlagsFilterTest, KeepElementWithEnabledFlag) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag="flag" /> + </manifest>)EOF", + {{"flag", true}}); + ASSERT_THAT(doc, NotNull()); + auto root = doc->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, NotNull()); +} + +TEST(FeatureFlagsFilterTest, SideBySideEnabledAndDisabled) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag="!flag" + android:protectionLevel="normal" /> + <permission android:name="FOO" android:featureFlag="flag" + android:protectionLevel="dangerous" /> + </manifest>)EOF", + {{"flag", true}}); + ASSERT_THAT(doc, NotNull()); + auto root = doc->root.get(); + ASSERT_THAT(root, NotNull()); + auto children = root->GetChildElements(); + ASSERT_EQ(children.size(), 1); + auto attr = children[0]->FindAttribute(xml::kSchemaAndroid, "protectionLevel"); + ASSERT_THAT(attr, NotNull()); + ASSERT_EQ(attr->value, "dangerous"); +} + +TEST(FeatureFlagsFilterTest, RemoveDeeplyNestedElement) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <application> + <provider /> + <activity> + <layout android:featureFlag="!flag" /> + </activity> + </application> + </manifest>)EOF", + {{"flag", true}}); + ASSERT_THAT(doc, NotNull()); + auto root = doc->root.get(); + ASSERT_THAT(root, NotNull()); + auto application = root->FindChild({}, "application"); + ASSERT_THAT(application, NotNull()); + auto activity = application->FindChild({}, "activity"); + ASSERT_THAT(activity, NotNull()); + auto maybe_removed = activity->FindChild({}, "layout"); + ASSERT_THAT(maybe_removed, IsNull()); +} + +TEST(FeatureFlagsFilterTest, KeepDeeplyNestedElement) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <application> + <provider /> + <activity> + <layout android:featureFlag="flag" /> + </activity> + </application> + </manifest>)EOF", + {{"flag", true}}); + ASSERT_THAT(doc, NotNull()); + auto root = doc->root.get(); + ASSERT_THAT(root, NotNull()); + auto application = root->FindChild({}, "application"); + ASSERT_THAT(application, NotNull()); + auto activity = application->FindChild({}, "activity"); + ASSERT_THAT(activity, NotNull()); + auto maybe_removed = activity->FindChild({}, "layout"); + ASSERT_THAT(maybe_removed, NotNull()); +} + +TEST(FeatureFlagsFilterTest, FailOnEmptyFeatureFlagAttribute) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag=" " /> + </manifest>)EOF", + {{"flag", false}}); + ASSERT_THAT(doc, IsNull()); +} + +TEST(FeatureFlagsFilterTest, FailOnFlagWithNoGivenValue) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag="flag" /> + </manifest>)EOF", + {{"flag", std::nullopt}}); + ASSERT_THAT(doc, IsNull()); +} + +TEST(FeatureFlagsFilterTest, FailOnUnrecognizedFlag) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag="unrecognized" /> + </manifest>)EOF", + {{"flag", true}}); + ASSERT_THAT(doc, IsNull()); +} + +TEST(FeatureFlagsFilterTest, FailOnMultipleValidationErrors) { + auto doc = Verify(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag="bar" /> + <permission android:name="FOO" android:featureFlag="unrecognized" /> + </manifest>)EOF", + {{"flag", std::nullopt}}); + ASSERT_THAT(doc, IsNull()); +} + +TEST(FeatureFlagsFilterTest, OptionRemoveDisabledElementsIsFalse) { + auto doc = VerifyWithOptions(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag="flag" /> + </manifest>)EOF", + {{"flag", false}}, {.remove_disabled_elements = false}); + ASSERT_THAT(doc, NotNull()); + auto root = doc->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, NotNull()); +} + +TEST(FeatureFlagsFilterTest, OptionFlagsMustHaveValueIsFalse) { + auto doc = VerifyWithOptions(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag="flag" /> + </manifest>)EOF", + {{"flag", std::nullopt}}, {.flags_must_have_value = false}); + ASSERT_THAT(doc, NotNull()); + auto root = doc->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, NotNull()); +} + +TEST(FeatureFlagsFilterTest, OptionFailOnUnrecognizedFlagsIsFalse) { + auto doc = VerifyWithOptions(R"EOF( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> + <permission android:name="FOO" android:featureFlag="unrecognized" /> + </manifest>)EOF", + {{"flag", true}}, {.fail_on_unrecognized_flags = false}); + ASSERT_THAT(doc, NotNull()); + auto root = doc->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, NotNull()); +} + +} // namespace aapt diff --git a/tools/aapt2/link/Linkers.h b/tools/aapt2/link/Linkers.h index 44cd276f77a2..18165f7d489f 100644 --- a/tools/aapt2/link/Linkers.h +++ b/tools/aapt2/link/Linkers.h @@ -20,12 +20,12 @@ #include <set> #include <unordered_set> +#include "Resource.h" +#include "SdkConstants.h" #include "android-base/macros.h" +#include "android-base/result.h" #include "androidfw/ConfigDescription.h" #include "androidfw/StringPiece.h" - -#include "Resource.h" -#include "SdkConstants.h" #include "process/IResourceTableConsumer.h" #include "xml/XmlDom.h" @@ -92,28 +92,6 @@ class PrivateAttributeMover : public IResourceTableConsumer { DISALLOW_COPY_AND_ASSIGN(PrivateAttributeMover); }; -class ResourceConfigValue; - -class ProductFilter : public IResourceTableConsumer { - public: - using ResourceConfigValueIter = std::vector<std::unique_ptr<ResourceConfigValue>>::iterator; - - explicit ProductFilter(std::unordered_set<std::string> products) : products_(products) { - } - - ResourceConfigValueIter SelectProductToKeep(const ResourceNameRef& name, - const ResourceConfigValueIter begin, - const ResourceConfigValueIter end, - android::IDiagnostics* diag); - - bool Consume(IAaptContext* context, ResourceTable* table) override; - - private: - DISALLOW_COPY_AND_ASSIGN(ProductFilter); - - std::unordered_set<std::string> products_; -}; - // Removes namespace nodes and URI information from the XmlResource. // // Once an XmlResource is processed by this consumer, it is no longer able to have its attributes diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index c4f6e70c0cc9..0b16e2c7efe4 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -338,7 +338,7 @@ static bool VerifyUsesFeature(xml::Element* el, android::SourcePathDiagnostics* } bool has_gl_es_version = false; - if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) { + if (el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) { if (has_name) { diag->Error(android::DiagMessage(el->line_number) << "cannot define both android:name and android:glEsVersion in <uses-feature>"); diff --git a/tools/aapt2/link/ProductFilter.cpp b/tools/aapt2/process/ProductFilter.cpp index 9544986fda76..0b1c0a6adb51 100644 --- a/tools/aapt2/link/ProductFilter.cpp +++ b/tools/aapt2/process/ProductFilter.cpp @@ -14,16 +14,18 @@ * limitations under the License. */ -#include "link/Linkers.h" +#include "process/ProductFilter.h" + +#include <algorithm> #include "ResourceTable.h" #include "trace/TraceBuffer.h" namespace aapt { -ProductFilter::ResourceConfigValueIter ProductFilter::SelectProductToKeep( - const ResourceNameRef& name, const ResourceConfigValueIter begin, - const ResourceConfigValueIter end, android::IDiagnostics* diag) { +std::optional<ProductFilter::ResourceConfigValueIter> ProductFilter::SelectProductToKeep( + const ResourceNameRef& name, ResourceConfigValueIter begin, ResourceConfigValueIter end, + android::IDiagnostics* diag) { ResourceConfigValueIter default_product_iter = end; ResourceConfigValueIter selected_product_iter = end; @@ -36,12 +38,11 @@ ProductFilter::ResourceConfigValueIter ProductFilter::SelectProductToKeep( << "selection of product '" << config_value->product << "' for resource " << name << " is ambiguous"); - ResourceConfigValue* previously_selected_config_value = - selected_product_iter->get(); + ResourceConfigValue* previously_selected_config_value = selected_product_iter->get(); diag->Note(android::DiagMessage(previously_selected_config_value->value->GetSource()) << "product '" << previously_selected_config_value->product << "' is also a candidate"); - return end; + return std::nullopt; } // Select this product. @@ -54,11 +55,10 @@ ProductFilter::ResourceConfigValueIter ProductFilter::SelectProductToKeep( diag->Error(android::DiagMessage(config_value->value->GetSource()) << "multiple default products defined for resource " << name); - ResourceConfigValue* previously_default_config_value = - default_product_iter->get(); + ResourceConfigValue* previously_default_config_value = default_product_iter->get(); diag->Note(android::DiagMessage(previously_default_config_value->value->GetSource()) << "default product also defined here"); - return end; + return std::nullopt; } // Mark the default. @@ -66,9 +66,16 @@ ProductFilter::ResourceConfigValueIter ProductFilter::SelectProductToKeep( } } + if (remove_default_config_values_) { + // If we are leaving only a specific product, return early here instead of selecting the default + // value. Returning end here will cause this value set to be skipped, and will be removed with + // ClearEmptyValues method. + return selected_product_iter; + } + if (default_product_iter == end) { diag->Error(android::DiagMessage() << "no default product defined for resource " << name); - return end; + return std::nullopt; } if (selected_product_iter == end) { @@ -89,20 +96,27 @@ bool ProductFilter::Consume(IAaptContext* context, ResourceTable* table) { ResourceConfigValueIter start_range_iter = iter; while (iter != entry->values.end()) { ++iter; - if (iter == entry->values.end() || - (*iter)->config != (*start_range_iter)->config) { + if (iter == entry->values.end() || (*iter)->config != (*start_range_iter)->config) { // End of the array, or we saw a different config, // so this must be the end of a range of products. // Select the product to keep from the set of products defined. ResourceNameRef name(pkg->name, type->named_type, entry->name); - auto value_to_keep = SelectProductToKeep( - name, start_range_iter, iter, context->GetDiagnostics()); - if (value_to_keep == iter) { + auto value_to_keep = + SelectProductToKeep(name, start_range_iter, iter, context->GetDiagnostics()); + if (!value_to_keep.has_value()) { // An error occurred, we could not pick a product. error = true; - } else { + } else if (auto val = value_to_keep.value(); val != iter) { // We selected a product to keep. Move it to the new array. - new_values.push_back(std::move(*value_to_keep)); + if (remove_default_config_values_) { + // We are filtering values with the given product. The selected value here will be + // a new default value, and all other values will be removed. + new_values.push_back( + std::make_unique<ResourceConfigValue>((*val)->config, android::StringPiece{})); + new_values.back()->value = std::move((*val)->value); + } else { + new_values.push_back(std::move(*val)); + } } // Start the next range of products. @@ -115,7 +129,27 @@ bool ProductFilter::Consume(IAaptContext* context, ResourceTable* table) { } } } + + if (remove_default_config_values_) { + ClearEmptyValues(table); + } + return !error; } +void ProductFilter::ClearEmptyValues(ResourceTable* table) { + // Clear any empty packages/types/entries, as remove_default_config_values_ may remove an entire + // value set. + CHECK(remove_default_config_values_) + << __func__ << " should only be called when remove_default_config_values_ is set"; + + for (auto& pkg : table->packages) { + for (auto& type : pkg->types) { + std::erase_if(type->entries, [](auto& entry) { return entry->values.empty(); }); + } + std::erase_if(pkg->types, [](auto& type) { return type->entries.empty(); }); + } + std::erase_if(table->packages, [](auto& package) { return package->types.empty(); }); +} + } // namespace aapt diff --git a/tools/aapt2/process/ProductFilter.h b/tools/aapt2/process/ProductFilter.h new file mode 100644 index 000000000000..0ec2f00863fc --- /dev/null +++ b/tools/aapt2/process/ProductFilter.h @@ -0,0 +1,65 @@ +#pragma once + +#include <memory> +#include <optional> +#include <string> +#include <unordered_set> +#include <utility> +#include <vector> + +#include "Resource.h" +#include "android-base/macros.h" +#include "androidfw/ConfigDescription.h" +#include "androidfw/IDiagnostics.h" +#include "process/IResourceTableConsumer.h" + +namespace aapt { + +class ResourceConfigValue; + +class ProductFilter : public IResourceTableConsumer { + public: + using ResourceConfigValueIter = std::vector<std::unique_ptr<ResourceConfigValue>>::iterator; + + // Setting remove_default_config_values will remove all values other than + // specified product, including default. For example, if the following table + // + // <string name="foo" product="default">foo_default</string> + // <string name="foo" product="tablet">foo_tablet</string> + // <string name="bar">bar</string> + // + // is consumed with tablet, it will result in + // + // <string name="foo">foo_tablet</string> + // + // removing foo_default and bar. This option is to generate an RRO package + // with given product. + explicit ProductFilter(std::unordered_set<std::string> products, + bool remove_default_config_values) + : products_(std::move(products)), + remove_default_config_values_(remove_default_config_values) { + } + + bool Consume(IAaptContext* context, ResourceTable* table) override; + + private: + DISALLOW_COPY_AND_ASSIGN(ProductFilter); + + // SelectProductToKeep returns an iterator for the selected value. + // + // Returns std::nullopt in case of failure (e.g. ambiguous values, missing or duplicated default + // values). + // Returns `end` if keep_as_default_product is set and no value for the specified product was + // found. + std::optional<ResourceConfigValueIter> SelectProductToKeep(const ResourceNameRef& name, + ResourceConfigValueIter begin, + ResourceConfigValueIter end, + android::IDiagnostics* diag); + + void ClearEmptyValues(ResourceTable* table); + + std::unordered_set<std::string> products_; + bool remove_default_config_values_; +}; + +} // namespace aapt diff --git a/tools/aapt2/link/ProductFilter_test.cpp b/tools/aapt2/process/ProductFilter_test.cpp index 2cb9afa05cad..27a82dcc3453 100644 --- a/tools/aapt2/link/ProductFilter_test.cpp +++ b/tools/aapt2/process/ProductFilter_test.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "link/Linkers.h" +#include "process/ProductFilter.h" #include "test/Test.h" @@ -57,17 +57,15 @@ TEST(ProductFilterTest, SelectTwoProducts) { .Build(), context->GetDiagnostics())); - ProductFilter filter({"tablet"}); + ProductFilter filter({"tablet"}, /* remove_default_config_values = */ false); ASSERT_TRUE(filter.Consume(context.get(), &table)); - EXPECT_EQ(nullptr, test::GetValueForConfigAndProduct<Id>( - &table, "android:string/one", land, "")); - EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<Id>( - &table, "android:string/one", land, "tablet")); - EXPECT_EQ(nullptr, test::GetValueForConfigAndProduct<Id>( - &table, "android:string/one", port, "")); - EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<Id>( - &table, "android:string/one", port, "tablet")); + EXPECT_EQ(nullptr, test::GetValueForConfigAndProduct<Id>(&table, "android:string/one", land, "")); + EXPECT_NE(nullptr, + test::GetValueForConfigAndProduct<Id>(&table, "android:string/one", land, "tablet")); + EXPECT_EQ(nullptr, test::GetValueForConfigAndProduct<Id>(&table, "android:string/one", port, "")); + EXPECT_NE(nullptr, + test::GetValueForConfigAndProduct<Id>(&table, "android:string/one", port, "tablet")); } TEST(ProductFilterTest, SelectDefaultProduct) { @@ -88,15 +86,15 @@ TEST(ProductFilterTest, SelectDefaultProduct) { context->GetDiagnostics())); ; - ProductFilter filter(std::unordered_set<std::string>{}); + ProductFilter filter(std::unordered_set<std::string>{}, + /* remove_default_config_values = */ false); ASSERT_TRUE(filter.Consume(context.get(), &table)); - EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<Id>( - &table, "android:string/one", - ConfigDescription::DefaultConfig(), "")); - EXPECT_EQ(nullptr, test::GetValueForConfigAndProduct<Id>( - &table, "android:string/one", - ConfigDescription::DefaultConfig(), "tablet")); + EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<Id>(&table, "android:string/one", + ConfigDescription::DefaultConfig(), "")); + EXPECT_EQ(nullptr, + test::GetValueForConfigAndProduct<Id>(&table, "android:string/one", + ConfigDescription::DefaultConfig(), "tablet")); } TEST(ProductFilterTest, FailOnAmbiguousProduct) { @@ -123,7 +121,7 @@ TEST(ProductFilterTest, FailOnAmbiguousProduct) { .Build(), context->GetDiagnostics())); - ProductFilter filter({"tablet", "no-sdcard"}); + ProductFilter filter({"tablet", "no-sdcard"}, /* remove_default_config_values = */ false); ASSERT_FALSE(filter.Consume(context.get(), &table)); } @@ -144,8 +142,67 @@ TEST(ProductFilterTest, FailOnMultipleDefaults) { .Build(), context->GetDiagnostics())); - ProductFilter filter(std::unordered_set<std::string>{}); + ProductFilter filter(std::unordered_set<std::string>{}, + /* remove_default_config_values = */ false); ASSERT_FALSE(filter.Consume(context.get(), &table)); } +TEST(ProductFilterTest, RemoveDefaultConfigValues) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + + const ConfigDescription land = test::ParseConfigOrDie("land"); + const ConfigDescription port = test::ParseConfigOrDie("port"); + + ResourceTable table; + ASSERT_TRUE(table.AddResource( + NewResourceBuilder(test::ParseNameOrDie("android:string/one")) + .SetValue(test::ValueBuilder<Id>().SetSource(android::Source("land/default.xml")).Build(), + land) + .Build(), + context->GetDiagnostics())); + + ASSERT_TRUE(table.AddResource( + NewResourceBuilder(test::ParseNameOrDie("android:string/one")) + .SetValue(test::ValueBuilder<Id>().SetSource(android::Source("land/tablet.xml")).Build(), + land, "tablet") + .Build(), + context->GetDiagnostics())); + + ASSERT_TRUE(table.AddResource( + NewResourceBuilder(test::ParseNameOrDie("android:string/two")) + .SetValue(test::ValueBuilder<Id>().SetSource(android::Source("land/default.xml")).Build(), + land) + .Build(), + context->GetDiagnostics())); + + ASSERT_TRUE(table.AddResource( + NewResourceBuilder(test::ParseNameOrDie("android:string/one")) + .SetValue(test::ValueBuilder<Id>().SetSource(android::Source("port/default.xml")).Build(), + port) + .Build(), + context->GetDiagnostics())); + + ASSERT_TRUE(table.AddResource( + NewResourceBuilder(test::ParseNameOrDie("android:string/one")) + .SetValue(test::ValueBuilder<Id>().SetSource(android::Source("port/tablet.xml")).Build(), + port, "tablet") + .Build(), + context->GetDiagnostics())); + + ASSERT_TRUE(table.AddResource( + NewResourceBuilder(test::ParseNameOrDie("android:string/two")) + .SetValue(test::ValueBuilder<Id>().SetSource(android::Source("port/default.xml")).Build(), + port) + .Build(), + context->GetDiagnostics())); + + ProductFilter filter({"tablet"}, /* remove_default_config_values = */ true); + ASSERT_TRUE(filter.Consume(context.get(), &table)); + + EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<Id>(&table, "android:string/one", land, "")); + EXPECT_EQ(nullptr, test::GetValueForConfigAndProduct<Id>(&table, "android:string/two", land, "")); + EXPECT_NE(nullptr, test::GetValueForConfigAndProduct<Id>(&table, "android:string/one", port, "")); + EXPECT_EQ(nullptr, test::GetValueForConfigAndProduct<Id>(&table, "android:string/two", port, "")); +} + } // namespace aapt diff --git a/tools/fonts/update_font_metadata.py b/tools/fonts/update_font_metadata.py index c07a98a1e3d2..04a552886d42 100755 --- a/tools/fonts/update_font_metadata.py +++ b/tools/fonts/update_font_metadata.py @@ -19,7 +19,7 @@ def main(): args_parser.add_argument('--revision', help='Updated font revision. Use + to update revision based on the current revision') args = args_parser.parse_args() - font = ttLib.TTFont(args.input) + font = ttLib.TTFont(args.input, recalcTimestamp=False) update_font_revision(font, args.revision) font.save(args.output) diff --git a/tools/lint/README.md b/tools/lint/README.md index b235ad60c799..ff8e44229189 100644 --- a/tools/lint/README.md +++ b/tools/lint/README.md @@ -103,10 +103,15 @@ out/soong/.intermediates/frameworks/base/services/autofill/services.autofill/and As noted above, this baseline file contains warnings too, which might be undesirable. For example, CI tools might surface these warnings in code reviews. In order to create this file without -warnings, we need to pass another flag to lint: `--nowarn`. The easiest way to do this is to -locally change the soong code in -[lint.go](http://cs/aosp-master/build/soong/java/lint.go;l=451;rcl=2e778d5bc4a8d1d77b4f4a3029a4a254ad57db75) -adding `cmd.Flag("--nowarn")` and running lint again. +warnings, we need to pass another flag to lint: `--nowarn`. One option is to add the flag to your +Android.bp file and then run lint again: + +``` + lint: { + extra_check_modules: ["AndroidFrameworkLintChecker"], + flags: ["--nowarn"], + } +``` # Documentation diff --git a/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt index e03d92ab44a0..f1727b78f135 100644 --- a/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt +++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt @@ -30,6 +30,7 @@ const val BINDER_CLASS = "android.os.Binder" const val IINTERFACE_INTERFACE = "android.os.IInterface" const val AIDL_PERMISSION_HELPER_SUFFIX = "_enforcePermission" +const val PERMISSION_PREFIX_LITERAL = "android.permission." /** * If a non java (e.g. c++) backend is enabled, the @EnforcePermission diff --git a/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt index d41fee3fc0dc..24d203fd1116 100644 --- a/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt +++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt @@ -24,33 +24,31 @@ import com.intellij.psi.PsiReferenceList import org.jetbrains.uast.UMethod /** - * Given a UMethod, determine if this method is - * the entrypoint to an interface generated by AIDL, - * returning the interface name if so, otherwise returning null + * Given a UMethod, determine if this method is the entrypoint to an interface + * generated by AIDL, returning the interface name if so, otherwise returning + * null */ fun getContainingAidlInterface(context: JavaContext, node: UMethod): String? { - if (!isContainedInSubclassOfStub(context, node)) return null - for (superMethod in node.findSuperMethods()) { - for (extendsInterface in superMethod.containingClass?.extendsList?.referenceElements - ?: continue) { - if (extendsInterface.qualifiedName == IINTERFACE_INTERFACE) { - return superMethod.containingClass?.name - } - } - } - return null + val containingStub = containingStub(context, node) ?: return null + val superMethod = node.findSuperMethods(containingStub) + if (superMethod.isEmpty()) return null + return containingStub.containingClass?.name } -fun isContainedInSubclassOfStub(context: JavaContext, node: UMethod?): Boolean { +/* Returns the containing Stub class if any. This is not sufficient to infer + * that the method itself extends an AIDL generated method. See + * getContainingAidlInterface for that purpose. + */ +fun containingStub(context: JavaContext, node: UMethod?): PsiClass? { var superClass = node?.containingClass?.superClass while (superClass != null) { - if (isStub(context, superClass)) return true + if (isStub(context, superClass)) return superClass superClass = superClass.superClass } - return false + return null } -fun isStub(context: JavaContext, psiClass: PsiClass?): Boolean { +private fun isStub(context: JavaContext, psiClass: PsiClass?): Boolean { if (psiClass == null) return false if (psiClass.name != "Stub") return false if (!context.evaluator.isStatic(psiClass)) return false diff --git a/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt index 935badecf8d5..624a1987638e 100644 --- a/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt +++ b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt @@ -20,6 +20,7 @@ import com.android.tools.lint.client.api.IssueRegistry import com.android.tools.lint.client.api.Vendor import com.android.tools.lint.detector.api.CURRENT_API import com.google.android.lint.parcel.SaferParcelChecker +import com.google.android.lint.aidl.PermissionAnnotationDetector import com.google.auto.service.AutoService @AutoService(IssueRegistry::class) @@ -37,6 +38,7 @@ class AndroidFrameworkIssueRegistry : IssueRegistry() { SaferParcelChecker.ISSUE_UNSAFE_API_USAGE, // TODO: Currently crashes due to OOM issue // PackageVisibilityDetector.ISSUE_PACKAGE_NAME_NO_PACKAGE_VISIBILITY_FILTERS, + PermissionAnnotationDetector.ISSUE_MISSING_PERMISSION_ANNOTATION, PermissionMethodDetector.ISSUE_PERMISSION_METHOD_USAGE, PermissionMethodDetector.ISSUE_CAN_BE_PERMISSION_METHOD, ) diff --git a/tools/lint/framework/checks/src/main/java/com/google/android/lint/PermissionAnnotationDetector.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/PermissionAnnotationDetector.kt new file mode 100644 index 000000000000..6b50cfd9e5ab --- /dev/null +++ b/tools/lint/framework/checks/src/main/java/com/google/android/lint/PermissionAnnotationDetector.kt @@ -0,0 +1,87 @@ +/* + * 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.google.android.lint.aidl + +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import org.jetbrains.uast.UBlockExpression +import org.jetbrains.uast.UMethod + +/** + * Ensures all AIDL-generated methods are annotated. + * + * This detector is run on system_server to validate that any method that may + * be exposed via an AIDL interface is permission-annotated. That is, it must + * have one of the following annotation: + * - @EnforcePermission + * - @RequiresNoPermission + * - @PermissionManuallyEnforced + */ +class PermissionAnnotationDetector : AidlImplementationDetector() { + + override fun visitAidlMethod( + context: JavaContext, + node: UMethod, + interfaceName: String, + body: UBlockExpression + ) { + if (context.evaluator.isAbstract(node)) return + + if (AIDL_PERMISSION_ANNOTATIONS.any { node.hasAnnotation(it) }) return + + context.report( + ISSUE_MISSING_PERMISSION_ANNOTATION, + node, + context.getLocation(node), + "The method ${node.name} is not permission-annotated." + ) + } + + companion object { + + private val EXPLANATION_MISSING_PERMISSION_ANNOTATION = """ + Interfaces that are exposed by system_server are required to have an annotation which + denotes the type of permission enforced. There are 3 possible options: + - @EnforcePermission + - @RequiresNoPermission + - @PermissionManuallyEnforced + See the documentation of each annotation for further details. + + The annotation on the Java implementation must be the same that the AIDL interface + definition. This is verified by a lint in the build system. + """.trimIndent() + + @JvmField + val ISSUE_MISSING_PERMISSION_ANNOTATION = Issue.create( + id = "MissingPermissionAnnotation", + briefDescription = "No permission annotation on exposed AIDL interface.", + explanation = EXPLANATION_MISSING_PERMISSION_ANNOTATION, + category = Category.CORRECTNESS, + priority = 5, + severity = Severity.ERROR, + implementation = Implementation( + PermissionAnnotationDetector::class.java, + Scope.JAVA_FILE_SCOPE + ), + enabledByDefault = false + ) + } +} diff --git a/tools/lint/framework/checks/src/test/java/com/google/android/lint/PermissionAnnotationDetectorTest.kt b/tools/lint/framework/checks/src/test/java/com/google/android/lint/PermissionAnnotationDetectorTest.kt new file mode 100644 index 000000000000..bce848a2e3a7 --- /dev/null +++ b/tools/lint/framework/checks/src/test/java/com/google/android/lint/PermissionAnnotationDetectorTest.kt @@ -0,0 +1,134 @@ +/* + * 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.google.android.lint.aidl + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestLintTask +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue + +@Suppress("UnstableApiUsage") +class PermissionAnnotationDetectorTest : LintDetectorTest() { + override fun getDetector(): Detector = PermissionAnnotationDetector() + + override fun getIssues(): List<Issue> = listOf( + PermissionAnnotationDetector.ISSUE_MISSING_PERMISSION_ANNOTATION, + ) + + override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) + + /** No issue scenario */ + + fun testDoesNotDetectIssuesInCorrectScenario() { + lint().files( + java( + """ + public class Foo extends IFoo.Stub { + @Override + @android.annotation.EnforcePermission("android.Manifest.permission.READ_CONTACTS") + public void testMethod() { } + } + """ + ).indented(), + *stubs + ) + .run() + .expectClean() + } + + fun testMissingAnnotation() { + lint().files( + java( + """ + public class Bar extends IBar.Stub { + public void testMethod() { } + } + """ + ).indented(), + *stubs + ) + .run() + .expect( + """ + src/Bar.java:2: Error: The method testMethod is not permission-annotated. [MissingPermissionAnnotation] + public void testMethod() { } + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 1 errors, 0 warnings + """ + ) + } + + fun testNoIssueWhenExtendingWithAnotherSubclass() { + lint().files( + java( + """ + public class Foo extends IFoo.Stub { + @Override + @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) + public void testMethod() { } + // not an AIDL method, just another method + public void someRandomMethod() { } + } + """).indented(), + java( + """ + public class Baz extends Bar { + @Override + public void someRandomMethod() { } + } + """).indented(), + *stubs + ) + .run() + .expectClean() + } + + /* Stubs */ + + // A service with permission annotation on the method. + private val interfaceIFoo: TestFile = java( + """ + public interface IFoo extends android.os.IInterface { + public static abstract class Stub extends android.os.Binder implements IFoo { + } + @Override + @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) + public void testMethod(); + @Override + @android.annotation.RequiresNoPermission + public void testMethodNoPermission(); + @Override + @android.annotation.PermissionManuallyEnforced + public void testMethodManual(); + } + """ + ).indented() + + // A service with no permission annotation. + private val interfaceIBar: TestFile = java( + """ + public interface IBar extends android.os.IInterface { + public static abstract class Stub extends android.os.Binder implements IBar { + } + public void testMethod(); + } + """ + ).indented() + + private val stubs = arrayOf(interfaceIFoo, interfaceIBar) +} diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt index a20266a9b140..28eab8f62e74 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt +++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt @@ -20,7 +20,6 @@ import com.android.tools.lint.client.api.IssueRegistry import com.android.tools.lint.client.api.Vendor import com.android.tools.lint.detector.api.CURRENT_API import com.google.android.lint.aidl.EnforcePermissionDetector -import com.google.android.lint.aidl.EnforcePermissionHelperDetector import com.google.android.lint.aidl.SimpleManualPermissionEnforcementDetector import com.google.auto.service.AutoService @@ -30,7 +29,8 @@ class AndroidGlobalIssueRegistry : IssueRegistry() { override val issues = listOf( EnforcePermissionDetector.ISSUE_MISSING_ENFORCE_PERMISSION, EnforcePermissionDetector.ISSUE_MISMATCHING_ENFORCE_PERMISSION, - EnforcePermissionHelperDetector.ISSUE_ENFORCE_PERMISSION_HELPER, + EnforcePermissionDetector.ISSUE_ENFORCE_PERMISSION_HELPER, + EnforcePermissionDetector.ISSUE_MISUSING_ENFORCE_PERMISSION, SimpleManualPermissionEnforcementDetector.ISSUE_SIMPLE_MANUAL_PERMISSION_ENFORCEMENT, ) @@ -45,4 +45,4 @@ class AndroidGlobalIssueRegistry : IssueRegistry() { feedbackUrl = "http://b/issues/new?component=315013", contact = "repsonsible-apis@google.com" ) -}
\ No newline at end of file +} diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt index 0baac2c7aacf..4455a9cda3a8 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt +++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt @@ -30,29 +30,34 @@ import com.android.tools.lint.detector.api.JavaContext import com.android.tools.lint.detector.api.Scope import com.android.tools.lint.detector.api.Severity import com.android.tools.lint.detector.api.SourceCodeScanner +import com.google.android.lint.findCallExpression import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiArrayInitializerMemberValue import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod -import org.jetbrains.uast.UAnnotation +import org.jetbrains.uast.UBlockExpression +import org.jetbrains.uast.UDeclarationsExpression import org.jetbrains.uast.UElement +import org.jetbrains.uast.UExpression import org.jetbrains.uast.UMethod -import org.jetbrains.uast.toUElement +import org.jetbrains.uast.skipParenthesizedExprDown + +import java.util.EnumSet /** - * Lint Detector that ensures that any method overriding a method annotated - * with @EnforcePermission is also annotated with the exact same annotation. - * The intent is to surface the effective permission checks to the service - * implementations. + * Lint Detector that ensures consistency when using the @EnforcePermission + * annotation. Multiple verifications are implemented: * - * This is done with 2 mechanisms: * 1. Visit any annotation usage, to ensure that any derived class will have - * the correct annotation on each methods. This is for the top to bottom - * propagation. - * 2. Visit any annotation, to ensure that if a method is annotated, it has + * the correct annotation on each methods. Even if the subclass does not + * have the annotation, visitAnnotationUsage will be called which allows us + * to capture the issue. + * 2. Visit any method, to ensure that if a method is annotated, it has * its ancestor also annotated. This is to avoid having an annotation on a * Java method without the corresponding annotation on the AIDL interface. + * 3. When annotated, ensures that the first instruction is to call the helper + * method (or the parent helper). */ class EnforcePermissionDetector : Detector(), SourceCodeScanner { @@ -60,9 +65,8 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { return listOf(ANNOTATION_ENFORCE_PERMISSION) } - override fun getApplicableUastTypes(): List<Class<out UElement>> { - return listOf(UAnnotation::class.java) - } + override fun getApplicableUastTypes(): List<Class<out UElement?>> = + listOf(UMethod::class.java) private fun annotationValueGetChildren(elem: PsiElement): Array<PsiElement> { if (elem is PsiArrayInitializerMemberValue) @@ -93,7 +97,7 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { val v1 = ConstantEvaluator.evaluate(context, value1) val v2 = ConstantEvaluator.evaluate(context, value2) if (v1 != null && v2 != null) { - if (v1 != v2) { + if (v1 != v2 && !isOneShortPermissionOfOther(v1, v2)) { return false } } else { @@ -105,7 +109,7 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { for (j in children1.indices) { val c1 = ConstantEvaluator.evaluate(context, children1[j]) val c2 = ConstantEvaluator.evaluate(context, children2[j]) - if (c1 != c2) { + if (c1 != c2 && !isOneShortPermissionOfOther(c1, c2)) { return false } } @@ -114,6 +118,12 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { return true } + private fun isOneShortPermissionOfOther( + permission1: Any?, + permission2: Any? + ): Boolean = permission1 == (permission2 as? String)?.removePrefix(PERMISSION_PREFIX_LITERAL) || + permission2 == (permission1 as? String)?.removePrefix(PERMISSION_PREFIX_LITERAL) + private fun compareMethods( context: JavaContext, element: UElement, @@ -121,11 +131,6 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { overriddenMethod: PsiMethod, checkEquivalence: Boolean = true ) { - // If method is not from a Stub subclass, this method shouldn't use @EP at all. - // This is handled by EnforcePermissionHelperDetector. - if (!isContainedInSubclassOfStub(context, overridingMethod.toUElement() as? UMethod)) { - return - } val overridingAnnotation = overridingMethod.getAnnotation(ANNOTATION_ENFORCE_PERMISSION) val overriddenAnnotation = overriddenMethod.getAnnotation(ANNOTATION_ENFORCE_PERMISSION) val location = context.getLocation(element) @@ -161,40 +166,112 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { ) { if (usageInfo.type == AnnotationUsageType.METHOD_OVERRIDE && annotationInfo.origin == AnnotationOrigin.METHOD) { + /* Ignore implementations that are not a sub-class of Stub (i.e., Proxy). */ + val uMethod = element as? UMethod ?: return + if (getContainingAidlInterface(context, uMethod) == null) { + return + } val overridingMethod = element.sourcePsi as PsiMethod val overriddenMethod = usageInfo.referenced as PsiMethod compareMethods(context, element, overridingMethod, overriddenMethod) } } - override fun createUastHandler(context: JavaContext): UElementHandler { - return object : UElementHandler() { - override fun visitAnnotation(node: UAnnotation) { - if (node.qualifiedName != ANNOTATION_ENFORCE_PERMISSION) { - return - } - val method = node.uastParent as? UMethod ?: return - val overridingMethod = method as PsiMethod - val parents = overridingMethod.findSuperMethods() - for (overriddenMethod in parents) { - // The equivalence check can be skipped, if both methods are - // annotated, it will be verified by visitAnnotationUsage. - compareMethods(context, method, overridingMethod, - overriddenMethod, checkEquivalence = false) - } + override fun createUastHandler(context: JavaContext): UElementHandler = AidlStubHandler(context) + + private inner class AidlStubHandler(val context: JavaContext) : UElementHandler() { + override fun visitMethod(node: UMethod) { + if (context.evaluator.isAbstract(node)) return + if (!node.hasAnnotation(ANNOTATION_ENFORCE_PERMISSION)) return + + val stubClass = containingStub(context, node) + if (stubClass == null) { + context.report( + ISSUE_MISUSING_ENFORCE_PERMISSION, + node, + context.getLocation(node), + "The class of ${node.name} does not inherit from an AIDL generated Stub class" + ) + return + } + + /* Check that we are connected to the super class */ + val overridingMethod = node as PsiMethod + val parents = overridingMethod.findSuperMethods(stubClass) + if (parents.isEmpty()) { + context.report( + ISSUE_MISUSING_ENFORCE_PERMISSION, + node, + context.getLocation(node), + "The method ${node.name} does not override an AIDL generated method" + ) + return + } + for (overriddenMethod in parents) { + // The equivalence check can be skipped, if both methods are + // annotated, it will be verified by visitAnnotationUsage. + compareMethods(context, node, overridingMethod, + overriddenMethod, checkEquivalence = false) + } + + /* Check that the helper is called as a first instruction */ + val targetExpression = getHelperMethodCallSourceString(node) + val message = + "Method must start with $targetExpression or super.${node.name}(), if applicable" + + val firstExpression = (node.uastBody as? UBlockExpression) + ?.expressions?.firstOrNull() + + if (firstExpression == null) { + context.report( + ISSUE_ENFORCE_PERMISSION_HELPER, + context.getLocation(node), + message, + ) + return + } + + val firstExpressionSource = firstExpression.skipParenthesizedExprDown() + .asSourceString() + .filterNot(Char::isWhitespace) + + if (firstExpressionSource != targetExpression && + firstExpressionSource != "super.$targetExpression") { + // calling super.<methodName>() is also legal + val directSuper = context.evaluator.getSuperMethod(node) + val firstCall = findCallExpression(firstExpression)?.resolve() + if (directSuper != null && firstCall == directSuper) return + + val locationTarget = getLocationTarget(firstExpression) + val expressionLocation = context.getLocation(locationTarget) + + context.report( + ISSUE_ENFORCE_PERMISSION_HELPER, + context.getLocation(node), + message, + getHelperMethodFix(node, expressionLocation), + ) } } } companion object { + + private const val HELPER_SUFFIX = "_enforcePermission" + val EXPLANATION = """ - The @EnforcePermission annotation is used to indicate that the underlying binder code - has already verified the caller's permissions before calling the appropriate method. The - verification code is usually generated by the AIDL compiler, which also takes care of - annotating the generated Java code. + The @EnforcePermission annotation is used to delegate the verification of the caller's + permissions to a generated AIDL method. In order to surface that information to platform developers, the same annotation must be used on the implementation class or methods. + + The @EnforcePermission annotation can only be used on methods whose class extends from + the Stub class generated by the AIDL compiler. When @EnforcePermission is applied, the + AIDL compiler generates a Stub method to do the permission check called yourMethodName$HELPER_SUFFIX. + + yourMethodName$HELPER_SUFFIX must be executed before any other operation. To do that, you can + either call it directly, or call it indirectly via super.yourMethodName(). """ val ISSUE_MISSING_ENFORCE_PERMISSION: Issue = Issue.create( @@ -206,7 +283,7 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { severity = Severity.ERROR, implementation = Implementation( EnforcePermissionDetector::class.java, - Scope.JAVA_FILE_SCOPE + EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES) ) ) @@ -219,8 +296,47 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { severity = Severity.ERROR, implementation = Implementation( EnforcePermissionDetector::class.java, - Scope.JAVA_FILE_SCOPE + EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES) + ) + ) + + val ISSUE_ENFORCE_PERMISSION_HELPER: Issue = Issue.create( + id = "MissingEnforcePermissionHelper", + briefDescription = """Missing permission-enforcing method call in AIDL method + |annotated with @EnforcePermission""".trimMargin(), + explanation = EXPLANATION, + category = Category.SECURITY, + priority = 6, + severity = Severity.ERROR, + implementation = Implementation( + EnforcePermissionDetector::class.java, + EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES) ) ) + + val ISSUE_MISUSING_ENFORCE_PERMISSION: Issue = Issue.create( + id = "MisusingEnforcePermissionAnnotation", + briefDescription = "@EnforcePermission cannot be used here", + explanation = EXPLANATION, + category = Category.SECURITY, + priority = 6, + severity = Severity.ERROR, + implementation = Implementation( + EnforcePermissionDetector::class.java, + EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES) + ) + ) + + /** + * handles an edge case with UDeclarationsExpression, where sourcePsi is null, + * resulting in an incorrect Location if used directly + */ + private fun getLocationTarget(firstExpression: UExpression): PsiElement? { + if (firstExpression.sourcePsi != null) return firstExpression.sourcePsi + if (firstExpression is UDeclarationsExpression) { + return firstExpression.declarations.firstOrNull()?.sourcePsi + } + return null + } } } diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt deleted file mode 100644 index df13af516514..000000000000 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.android.lint.aidl - -import com.android.tools.lint.client.api.UElementHandler -import com.android.tools.lint.detector.api.Category -import com.android.tools.lint.detector.api.Detector -import com.android.tools.lint.detector.api.Implementation -import com.android.tools.lint.detector.api.Issue -import com.android.tools.lint.detector.api.JavaContext -import com.android.tools.lint.detector.api.Scope -import com.android.tools.lint.detector.api.Severity -import com.android.tools.lint.detector.api.SourceCodeScanner -import com.google.android.lint.findCallExpression -import com.intellij.psi.PsiElement -import org.jetbrains.uast.UBlockExpression -import org.jetbrains.uast.UDeclarationsExpression -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UExpression -import org.jetbrains.uast.UMethod -import org.jetbrains.uast.skipParenthesizedExprDown - -class EnforcePermissionHelperDetector : Detector(), SourceCodeScanner { - override fun getApplicableUastTypes(): List<Class<out UElement?>> = - listOf(UMethod::class.java) - - override fun createUastHandler(context: JavaContext): UElementHandler = AidlStubHandler(context) - - private inner class AidlStubHandler(val context: JavaContext) : UElementHandler() { - override fun visitMethod(node: UMethod) { - if (context.evaluator.isAbstract(node)) return - if (!node.hasAnnotation(ANNOTATION_ENFORCE_PERMISSION)) return - - if (!isContainedInSubclassOfStub(context, node)) { - context.report( - ISSUE_MISUSING_ENFORCE_PERMISSION, - node, - context.getLocation(node), - "The class of ${node.name} does not inherit from an AIDL generated Stub class" - ) - return - } - - val targetExpression = getHelperMethodCallSourceString(node) - val message = - "Method must start with $targetExpression or super.${node.name}(), if applicable" - - val firstExpression = (node.uastBody as? UBlockExpression) - ?.expressions?.firstOrNull() - - if (firstExpression == null) { - context.report( - ISSUE_ENFORCE_PERMISSION_HELPER, - context.getLocation(node), - message, - ) - return - } - - val firstExpressionSource = firstExpression.skipParenthesizedExprDown() - .asSourceString() - .filterNot(Char::isWhitespace) - - if (firstExpressionSource != targetExpression && - firstExpressionSource != "super.$targetExpression") { - // calling super.<methodName>() is also legal - val directSuper = context.evaluator.getSuperMethod(node) - val firstCall = findCallExpression(firstExpression)?.resolve() - if (directSuper != null && firstCall == directSuper) return - - val locationTarget = getLocationTarget(firstExpression) - val expressionLocation = context.getLocation(locationTarget) - - context.report( - ISSUE_ENFORCE_PERMISSION_HELPER, - context.getLocation(node), - message, - getHelperMethodFix(node, expressionLocation), - ) - } - } - } - - companion object { - private const val HELPER_SUFFIX = "_enforcePermission" - - private const val EXPLANATION = """ - The @EnforcePermission annotation can only be used on methods whose class extends from - the Stub class generated by the AIDL compiler. When @EnforcePermission is applied, the - AIDL compiler generates a Stub method to do the permission check called yourMethodName$HELPER_SUFFIX. - - yourMethodName$HELPER_SUFFIX must be executed before any other operation. To do that, you can - either call it directly, or call it indirectly via super.yourMethodName(). - """ - - val ISSUE_ENFORCE_PERMISSION_HELPER: Issue = Issue.create( - id = "MissingEnforcePermissionHelper", - briefDescription = """Missing permission-enforcing method call in AIDL method - |annotated with @EnforcePermission""".trimMargin(), - explanation = EXPLANATION, - category = Category.SECURITY, - priority = 6, - severity = Severity.ERROR, - implementation = Implementation( - EnforcePermissionHelperDetector::class.java, - Scope.JAVA_FILE_SCOPE - ) - ) - - val ISSUE_MISUSING_ENFORCE_PERMISSION: Issue = Issue.create( - id = "MisusingEnforcePermissionAnnotation", - briefDescription = "@EnforcePermission cannot be used here", - explanation = EXPLANATION, - category = Category.SECURITY, - priority = 6, - severity = Severity.ERROR, - implementation = Implementation( - EnforcePermissionDetector::class.java, - Scope.JAVA_FILE_SCOPE - ) - ) - - /** - * handles an edge case with UDeclarationsExpression, where sourcePsi is null, - * resulting in an incorrect Location if used directly - */ - private fun getLocationTarget(firstExpression: UExpression): PsiElement? { - if (firstExpression.sourcePsi != null) return firstExpression.sourcePsi - if (firstExpression is UDeclarationsExpression) { - return firstExpression.declarations.firstOrNull()?.sourcePsi - } - return null - } - } -} diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionDetectorTest.kt index 75b00737a168..2afca05f8130 100644 --- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionDetectorTest.kt +++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionDetectorTest.kt @@ -28,7 +28,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { override fun getIssues(): List<Issue> = listOf( EnforcePermissionDetector.ISSUE_MISSING_ENFORCE_PERMISSION, - EnforcePermissionDetector.ISSUE_MISMATCHING_ENFORCE_PERMISSION + EnforcePermissionDetector.ISSUE_MISMATCHING_ENFORCE_PERMISSION, + EnforcePermissionDetector.ISSUE_ENFORCE_PERMISSION_HELPER, + EnforcePermissionDetector.ISSUE_MISUSING_ENFORCE_PERMISSION ) override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) @@ -41,7 +43,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { public class TestClass2 extends IFooMethod.Stub { @Override @EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) - public void testMethod() {} + public void testMethod() { + testMethod_enforcePermission(); + } } """).indented(), *stubs @@ -58,7 +62,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { public class TestClass11 extends IFooMethod.Stub { @Override @EnforcePermission(allOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_PHONE_STATE}) - public void testMethodAll() {} + public void testMethodAll() { + testMethodAll_enforcePermission(); + } } """).indented(), *stubs @@ -75,7 +81,10 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { public class TestClass111 extends IFooMethod.Stub { @Override @EnforcePermission(allOf={"android.permission.INTERNET", android.Manifest.permission.READ_PHONE_STATE}) - public void testMethodAllLiteral() {} + public void testMethodAllLiteral() { + testMethodAllLiteral_enforcePermission(); + + } } """).indented(), *stubs @@ -92,7 +101,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { public class TestClass12 extends IFooMethod.Stub { @Override @EnforcePermission(anyOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_PHONE_STATE}) - public void testMethodAny() {} + public void testMethodAny() { + testMethodAny_enforcePermission(); + } } """).indented(), *stubs @@ -109,7 +120,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { public class TestClass121 extends IFooMethod.Stub { @Override @EnforcePermission(anyOf={"android.permission.INTERNET", android.Manifest.permission.READ_PHONE_STATE}) - public void testMethodAnyLiteral() {} + public void testMethodAnyLiteral() { + testMethodAnyLiteral_enforcePermission(); + } } """).indented(), *stubs @@ -124,7 +137,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { package test.pkg; public class TestClass4 extends IFooMethod.Stub { @android.annotation.EnforcePermission(android.Manifest.permission.INTERNET) - public void testMethod() {} + public void testMethod() { + testMethod_enforcePermission(); + } } """).indented(), *stubs @@ -132,21 +147,67 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { .run() .expect(""" src/test/pkg/TestClass4.java:4: Error: The method TestClass4.testMethod is annotated with @android.annotation.EnforcePermission(android.Manifest.permission.INTERNET) \ - which differs from the overridden method Stub.testMethod: @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE). \ + which differs from the overridden method IFooMethod.testMethod: @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE). \ The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] - public void testMethod() {} + public void testMethod() { ~~~~~~~~~~ 1 errors, 0 warnings """.addLineContinuation()) } + fun testDetectIssuesAnnotationOnNonStubMethod() { + lint().files(java( + """ + package test.pkg; + public class TestClass42 extends IFooMethod.Stub { + @android.annotation.EnforcePermission(android.Manifest.permission.INTERNET) + public void aRegularMethodNotPartOfStub() { + } + } + """).indented(), + *stubs + ) + .run() + .expect(""" + src/test/pkg/TestClass42.java:3: Error: The method aRegularMethodNotPartOfStub does not override an AIDL generated method [MisusingEnforcePermissionAnnotation] + @android.annotation.EnforcePermission(android.Manifest.permission.INTERNET) + ^ + 1 errors, 0 warnings + """.addLineContinuation()) + } + + fun testDetectNoIssuesAnnotationOnNonStubMethod() { + lint().files(java( + """ + package test.pkg; + public class TestClass43 extends IFooMethod.Stub { + public void aRegularMethodNotPartOfStub() { + } + } + """).indented(), java( + """ + package test.pkg; + public class TestClass44 extends TestClass43 { + @Override + public void aRegularMethodNotPartOfStub() { + } + } + """).indented(), + *stubs + ) + .run() + .expectClean() + } + fun testDetectIssuesEmptyAnnotationOnMethod() { lint().files(java( """ package test.pkg; public class TestClass41 extends IFooMethod.Stub { @android.annotation.EnforcePermission - public void testMethod() {} + public void testMethod() { + testMethod_enforcePermission(); + } } """).indented(), *stubs @@ -154,9 +215,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { .run() .expect(""" src/test/pkg/TestClass41.java:4: Error: The method TestClass41.testMethod is annotated with @android.annotation.EnforcePermission \ - which differs from the overridden method Stub.testMethod: @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE). \ + which differs from the overridden method IFooMethod.testMethod: @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE). \ The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] - public void testMethod() {} + public void testMethod() { ~~~~~~~~~~ 1 errors, 0 warnings """.addLineContinuation()) @@ -168,7 +229,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { package test.pkg; public class TestClass9 extends IFooMethod.Stub { @android.annotation.EnforcePermission(anyOf={android.Manifest.permission.INTERNET, android.Manifest.permission.NFC}) - public void testMethodAny() {} + public void testMethodAny() { + testMethodAny_enforcePermission(); + } } """).indented(), *stubs @@ -177,10 +240,10 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { .expect(""" src/test/pkg/TestClass9.java:4: Error: The method TestClass9.testMethodAny is annotated with \ @android.annotation.EnforcePermission(anyOf={android.Manifest.permission.INTERNET, android.Manifest.permission.NFC}) \ - which differs from the overridden method Stub.testMethodAny: \ + which differs from the overridden method IFooMethod.testMethodAny: \ @android.annotation.EnforcePermission(anyOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_PHONE_STATE}). \ The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] - public void testMethodAny() {} + public void testMethodAny() { ~~~~~~~~~~~~~ 1 errors, 0 warnings """.addLineContinuation()) @@ -192,7 +255,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { package test.pkg; public class TestClass91 extends IFooMethod.Stub { @android.annotation.EnforcePermission(anyOf={"android.permission.INTERNET", "android.permissionoopsthisisatypo.READ_PHONE_STATE"}) - public void testMethodAnyLiteral() {} + public void testMethodAnyLiteral() { + testMethodAnyLiteral_enforcePermission(); + } } """).indented(), *stubs @@ -201,10 +266,10 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { .expect(""" src/test/pkg/TestClass91.java:4: Error: The method TestClass91.testMethodAnyLiteral is annotated with \ @android.annotation.EnforcePermission(anyOf={"android.permission.INTERNET", "android.permissionoopsthisisatypo.READ_PHONE_STATE"}) \ - which differs from the overridden method Stub.testMethodAnyLiteral: \ + which differs from the overridden method IFooMethod.testMethodAnyLiteral: \ @android.annotation.EnforcePermission(anyOf={android.Manifest.permission.INTERNET, "android.permission.READ_PHONE_STATE"}). \ The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] - public void testMethodAnyLiteral() {} + public void testMethodAnyLiteral() { ~~~~~~~~~~~~~~~~~~~~ 1 errors, 0 warnings """.addLineContinuation()) @@ -216,7 +281,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { package test.pkg; public class TestClass10 extends IFooMethod.Stub { @android.annotation.EnforcePermission(allOf={android.Manifest.permission.INTERNET, android.Manifest.permission.NFC}) - public void testMethodAll() {} + public void testMethodAll() { + testMethodAll_enforcePermission(); + } } """).indented(), *stubs @@ -225,10 +292,10 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { .expect(""" src/test/pkg/TestClass10.java:4: Error: The method TestClass10.testMethodAll is annotated with \ @android.annotation.EnforcePermission(allOf={android.Manifest.permission.INTERNET, android.Manifest.permission.NFC}) \ - which differs from the overridden method Stub.testMethodAll: \ + which differs from the overridden method IFooMethod.testMethodAll: \ @android.annotation.EnforcePermission(allOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_PHONE_STATE}). \ The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] - public void testMethodAll() {} + public void testMethodAll() { ~~~~~~~~~~~~~ 1 errors, 0 warnings """.addLineContinuation()) @@ -240,7 +307,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { package test.pkg; public class TestClass101 extends IFooMethod.Stub { @android.annotation.EnforcePermission(allOf={"android.permission.INTERNET", "android.permissionoopsthisisatypo.READ_PHONE_STATE"}) - public void testMethodAllLiteral() {} + public void testMethodAllLiteral() { + testMethodAllLiteral_enforcePermission(); + } } """).indented(), *stubs @@ -249,10 +318,10 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { .expect(""" src/test/pkg/TestClass101.java:4: Error: The method TestClass101.testMethodAllLiteral is annotated with \ @android.annotation.EnforcePermission(allOf={"android.permission.INTERNET", "android.permissionoopsthisisatypo.READ_PHONE_STATE"}) \ - which differs from the overridden method Stub.testMethodAllLiteral: \ + which differs from the overridden method IFooMethod.testMethodAllLiteral: \ @android.annotation.EnforcePermission(allOf={android.Manifest.permission.INTERNET, "android.permission.READ_PHONE_STATE"}). \ The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] - public void testMethodAllLiteral() {} + public void testMethodAllLiteral() { ~~~~~~~~~~~~~~~~~~~~ 1 errors, 0 warnings """.addLineContinuation()) @@ -263,16 +332,18 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { """ package test.pkg; public class TestClass6 extends IFooMethod.Stub { - public void testMethod() {} + public void testMethod() { + testMethod_enforcePermission(); + } } """).indented(), *stubs ) .run() .expect(""" - src/test/pkg/TestClass6.java:3: Error: The method TestClass6.testMethod overrides the method Stub.testMethod which is annotated with @EnforcePermission. \ + src/test/pkg/TestClass6.java:3: Error: The method TestClass6.testMethod overrides the method IFooMethod.testMethod which is annotated with @EnforcePermission. \ The same annotation must be used on TestClass6.testMethod [MissingEnforcePermissionAnnotation] - public void testMethod() {} + public void testMethod() { ~~~~~~~~~~ 1 errors, 0 warnings """.addLineContinuation()) @@ -284,16 +355,18 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { package test.pkg; public class TestClass7 extends IBar.Stub { @android.annotation.EnforcePermission(android.Manifest.permission.INTERNET) - public void testMethod() {} + public void testMethod() { + testMethod_enforcePermission(); + } } """).indented(), *stubs ) .run() .expect(""" - src/test/pkg/TestClass7.java:4: Error: The method TestClass7.testMethod overrides the method Stub.testMethod which is not annotated with @EnforcePermission. \ - The same annotation must be used on Stub.testMethod. Did you forget to annotate the AIDL definition? [MissingEnforcePermissionAnnotation] - public void testMethod() {} + src/test/pkg/TestClass7.java:4: Error: The method TestClass7.testMethod overrides the method IBar.testMethod which is not annotated with @EnforcePermission. \ + The same annotation must be used on IBar.testMethod. Did you forget to annotate the AIDL definition? [MissingEnforcePermissionAnnotation] + public void testMethod() { ~~~~~~~~~~ 1 errors, 0 warnings """.addLineContinuation()) @@ -304,7 +377,9 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { """ package test.pkg; public class Default extends IFooMethod.Stub { - public void testMethod() {} + public void testMethod() { + testMethod_enforcePermission(); + } } """).indented(), *stubs @@ -313,23 +388,74 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { .expect( """ src/test/pkg/Default.java:3: Error: The method Default.testMethod \ - overrides the method Stub.testMethod which is annotated with @EnforcePermission. The same annotation must be used on Default.testMethod [MissingEnforcePermissionAnnotation] - public void testMethod() {} + overrides the method IFooMethod.testMethod which is annotated with @EnforcePermission. The same annotation must be used on Default.testMethod [MissingEnforcePermissionAnnotation] + public void testMethod() { ~~~~~~~~~~ - 1 errors, 0 warnings + 1 errors, 0 warnings """.addLineContinuation() ) } - fun testDoesDetectIssuesShortStringsNotAllowed() { + fun testDoesNotDetectIssuesShortStringsAllowedInChildAndParent() { lint().files(java( """ package test.pkg; import android.annotation.EnforcePermission; public class TestClass121 extends IFooMethod.Stub { @Override + @EnforcePermission("READ_PHONE_STATE") + public void testMethod() { + testMethod_enforcePermission(); + } + @Override + @EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) + public void testMethodParentShortPermission() { + testMethodParentShortPermission_enforcePermission(); + } + @Override @EnforcePermission(anyOf={"INTERNET", "READ_PHONE_STATE"}) - public void testMethodAnyLiteral() {} + public void testMethodAnyLiteral() { + testMethodAnyLiteral_enforcePermission(); + } + @Override + @EnforcePermission(anyOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_PHONE_STATE}) + public void testMethodAnyLiteralParentsShortPermission() { + testMethodAnyLiteralParentsShortPermission_enforcePermission(); + } + } + """).indented(), + *stubs + ) + .run() + .expectClean() + } + + fun testDoesDetectIssuesWrongShortStringsInChildAndParent() { + lint().files(java( + """ + package test.pkg; + import android.annotation.EnforcePermission; + public class TestClass121 extends IFooMethod.Stub { + @Override + @EnforcePermission("READ_WRONG_PHONE_STATE") + public void testMethod() { + testMethod_enforcePermission(); + } + @Override + @EnforcePermission(android.Manifest.permission.READ_WRONG_PHONE_STATE) + public void testMethodParentShortPermission() { + testMethodParentShortPermission_enforcePermission(); + } + @Override + @EnforcePermission(anyOf={"WRONG_INTERNET", "READ_PHONE_STATE"}) + public void testMethodAnyLiteral() { + testMethodAnyLiteral_enforcePermission(); + } + @Override + @EnforcePermission(anyOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_WRONG_PHONE_STATE}) + public void testMethodAnyLiteralParentsShortPermission() { + testMethodAnyLiteralParentsShortPermission_enforcePermission(); + } } """).indented(), *stubs @@ -337,14 +463,19 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { .run() .expect( """ - src/test/pkg/TestClass121.java:6: Error: The method \ - TestClass121.testMethodAnyLiteral is annotated with @EnforcePermission(anyOf={"INTERNET", "READ_PHONE_STATE"}) \ - which differs from the overridden method Stub.testMethodAnyLiteral: \ - @android.annotation.EnforcePermission(anyOf={android.Manifest.permission.INTERNET, "android.permission.READ_PHONE_STATE"}). \ - The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] - public void testMethodAnyLiteral() {} - ~~~~~~~~~~~~~~~~~~~~ - 1 errors, 0 warnings + src/test/pkg/TestClass121.java:6: Error: The method TestClass121.testMethod is annotated with @EnforcePermission("READ_WRONG_PHONE_STATE") which differs from the overridden method IFooMethod.testMethod: @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE). The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] + public void testMethod() { + ~~~~~~~~~~ + src/test/pkg/TestClass121.java:11: Error: The method TestClass121.testMethodParentShortPermission is annotated with @EnforcePermission(android.Manifest.permission.READ_WRONG_PHONE_STATE) which differs from the overridden method IFooMethod.testMethodParentShortPermission: @android.annotation.EnforcePermission("READ_PHONE_STATE"). The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] + public void testMethodParentShortPermission() { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestClass121.java:16: Error: The method TestClass121.testMethodAnyLiteral is annotated with @EnforcePermission(anyOf={"WRONG_INTERNET", "READ_PHONE_STATE"}) which differs from the overridden method IFooMethod.testMethodAnyLiteral: @android.annotation.EnforcePermission(anyOf={android.Manifest.permission.INTERNET, "android.permission.READ_PHONE_STATE"}). The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] + public void testMethodAnyLiteral() { + ~~~~~~~~~~~~~~~~~~~~ + src/test/pkg/TestClass121.java:21: Error: The method TestClass121.testMethodAnyLiteralParentsShortPermission is annotated with @EnforcePermission(anyOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_WRONG_PHONE_STATE}) which differs from the overridden method IFooMethod.testMethodAnyLiteralParentsShortPermission: @android.annotation.EnforcePermission(anyOf={"INTERNET", "READ_PHONE_STATE"}). The same annotation must be used for both methods. [MismatchingEnforcePermissionAnnotation] + public void testMethodAnyLiteralParentsShortPermission() { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 4 errors, 0 warnings """.addLineContinuation() ) } @@ -356,28 +487,17 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { """ public interface IFooMethod extends android.os.IInterface { public static abstract class Stub extends android.os.Binder implements IFooMethod { - @Override - @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) - public void testMethod() {} - @Override - @android.annotation.EnforcePermission(anyOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_PHONE_STATE}) - public void testMethodAny() {} - @Override - @android.annotation.EnforcePermission(anyOf={android.Manifest.permission.INTERNET, "android.permission.READ_PHONE_STATE"}) - public void testMethodAnyLiteral() {} - @Override - @android.annotation.EnforcePermission(allOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_PHONE_STATE}) - public void testMethodAll() {} - @Override - @android.annotation.EnforcePermission(allOf={android.Manifest.permission.INTERNET, "android.permission.READ_PHONE_STATE"}) - public void testMethodAllLiteral() {} } @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) public void testMethod(); + @android.annotation.EnforcePermission("READ_PHONE_STATE") + public void testMethodParentShortPermission(); @android.annotation.EnforcePermission(anyOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_PHONE_STATE}) public void testMethodAny() {} @android.annotation.EnforcePermission(anyOf={android.Manifest.permission.INTERNET, "android.permission.READ_PHONE_STATE"}) public void testMethodAnyLiteral() {} + @android.annotation.EnforcePermission(anyOf={"INTERNET", "READ_PHONE_STATE"}) + public void testMethodAnyLiteralParentsShortPermission() {} @android.annotation.EnforcePermission(allOf={android.Manifest.permission.INTERNET, android.Manifest.permission.READ_PHONE_STATE}) public void testMethodAll() {} @android.annotation.EnforcePermission(allOf={android.Manifest.permission.INTERNET, "android.permission.READ_PHONE_STATE"}) @@ -391,8 +511,6 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { """ public interface IBar extends android.os.IInterface { public static abstract class Stub extends android.os.Binder implements IBar { - @Override - public void testMethod() {} } public void testMethod(); } @@ -404,6 +522,7 @@ class EnforcePermissionDetectorTest : LintDetectorTest() { package android.Manifest; class permission { public static final String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE"; + public static final String READ_WRONG_PHONE_STATE = "android.permission.READ_WRONG_PHONE_STATE"; public static final String NFC = "android.permission.NFC"; public static final String INTERNET = "android.permission.INTERNET"; } diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorCodegenTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorCodegenTest.kt index 5a63bb4084d2..a4b0bc3a7c76 100644 --- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorCodegenTest.kt +++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorCodegenTest.kt @@ -25,10 +25,11 @@ import com.android.tools.lint.detector.api.Issue @Suppress("UnstableApiUsage") class EnforcePermissionHelperDetectorCodegenTest : LintDetectorTest() { - override fun getDetector(): Detector = EnforcePermissionHelperDetector() + override fun getDetector(): Detector = EnforcePermissionDetector() override fun getIssues(): List<Issue> = listOf( - EnforcePermissionHelperDetector.ISSUE_ENFORCE_PERMISSION_HELPER + EnforcePermissionDetector.ISSUE_ENFORCE_PERMISSION_HELPER, + EnforcePermissionDetector.ISSUE_MISUSING_ENFORCE_PERMISSION ) override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorTest.kt index 10a6e1da91dc..64e2bfbad7bb 100644 --- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorTest.kt +++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionHelperDetectorTest.kt @@ -20,10 +20,10 @@ import com.android.tools.lint.checks.infrastructure.LintDetectorTest import com.android.tools.lint.checks.infrastructure.TestLintTask class EnforcePermissionHelperDetectorTest : LintDetectorTest() { - override fun getDetector() = EnforcePermissionHelperDetector() + override fun getDetector() = EnforcePermissionDetector() override fun getIssues() = listOf( - EnforcePermissionHelperDetector.ISSUE_ENFORCE_PERMISSION_HELPER, - EnforcePermissionHelperDetector.ISSUE_MISUSING_ENFORCE_PERMISSION + EnforcePermissionDetector.ISSUE_ENFORCE_PERMISSION_HELPER, + EnforcePermissionDetector.ISSUE_MISUSING_ENFORCE_PERMISSION ) override fun lint(): TestLintTask = super.lint().allowMissingSdk() |