diff options
95 files changed, 988 insertions, 433 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index f0b759878e20..f0e0c30fd031 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -13,6 +13,7 @@ // limitations under the License. aconfig_srcjars = [ + ":android.content.pm.flags-aconfig-java{.generated_srcjars}", ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}", ":android.nfc.flags-aconfig-java{.generated_srcjars}", ":android.os.flags-aconfig-java{.generated_srcjars}", @@ -21,6 +22,7 @@ aconfig_srcjars = [ ":com.android.window.flags.window-aconfig-java{.generated_srcjars}", ":com.android.hardware.input-aconfig-java{.generated_srcjars}", ":com.android.text.flags-aconfig-java{.generated_srcjars}", + ":com.android.net.flags-aconfig-java{.generated_srcjars}", ] filegroup { @@ -145,6 +147,26 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } +// Package Manager +aconfig_declarations { + name: "android.content.pm.flags-aconfig", + package: "android.content.pm", + srcs: ["core/java/android/content/pm/flags.aconfig"], +} + +java_aconfig_library { + name: "android.content.pm.flags-aconfig-java", + aconfig_declarations: "android.content.pm.flags-aconfig", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + +java_aconfig_library { + name: "android.content.pm.flags-aconfig-java-host", + aconfig_declarations: "android.content.pm.flags-aconfig", + host_supported: true, + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + // Biometrics aconfig_declarations { name: "android.hardware.biometrics.flags-aconfig", @@ -157,3 +179,10 @@ java_aconfig_library { aconfig_declarations: "android.hardware.biometrics.flags-aconfig", defaults: ["framework-minus-apex-aconfig-java-defaults"], } + +// CoreNetworking +java_aconfig_library { + name: "com.android.net.flags-aconfig-java", + aconfig_declarations: "com.android.net.flags-aconfig", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} diff --git a/Android.mk b/Android.mk index d9e202c9305c..e2c1ed8e9ddb 100644 --- a/Android.mk +++ b/Android.mk @@ -69,9 +69,6 @@ $(SDK_METADATA): $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/framework-doc-stub .PHONY: framework-doc-stubs framework-doc-stubs: $(SDK_METADATA) -# Run this for checkbuild -checkbuild: doc-comment-check-docs - # Include subdirectory makefiles # ============================================================ @@ -34,3 +34,6 @@ per-file TestProtoLibraries.bp = file:platform/tools/tradefederation:/OWNERS per-file ZYGOTE_OWNERS = file:/ZYGOTE_OWNERS per-file SQLITE_OWNERS = file:/SQLITE_OWNERS + +per-file *ravenwood* = file:ravenwood/OWNERS +per-file *Ravenwood* = file:ravenwood/OWNERS diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java index e636f604ddb0..dfa91835bad3 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java @@ -1327,13 +1327,13 @@ public final class JobServiceContext implements ServiceConnection { private void handleOpTimeoutLocked() { switch (mVerb) { case VERB_BINDING: - onSlowAppResponseLocked(/* reschedule */ false, /* updateStopReasons */ true, + // The system may have been too busy. Don't drop the job or trigger an ANR. + onSlowAppResponseLocked(/* reschedule */ true, /* updateStopReasons */ true, /* texCounterMetricId */ "job_scheduler.value_cntr_w_uid_slow_app_response_binding", /* debugReason */ "timed out while binding", /* anrMessage */ "Timed out while trying to bind", - CompatChanges.isChangeEnabled(ANR_PRE_UDC_APIS_ON_SLOW_RESPONSES, - mRunningJob.getUid())); + /* triggerAnr */ false); break; case VERB_STARTING: // Client unresponsive - wedged or failed to respond in time. We don't really diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java index 0a7bffc786cc..4b4e51290abd 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java @@ -1118,6 +1118,7 @@ public final class JobStore { } boolean needFileMigration = false; long nowElapsed = sElapsedRealtimeClock.millis(); + int numDuplicates = 0; synchronized (mLock) { for (File file : files) { final AtomicFile aFile = createJobFile(file); @@ -1126,6 +1127,16 @@ public final class JobStore { if (jobs != null) { for (int i = 0; i < jobs.size(); i++) { JobStatus js = jobs.get(i); + final JobStatus existingJob = this.jobSet.get( + js.getUid(), js.getNamespace(), js.getJobId()); + if (existingJob != null) { + numDuplicates++; + // Jobs are meant to have unique uid-namespace-jobId + // combinations, but we've somehow read multiple jobs with the + // combination. Drop the latter one since keeping both will + // result in other issues. + continue; + } js.prepareLocked(); js.enqueueTime = nowElapsed; this.jobSet.add(js); @@ -1174,6 +1185,10 @@ public final class JobStore { migrateJobFilesAsync(); } + if (numDuplicates > 0) { + Slog.wtf(TAG, "Encountered " + numDuplicates + " duplicate persisted jobs"); + } + // Log the count immediately after loading from boot. mCurrentJobSetSize = numJobs; mScheduledJob30MinHighWaterMark = mCurrentJobSetSize; diff --git a/api/ApiDocs.bp b/api/ApiDocs.bp index 6461c00b1dcd..7142eb5bef53 100644 --- a/api/ApiDocs.bp +++ b/api/ApiDocs.bp @@ -20,41 +20,6 @@ // The API doc generation is done by the various droiddoc modules each of which // is for different format. -///////////////////////////////////////////////////////////////////// -// stub source files are generated using metalava -///////////////////////////////////////////////////////////////////// - -framework_docs_only_libs = [ - "voip-common", - "android.test.mock", - "android-support-annotations", - "android-support-compat", - "android-support-core-ui", - "android-support-core-utils", - "android-support-design", - "android-support-dynamic-animation", - "android-support-exifinterface", - "android-support-fragment", - "android-support-media-compat", - "android-support-percent", - "android-support-transition", - "android-support-v7-cardview", - "android-support-v7-gridlayout", - "android-support-v7-mediarouter", - "android-support-v7-palette", - "android-support-v7-preference", - "android-support-v13", - "android-support-v14-preference", - "android-support-v17-leanback", - "android-support-vectordrawable", - "android-support-animatedvectordrawable", - "android-support-v7-appcompat", - "android-support-v7-recyclerview", - "android-support-v8-renderscript", - "android-support-multidex", - "android-support-multidex-instrumentation", -] - // These defaults enable doc-stub generation, api lint database generation and sdk value generation. stubs_defaults { name: "android-non-updatable-doc-stubs-defaults", @@ -65,7 +30,6 @@ stubs_defaults { ":android-test-mock-sources", ":android-test-runner-sources", ], - libs: framework_docs_only_libs, create_doc_stubs: true, write_sdk_values: true, } @@ -160,7 +124,6 @@ droidstubs { "packages/modules/Media/apex/aidl/stable", ], }, - extensions_info_file: ":sdk-extensions-info", } droidstubs { @@ -195,7 +158,9 @@ framework_docs_only_args = " -android -manifest $(location :frameworks-base-core doc_defaults { name: "framework-docs-default", - libs: framework_docs_only_libs + [ + sdk_version: "none", + system_modules: "none", + libs: [ "stub-annotations", "unsupportedappusage", ], @@ -234,20 +199,6 @@ doc_defaults { }, } -doc_defaults { - name: "framework-dokka-docs-default", -} - -droiddoc { - name: "doc-comment-check-docs", - defaults: ["framework-docs-default"], - srcs: [ - ":framework-doc-stubs", - ], - args: framework_docs_only_args + " -referenceonly -parsecomments", - installable: false, -} - droiddoc { name: "offline-sdk-docs", defaults: ["framework-docs-default"], @@ -301,70 +252,6 @@ droiddoc { } droiddoc { - name: "online-sdk-docs", - defaults: ["framework-docs-default"], - srcs: [ - ":framework-doc-stubs", - ], - hdf: [ - "android.whichdoc online", - "android.hasSamples true", - ], - proofread_file: "online-sdk-docs-proofread.txt", - args: framework_docs_only_args + - " -toroot / -samplegroup Admin " + - " -samplegroup Background " + - " -samplegroup Connectivity " + - " -samplegroup Content " + - " -samplegroup Input " + - " -samplegroup Media " + - " -samplegroup Notification " + - " -samplegroup RenderScript " + - " -samplegroup Security " + - " -samplegroup Sensors " + - " -samplegroup System " + - " -samplegroup Testing " + - " -samplegroup UI " + - " -samplegroup Views " + - " -samplegroup Wearable -samplesdir development/samples/browseable ", -} - -droiddoc { - name: "online-system-api-sdk-docs", - defaults: ["framework-docs-default"], - srcs: [ - ":framework-doc-system-stubs", - ], - hdf: [ - "android.whichdoc online", - "android.hasSamples true", - ], - proofread_file: "online-system-api-sdk-docs-proofread.txt", - args: framework_docs_only_args + - " -referenceonly " + - " -title \"Android SDK - Including system APIs.\" " + - " -hide 101 " + - " -hide 104 " + - " -hide 108 " + - " -toroot / -samplegroup Admin " + - " -samplegroup Background " + - " -samplegroup Connectivity " + - " -samplegroup Content " + - " -samplegroup Input " + - " -samplegroup Media " + - " -samplegroup Notification " + - " -samplegroup RenderScript " + - " -samplegroup Security " + - " -samplegroup Sensors " + - " -samplegroup System " + - " -samplegroup Testing " + - " -samplegroup UI " + - " -samplegroup Views " + - " -samplegroup Wearable -samplesdir development/samples/browseable ", - installable: false, -} - -droiddoc { name: "ds-docs-java", defaults: ["framework-docs-default"], srcs: [ @@ -395,7 +282,6 @@ droiddoc { droiddoc { name: "ds-docs-kt", - defaults: ["framework-dokka-docs-default"], srcs: [ ":framework-doc-stubs", ], @@ -474,44 +360,3 @@ droiddoc { " -atLinksNavtree " + " -navtreeonly ", } - -droiddoc { - name: "online-sdk-dev-docs", - defaults: ["framework-docs-default"], - srcs: [ - ":framework-doc-stubs", - ], - hdf: [ - "android.whichdoc online", - "android.hasSamples true", - ], - proofread_file: "online-sdk-dev-docs-proofread.txt", - args: framework_docs_only_args + - " -toroot / -samplegroup Admin " + - " -samplegroup Background " + - " -samplegroup Connectivity " + - " -samplegroup Content " + - " -samplegroup Input " + - " -samplegroup Media " + - " -samplegroup Notification " + - " -samplegroup RenderScript " + - " -samplegroup Security " + - " -samplegroup Sensors " + - " -samplegroup System " + - " -samplegroup Testing " + - " -samplegroup UI " + - " -samplegroup Views " + - " -samplegroup Wearable -samplesdir development/samples/browseable ", -} - -droiddoc { - name: "hidden-docs", - defaults: ["framework-docs-default"], - srcs: [ - ":framework-doc-stubs", - ], - proofread_file: "hidden-docs-proofread.txt", - args: framework_docs_only_args + - " -referenceonly " + - " -title \"Android SDK - Including hidden APIs.\"", -} diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index 857077d60a5d..a410a58218c4 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -436,6 +436,26 @@ java_api_library { full_api_surface_stub: "android_module_lib_stubs_current_full.from-text", } +// This module generates a stub jar that is a union of the test and module lib +// non-updatable api contributions. Modules should not depend on the stub jar +// generated from this module, as this module is strictly used for hiddenapi only. +java_api_library { + name: "android-non-updatable.stubs.test_module_lib", + api_surface: "module_lib", + api_contributions: [ + "api-stubs-docs-non-updatable.api.contribution", + "system-api-stubs-docs-non-updatable.api.contribution", + "test-api-stubs-docs-non-updatable.api.contribution", + "module-lib-api-stubs-docs-non-updatable.api.contribution", + ], + defaults: ["android-non-updatable_from_text_defaults"], + full_api_surface_stub: "android_test_module_lib_stubs_current.from-text", + + // This module is only used for hiddenapi, and other modules should not + // depend on this module. + visibility: ["//visibility:private"], +} + java_defaults { name: "android_stubs_dists_default", dist: { @@ -657,6 +677,7 @@ java_api_library { "api-stubs-docs-non-updatable.api.contribution", ], visibility: ["//visibility:public"], + enable_validation: false, } java_api_library { @@ -672,6 +693,7 @@ java_api_library { "system-api-stubs-docs-non-updatable.api.contribution", ], visibility: ["//visibility:public"], + enable_validation: false, } java_api_library { @@ -689,6 +711,7 @@ java_api_library { "test-api-stubs-docs-non-updatable.api.contribution", ], visibility: ["//visibility:public"], + enable_validation: false, } java_api_library { @@ -704,6 +727,7 @@ java_api_library { "api-stubs-docs-non-updatable.api.contribution", "system-api-stubs-docs-non-updatable.api.contribution", ], + enable_validation: false, } java_api_library { @@ -723,6 +747,7 @@ java_api_library { "module-lib-api-stubs-docs-non-updatable.api.contribution", ], visibility: ["//visibility:public"], + enable_validation: false, } java_api_library { @@ -736,6 +761,32 @@ java_api_library { "stub-annotations", ], visibility: ["//visibility:public"], + enable_validation: false, +} + +java_api_library { + name: "android_test_module_lib_stubs_current.from-text", + api_surface: "module-lib", + defaults: [ + "android_stubs_current_contributions", + "android_system_stubs_current_contributions", + "android_test_stubs_current_contributions", + "android_module_lib_stubs_current_contributions", + ], + libs: [ + "android_module_lib_stubs_current_full.from-text", + "stub-annotations", + ], + api_contributions: [ + "test-api-stubs-docs-non-updatable.api.contribution", + ], + + // This module is only used to build android-non-updatable.stubs.test_module_lib + // and other modules should not depend on this module. + visibility: [ + "//visibility:private", + ], + enable_validation: false, } java_api_library { @@ -752,6 +803,7 @@ java_api_library { "android_module_lib_stubs_current.from-text", ], visibility: ["//visibility:public"], + enable_validation: false, } //////////////////////////////////////////////////////////////////////// diff --git a/core/api/current.txt b/core/api/current.txt index 4304210737ea..e8988dcf3f17 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android { public final class Manifest { @@ -32495,6 +32497,7 @@ package android.os { field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3 field public static final int BATTERY_PROPERTY_CURRENT_NOW = 2; // 0x2 field public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5; // 0x5 + field @FlaggedApi("android.os.state_of_health_public") public static final int BATTERY_PROPERTY_STATE_OF_HEALTH = 10; // 0xa field public static final int BATTERY_PROPERTY_STATUS = 6; // 0x6 field public static final int BATTERY_STATUS_CHARGING = 2; // 0x2 field public static final int BATTERY_STATUS_DISCHARGING = 3; // 0x3 diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 7cfa1e377933..01cf77abd3ed 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android { public static final class Manifest.permission { diff --git a/core/api/module-lib-removed.txt b/core/api/module-lib-removed.txt index d802177e249b..14191ebcb080 100644 --- a/core/api/module-lib-removed.txt +++ b/core/api/module-lib-removed.txt @@ -1 +1,3 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 diff --git a/core/api/removed.txt b/core/api/removed.txt index 8b3696a1e6d9..ede88a29624d 100644 --- a/core/api/removed.txt +++ b/core/api/removed.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android.app { public class Notification implements android.os.Parcelable { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index e9d694bd08df..40eee4c277ac 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android { public static final class Manifest.permission { @@ -10316,7 +10318,6 @@ package android.os { field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_CHARGING_POLICY = 9; // 0x9 field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_FIRST_USAGE_DATE = 8; // 0x8 field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_MANUFACTURING_DATE = 7; // 0x7 - field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_STATE_OF_HEALTH = 10; // 0xa field public static final int CHARGING_POLICY_ADAPTIVE_AC = 3; // 0x3 field public static final int CHARGING_POLICY_ADAPTIVE_AON = 2; // 0x2 field public static final int CHARGING_POLICY_ADAPTIVE_LONGLIFE = 4; // 0x4 @@ -10384,8 +10385,8 @@ package android.os { method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanResults(@NonNull android.os.WorkSource, int); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanStarted(@NonNull android.os.WorkSource, boolean); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanStopped(@NonNull android.os.WorkSource, boolean); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOff(int, int, @NonNull String); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOn(int, int, @NonNull String); + method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOff(int, int, @NonNull String); + method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOn(int, int, @NonNull String); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportMobileRadioPowerState(boolean, int); diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt index 1c10356c6b03..4161330dcb37 100644 --- a/core/api/system-removed.txt +++ b/core/api/system-removed.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android.app { public class AppOpsManager { diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 70377ab6a0d9..8d0e396f110d 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android { public static final class Manifest.permission { diff --git a/core/api/test-removed.txt b/core/api/test-removed.txt index d802177e249b..14191ebcb080 100644 --- a/core/api/test-removed.txt +++ b/core/api/test-removed.txt @@ -1 +1,3 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index b5efb73225d6..0414f792f159 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -50,7 +50,6 @@ import android.os.Trace; import android.os.UserHandle; import android.provider.Settings; import android.security.net.config.NetworkSecurityConfigProvider; -import android.sysprop.VndkProperties; import android.text.TextUtils; import android.util.AndroidRuntimeException; import android.util.ArrayMap; @@ -901,14 +900,10 @@ public final class LoadedApk { } // Similar to vendor apks, we should add /product/lib for apks from product partition - // when product apps are marked as unbundled. We cannot use the same way from vendor - // to check if lib path exists because there is possibility that /product/lib would not - // exist from legacy device while product apks are bundled. To make this clear, we use - // "ro.product.vndk.version" property. If the property is defined, we regard all product - // apks as unbundled. + // when product apps are marked as unbundled. Product is separated as long as the + // partition exists, so it can be handled with same approach from the vendor partition. if (mApplicationInfo.getCodePath() != null - && mApplicationInfo.isProduct() - && VndkProperties.product_vndk_version().isPresent()) { + && mApplicationInfo.isProduct()) { isBundledApp = false; } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index ef26235a3879..f11b1b7ee76d 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -345,6 +345,13 @@ public class PackageInstaller { "android.content.pm.extra.RESOLVED_BASE_PATH"; /** + * A list of warnings that occurred during installation. + * + * @hide + */ + public static final String EXTRA_WARNINGS = "android.content.pm.extra.WARNINGS"; + + /** * Streaming installation pending. * Caller should make sure DataLoader is able to prepare image and reinitiate the operation. * diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig new file mode 100644 index 000000000000..524253371e49 --- /dev/null +++ b/core/java/android/content/pm/flags.aconfig @@ -0,0 +1,8 @@ +package: "android.content.pm" + +flag { + name: "use_art_service_v2" + namespace: "package_manager_service" + description: "Feature flag to enable the features that rely on new ART Service APIs that are in the VIC version of the ART module." + bug: "304741685" +} diff --git a/core/java/android/hardware/biometrics/CryptoObject.java b/core/java/android/hardware/biometrics/CryptoObject.java index 151f819329c9..6ac1efb49839 100644 --- a/core/java/android/hardware/biometrics/CryptoObject.java +++ b/core/java/android/hardware/biometrics/CryptoObject.java @@ -114,8 +114,8 @@ public class CryptoObject { } /** - * Get {@link PresentationSession} object. - * @return {@link PresentationSession} object or null if this doesn't contain one. + * Get {@link KeyAgreement} object. + * @return {@link KeyAgreement} object or null if this doesn't contain one. */ @FlaggedApi(FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT) public KeyAgreement getKeyAgreement() { diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java index 092923e927a3..6a4ec9b7605a 100644 --- a/core/java/android/os/BatteryManager.java +++ b/core/java/android/os/BatteryManager.java @@ -16,7 +16,10 @@ package android.os; +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.SystemApi; import android.annotation.SystemService; @@ -354,17 +357,11 @@ public class BatteryManager { public static final int BATTERY_PROPERTY_CHARGING_POLICY = 9; /** - * - * Percentage representing the measured battery state of health (remaining - * estimated full charge capacity relative to the rated capacity in %). - * - * <p class="note"> - * The sender must hold the {@link android.Manifest.permission#BATTERY_STATS} permission. - * - * @hide + * Percentage representing the measured battery state of health. + * This is the remaining estimated full charge capacity relative + * to the rated capacity in %. */ - @RequiresPermission(permission.BATTERY_STATS) - @SystemApi + @FlaggedApi(FLAG_STATE_OF_HEALTH_PUBLIC) public static final int BATTERY_PROPERTY_STATE_OF_HEALTH = 10; private final Context mContext; diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java index 955fad3d1a48..3abe9a0e38f5 100644 --- a/core/java/android/os/BatteryStatsManager.java +++ b/core/java/android/os/BatteryStatsManager.java @@ -520,8 +520,9 @@ public final class BatteryStatsManager { * @param uid calling package uid * @param reason why Bluetooth has been turned on * @param packageName package responsible for this change - * @Deprecated Bluetooth self report its state and no longer call this + * @deprecated Bluetooth self report its state and no longer call this */ + @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOn(int uid, int reason, @NonNull String packageName) { } @@ -532,8 +533,9 @@ public final class BatteryStatsManager { * @param uid calling package uid * @param reason why Bluetooth has been turned on * @param packageName package responsible for this change - * @Deprecated Bluetooth self report its state and no longer call this + * @deprecated Bluetooth self report its state and no longer call this */ + @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOff(int uid, int reason, @NonNull String packageName) { } diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 94971b8654ee..c9073fa4b72c 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -123,6 +123,7 @@ public class GraphicsEnvironment { private int mAngleOptInIndex = -1; private boolean mEnabledByGameMode = false; + private boolean mShouldUseAngle = false; /** * Set up GraphicsEnvironment @@ -141,19 +142,16 @@ public class GraphicsEnvironment { // Setup ANGLE and pass down ANGLE details to the C++ code Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupAngle"); - boolean useAngle = false; if (setupAngle(context, coreSettings, pm, packageName)) { - if (shouldUseAngle(context, coreSettings, packageName)) { - useAngle = true; - setGpuStats(ANGLE_DRIVER_NAME, ANGLE_DRIVER_VERSION_NAME, ANGLE_DRIVER_VERSION_CODE, - 0, packageName, getVulkanVersion(pm)); - } + mShouldUseAngle = true; + setGpuStats(ANGLE_DRIVER_NAME, ANGLE_DRIVER_VERSION_NAME, ANGLE_DRIVER_VERSION_CODE, + 0, packageName, getVulkanVersion(pm)); } Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "chooseDriver"); if (!chooseDriver(context, coreSettings, pm, packageName, appInfoWithMetaData)) { - if (!useAngle) { + if (!mShouldUseAngle) { setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE, SystemProperties.getLong(PROPERTY_GFX_DRIVER_BUILD_TIME, 0), @@ -636,44 +634,35 @@ public class GraphicsEnvironment { } /** - * Determine if ANGLE will be used and setup the environment - */ - private boolean setupAndUseAngle(Context context, String packageName) { - // Need to make sure we are evaluating ANGLE usage for the correct circumstances - if (!setupAngle(context, null, context.getPackageManager(), packageName)) { - Log.v(TAG, "Package '" + packageName + "' should not use ANGLE"); - return false; - } - - final boolean useAngle = getShouldUseAngle(packageName); - Log.v(TAG, "Package '" + packageName + "' should use ANGLE = '" + useAngle + "'"); - - return useAngle; - } - - /** - * Show the ANGLE in Use Dialog Box + * Show the ANGLE in use dialog box. + * The ANGLE in use dialog box will show up as long as the application + * should use ANGLE. It does not mean the application has successfully + * loaded ANGLE because this check happens before the loading completes. * @param context */ public void showAngleInUseDialogBox(Context context) { - final String packageName = context.getPackageName(); + if (!shouldShowAngleInUseDialogBox(context)) { + return; + } + + if (!mShouldUseAngle) { + return; + } - if (shouldShowAngleInUseDialogBox(context) && setupAndUseAngle(context, packageName)) { - final Intent intent = new Intent(ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE); - String anglePkg = getAnglePackageName(context.getPackageManager()); - intent.setPackage(anglePkg); + final Intent intent = new Intent(ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE); + final String anglePkg = getAnglePackageName(context.getPackageManager()); + intent.setPackage(anglePkg); - context.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Bundle results = getResultExtras(true); + context.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final Bundle results = getResultExtras(true); - String toastMsg = results.getString(INTENT_KEY_A4A_TOAST_MESSAGE); - final Toast toast = Toast.makeText(context, toastMsg, Toast.LENGTH_LONG); - toast.show(); - } - }, null, Activity.RESULT_OK, null, null); - } + final String toastMsg = results.getString(INTENT_KEY_A4A_TOAST_MESSAGE); + final Toast toast = Toast.makeText(context, toastMsg, Toast.LENGTH_LONG); + toast.show(); + } + }, null, Activity.RESULT_OK, null, null); } private String[] getAngleEglFeatures(Context context, Bundle coreSettings) { @@ -901,9 +890,8 @@ public class GraphicsEnvironment { private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries); private static native void setGpuStats(String driverPackageName, String driverVersionName, long driverVersionCode, long driverBuildTime, String appPackageName, int vulkanVersion); - private static native void setAngleInfo(String path, String appPackage, + private static native void setAngleInfo(String path, String packageName, String devOptIn, String[] features); - private static native boolean getShouldUseAngle(String packageName); private static native boolean setInjectLayersPrSetDumpable(); private static native void nativeToggleAngleAsSystemDriver(boolean enabled); diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig index 851aa6dce560..77229c44cc8d 100644 --- a/core/java/android/os/flags.aconfig +++ b/core/java/android/os/flags.aconfig @@ -1,6 +1,13 @@ package: "android.os" flag { + name: "state_of_health_public" + namespace: "system_sw_battery" + description: "Feature flag for making state_of_health a public api." + bug: "288842045" +} + +flag { name: "disallow_cellular_null_ciphers_restriction" namespace: "cellular_security" description: "Guards a new UserManager user restriction that admins can use to require cellular encryption on their managed devices." diff --git a/core/java/com/android/internal/foldables/OWNERS b/core/java/com/android/internal/foldables/OWNERS new file mode 100644 index 000000000000..6ce1ee4d3de2 --- /dev/null +++ b/core/java/com/android/internal/foldables/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/display/OWNERS diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index d90d5f8c5eac..b2131f6fdfad 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -1314,7 +1314,16 @@ void AndroidRuntime::exit(int code) ALOGI("VM exiting with result code %d.", code); onExit(code); } + +#ifdef __ANDROID_CLANG_COVERAGE__ + // When compiled with coverage, a function is registered with atexit to call + // `__llvm_profile_write_file` when the process exit. + // For Clang code coverage to work, call exit instead of _exit to run hooks + // registered with atexit. + ::exit(code); +#else ::_exit(code); +#endif } void AndroidRuntime::onVmCreated(JNIEnv* env) diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index 01dbceb38d3a..d94b9828808b 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -49,10 +49,10 @@ void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName, appPackageNameChars.c_str(), vulkanVersion); } -void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, +void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring packageName, jstring devOptIn, jobjectArray featuresObj) { ScopedUtfChars pathChars(env, path); - ScopedUtfChars appNameChars(env, appName); + ScopedUtfChars packageNameChars(env, packageName); ScopedUtfChars devOptInChars(env, devOptIn); std::vector<std::string> features; @@ -73,15 +73,10 @@ void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appNa } } - android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(), + android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), packageNameChars.c_str(), devOptInChars.c_str(), features); } -bool shouldUseAngle_native(JNIEnv* env, jobject clazz, jstring appName) { - ScopedUtfChars appNameChars(env, appName); - return android::GraphicsEnv::getInstance().shouldUseAngle(appNameChars.c_str()); -} - void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) { android::NativeLoaderNamespace* appNamespace = android::FindNativeLoaderNamespaceByClassLoader( env, classLoader); @@ -126,8 +121,6 @@ const JNINativeMethod g_methods[] = { {"setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V", reinterpret_cast<void*>(setAngleInfo_native)}, - {"getShouldUseAngle", "(Ljava/lang/String;)Z", - reinterpret_cast<void*>(shouldUseAngle_native)}, {"setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native)}, {"setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native)}, diff --git a/graphics/java/android/graphics/drawable/RippleShader.java b/graphics/java/android/graphics/drawable/RippleShader.java index 4461f39fd006..c2a7a84ad809 100644 --- a/graphics/java/android/graphics/drawable/RippleShader.java +++ b/graphics/java/android/graphics/drawable/RippleShader.java @@ -109,9 +109,8 @@ final class RippleShader extends RuntimeShader { + " float alpha = min(fadeIn, 1. - fadeOutNoise);\n" + " vec2 uv = p * in_resolutionScale;\n" + " vec2 densityUv = uv - mod(uv, in_noiseScale);\n" - + " float turbulence = turbulence(uv, in_turbulencePhase);\n" - + " float sparkleAlpha = sparkles(densityUv, in_noisePhase) * ring * alpha " - + "* turbulence;\n" + + " float turb = turbulence(uv, in_turbulencePhase);\n" + + " float sparkleAlpha = sparkles(densityUv, in_noisePhase) * ring * alpha * turb;\n" + " float fade = min(fadeIn, 1. - fadeOutRipple);\n" + " float waveAlpha = softCircle(p, center, in_maxRadius * scaleIn, 1.) * fade " + "* in_color.a;\n" diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java index 31c2eb2efaed..b7ea04fdfe07 100644 --- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java +++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java @@ -128,25 +128,6 @@ public class AndroidKeyStoreMaintenance { } /** - * Queries user state from Keystore 2.0. - * - * @param userId - Android user id of the user. - * @return UserState enum variant as integer if successful or an error - */ - public static int getState(int userId) { - StrictMode.noteDiskRead(); - try { - return getService().getState(userId); - } catch (ServiceSpecificException e) { - Log.e(TAG, "getState 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 off body event was detected. */ public static void onDeviceOffBody() { diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 8045f55f6b4c..11b827117aa3 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -19,8 +19,6 @@ package android.security; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.StrictMode; -import android.os.UserHandle; -import android.security.maintenance.UserState; /** * @hide This should not be made public in its present form because it @@ -37,15 +35,6 @@ public class KeyStore { // Used for UID field to indicate the calling UID. public static final int UID_SELF = -1; - // States - public enum State { - @UnsupportedAppUsage - UNLOCKED, - @UnsupportedAppUsage - LOCKED, - UNINITIALIZED - }; - private static final KeyStore KEY_STORE = new KeyStore(); @UnsupportedAppUsage @@ -55,28 +44,6 @@ public class KeyStore { /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public State state(int userId) { - int userState = AndroidKeyStoreMaintenance.getState(userId); - switch (userState) { - case UserState.UNINITIALIZED: - return KeyStore.State.UNINITIALIZED; - case UserState.LSKF_UNLOCKED: - return KeyStore.State.UNLOCKED; - case UserState.LSKF_LOCKED: - return KeyStore.State.LOCKED; - default: - throw new AssertionError(userState); - } - } - - /** @hide */ - @UnsupportedAppUsage - public State state() { - return state(UserHandle.myUserId()); - } - - /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public byte[] get(String key) { return null; } diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index 96c257b304a0..1ba41b106f56 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -75,16 +75,18 @@ import javax.security.auth.x500.X500Principal; * {@link java.security.interfaces.ECPublicKey} or {@link java.security.interfaces.RSAPublicKey} * interfaces. * - * <p>For asymmetric key pairs, a self-signed X.509 certificate will be also generated and stored in - * the Android Keystore. This is because the {@link java.security.KeyStore} abstraction does not - * support storing key pairs without a certificate. The subject, serial number, and validity dates - * of the certificate can be customized in this spec. The self-signed certificate may be replaced at - * a later time by a certificate signed by a Certificate Authority (CA). + * <p>For asymmetric key pairs, a X.509 certificate will be also generated and stored in the Android + * Keystore. This is because the {@link java.security.KeyStore} abstraction does not support storing + * key pairs without a certificate. The subject, serial number, and validity dates of the + * certificate can be customized in this spec. The certificate may be replaced at a later time by a + * certificate signed by a Certificate Authority (CA). * - * <p>NOTE: If a private key is not authorized to sign the self-signed certificate, then the - * certificate will be created with an invalid signature which will not verify. Such a certificate - * is still useful because it provides access to the public key. To generate a valid signature for - * the certificate the key needs to be authorized for all of the following: + * <p>NOTE: If attestation is not requested using {@link Builder#setAttestationChallenge(byte[])}, + * generated certificate may be self-signed. If a private key is not authorized to sign the + * certificate, then the certificate will be created with an invalid signature which will not + * verify. Such a certificate is still useful because it provides access to the public key. To + * generate a valid signature for the certificate the key needs to be authorized for all of the + * following: * <ul> * <li>{@link KeyProperties#PURPOSE_SIGN},</li> * <li>operation without requiring the user to be authenticated (see @@ -989,12 +991,6 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * @param purposes set of purposes (e.g., encrypt, decrypt, sign) for which the key can be * used. Attempts to use the key for any other purpose will be rejected. * - * <p>If the set of purposes for which the key can be used does not contain - * {@link KeyProperties#PURPOSE_SIGN}, the self-signed certificate generated by - * {@link KeyPairGenerator} of {@code AndroidKeyStore} provider will contain an - * invalid signature. This is OK if the certificate is only used for obtaining the - * public key from Android KeyStore. - * * <p>See {@link KeyProperties}.{@code PURPOSE} flags. */ public Builder(@NonNull String keystoreAlias, @KeyProperties.PurposeEnum int purposes) { @@ -1140,7 +1136,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** - * Sets the subject used for the self-signed certificate of the generated key pair. + * Sets the subject used for the certificate of the generated key pair. * * <p>By default, the subject is {@code CN=fake}. */ @@ -1154,7 +1150,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** - * Sets the serial number used for the self-signed certificate of the generated key pair. + * Sets the serial number used for the certificate of the generated key pair. * * <p>By default, the serial number is {@code 1}. */ @@ -1168,8 +1164,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** - * Sets the start of the validity period for the self-signed certificate of the generated - * key pair. + * Sets the start of the validity period for the certificate of the generated key pair. * * <p>By default, this date is {@code Jan 1 1970}. */ @@ -1183,8 +1178,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu } /** - * Sets the end of the validity period for the self-signed certificate of the generated key - * pair. + * Sets the end of the validity period for the certificate of the generated key pair. * * <p>By default, this date is {@code Jan 1 2048}. */ diff --git a/libs/hwui/api/current.txt b/libs/hwui/api/current.txt index c396a2032eed..794082124344 100644 --- a/libs/hwui/api/current.txt +++ b/libs/hwui/api/current.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android.graphics { public class ColorMatrix { diff --git a/libs/hwui/api/module-lib-current.txt b/libs/hwui/api/module-lib-current.txt index d802177e249b..14191ebcb080 100644 --- a/libs/hwui/api/module-lib-current.txt +++ b/libs/hwui/api/module-lib-current.txt @@ -1 +1,3 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 diff --git a/libs/hwui/api/module-lib-removed.txt b/libs/hwui/api/module-lib-removed.txt index d802177e249b..14191ebcb080 100644 --- a/libs/hwui/api/module-lib-removed.txt +++ b/libs/hwui/api/module-lib-removed.txt @@ -1 +1,3 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 diff --git a/libs/hwui/api/removed.txt b/libs/hwui/api/removed.txt index d802177e249b..14191ebcb080 100644 --- a/libs/hwui/api/removed.txt +++ b/libs/hwui/api/removed.txt @@ -1 +1,3 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 diff --git a/libs/hwui/api/system-current.txt b/libs/hwui/api/system-current.txt index d802177e249b..14191ebcb080 100644 --- a/libs/hwui/api/system-current.txt +++ b/libs/hwui/api/system-current.txt @@ -1 +1,3 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 diff --git a/libs/hwui/api/system-removed.txt b/libs/hwui/api/system-removed.txt index d802177e249b..14191ebcb080 100644 --- a/libs/hwui/api/system-removed.txt +++ b/libs/hwui/api/system-removed.txt @@ -1 +1,3 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index a311296dd90c..b002bbf20c08 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -1282,11 +1282,8 @@ public final class AudioFormat implements Parcelable { * {@link AudioFormat#CHANNEL_OUT_BACK_CENTER}, * {@link AudioFormat#CHANNEL_OUT_SIDE_LEFT}, * {@link AudioFormat#CHANNEL_OUT_SIDE_RIGHT}. - * <p> For a valid {@link AudioTrack} channel position mask, - * the following conditions apply: - * <br> (1) at most {@link AudioSystem#OUT_CHANNEL_COUNT_MAX} channel positions may be - * used; - * <br> (2) right/left pairs should be matched. + * <p> For output or {@link AudioTrack}, channel position masks which do not contain + * matched left/right pairs are invalid. * <p> For input or {@link AudioRecord}, the mask should be * {@link AudioFormat#CHANNEL_IN_MONO} or * {@link AudioFormat#CHANNEL_IN_STEREO}. {@link AudioFormat#CHANNEL_IN_MONO} is diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index ab2a22bd8857..0dea2c859fcd 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1485,8 +1485,7 @@ public class AudioManager { * Returns the volume group id associated to the given {@link AudioAttributes}. * * @param attributes The {@link AudioAttributes} to consider. - * @return {@link android.media.audiopolicy.AudioVolumeGroup} id supporting the given - * {@link AudioAttributes} if found, + * @return audio volume group id supporting the given {@link AudioAttributes} if found, * {@code android.media.audiopolicy.AudioVolumeGroup.DEFAULT_VOLUME_GROUP} otherwise. */ public int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) { @@ -1601,7 +1600,7 @@ public class AudioManager { * <p> Call first in prior {@link #getVolumeGroupIdForAttributes(AudioAttributes)} to retrieve * the volume group id supporting the given {@link AudioAttributes}. * - * @param groupId of the {@link android.media.audiopolicy.AudioVolumeGroup} to consider. + * @param groupId of the audio volume group to consider. * @param direction The direction to adjust the volume. One of * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or * {@link #ADJUST_SAME}. @@ -1645,8 +1644,8 @@ public class AudioManager { * <p> Call first in prior {@link #getVolumeGroupIdForAttributes(AudioAttributes)} to retrieve * the volume group id supporting the given {@link AudioAttributes}. * - * @param groupId of the {@link android.media.audiopolicy.AudioVolumeGroup} to consider. - * @return The mute state for the given {@link android.media.audiopolicy.AudioVolumeGroup} id. + * @param groupId of the audio volume group to consider. + * @return The mute state for the given audio volume group id. * @see #adjustVolumeGroupVolume(int, int, int) */ public boolean isVolumeGroupMuted(int groupId) { diff --git a/media/java/android/media/projection/OWNERS b/media/java/android/media/projection/OWNERS index cc9be9c5126a..880ec8fdef88 100644 --- a/media/java/android/media/projection/OWNERS +++ b/media/java/android/media/projection/OWNERS @@ -4,3 +4,4 @@ michaelwr@google.com santoscordon@google.com chaviw@google.com nmusgrave@google.com +dakinola@google.com diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp index c616b84fa6fb..1c25080939da 100644 --- a/media/jni/android_media_MediaDrm.cpp +++ b/media/jni/android_media_MediaDrm.cpp @@ -38,6 +38,8 @@ #include <mediadrm/IDrmMetricsConsumer.h> #include <mediadrm/IDrm.h> #include <utils/Vector.h> +#include <map> +#include <string> using ::android::os::PersistableBundle; namespace drm = ::android::hardware::drm; @@ -193,6 +195,11 @@ struct LogMessageFields { jclass classId; }; +struct DrmExceptionFields { + jmethodID init; + jclass classId; +}; + struct fields_t { jfieldID context; jmethodID post_event; @@ -215,6 +222,7 @@ struct fields_t { jclass parcelCreatorClassId; KeyStatusFields keyStatus; LogMessageFields logMessage; + std::map<std::string, DrmExceptionFields> exceptionCtors; }; static fields_t gFields; @@ -245,18 +253,32 @@ jobject hidlLogMessagesToJavaList(JNIEnv *env, const Vector<drm::V1_4::LogMessag return arrayList; } -int drmThrowException(JNIEnv* env, const char *className, const DrmStatus &err, const char *msg) { +void resolveDrmExceptionCtor(JNIEnv *env, const char *className) { + jclass clazz; + jmethodID init; + FIND_CLASS(clazz, className); + GET_METHOD_ID(init, clazz, "<init>", "(Ljava/lang/String;III)V"); + gFields.exceptionCtors[std::string(className)] = { + .init = init, + .classId = static_cast<jclass>(env->NewGlobalRef(clazz)) + }; +} + +void drmThrowException(JNIEnv* env, const char *className, const DrmStatus &err, const char *msg) { using namespace android::jnihelp; - jstring _detailMessage = CreateExceptionMsg(env, msg); - int _status = ThrowException(env, className, "(Ljava/lang/String;III)V", - _detailMessage, - err.getCdmErr(), - err.getOemErr(), - err.getContext()); - if (_detailMessage != NULL) { - env->DeleteLocalRef(_detailMessage); + + if (gFields.exceptionCtors.count(std::string(className)) == 0) { + jniThrowException(env, className, msg); + } else { + jstring _detailMessage = CreateExceptionMsg(env, msg); + jobject exception = env->NewObject(gFields.exceptionCtors[std::string(className)].classId, + gFields.exceptionCtors[std::string(className)].init, _detailMessage, + err.getCdmErr(), err.getOemErr(), err.getContext()); + env->Throw(static_cast<jthrowable>(exception)); + if (_detailMessage != NULL) { + env->DeleteLocalRef(_detailMessage); + } } - return _status; } } // namespace anonymous @@ -952,6 +974,10 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) { FIND_CLASS(clazz, "android/media/MediaDrm$LogMessage"); gFields.logMessage.classId = static_cast<jclass>(env->NewGlobalRef(clazz)); GET_METHOD_ID(gFields.logMessage.init, clazz, "<init>", "(JILjava/lang/String;)V"); + + resolveDrmExceptionCtor(env, "android/media/NotProvisionedException"); + resolveDrmExceptionCtor(env, "android/media/ResourceBusyException"); + resolveDrmExceptionCtor(env, "android/media/DeniedByServerException"); } static void android_media_MediaDrm_native_setup( @@ -2192,4 +2218,4 @@ static const JNINativeMethod gMethods[] = { int register_android_media_Drm(JNIEnv *env) { return AndroidRuntime::registerNativeMethods(env, "android/media/MediaDrm", gMethods, NELEM(gMethods)); -} +}
\ No newline at end of file diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml index e88655894156..7d79a6c266e4 100644 --- a/media/tests/MediaFrameworkTest/AndroidManifest.xml +++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml @@ -20,6 +20,7 @@ <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> diff --git a/media/tests/MediaFrameworkTest/AndroidTest.xml b/media/tests/MediaFrameworkTest/AndroidTest.xml index 132028ce98dc..91c92cc13d1b 100644 --- a/media/tests/MediaFrameworkTest/AndroidTest.xml +++ b/media/tests/MediaFrameworkTest/AndroidTest.xml @@ -23,5 +23,6 @@ <option name="package" value="com.android.mediaframeworktest" /> <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> <option name="hidden-api-checks" value="false"/> + <option name="isolated-storage" value="false"/> </test> </configuration> diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java index 9be7004c5701..30edfa40802b 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java @@ -44,7 +44,6 @@ public class MediaFrameworkUnitTestRunner extends InstrumentationTestRunner { @Override public TestSuite getAllTests() { TestSuite suite = new InstrumentationTestSuite(this); - addMediaMetadataRetrieverStateUnitTests(suite); addMediaRecorderStateUnitTests(suite); addMediaPlayerStateUnitTests(suite); addMediaScannerUnitTests(suite); @@ -70,11 +69,6 @@ public class MediaFrameworkUnitTestRunner extends InstrumentationTestRunner { } // Running all unit tests checking the state machine may be time-consuming. - private void addMediaMetadataRetrieverStateUnitTests(TestSuite suite) { - suite.addTestSuite(MediaMetadataRetrieverTest.class); - } - - // Running all unit tests checking the state machine may be time-consuming. private void addMediaRecorderStateUnitTests(TestSuite suite) { suite.addTestSuite(MediaRecorderPrepareStateUnitTest.class); suite.addTestSuite(MediaRecorderResetStateUnitTest.class); 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 bdca4744ff74..f70d2d1f8ae7 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java @@ -16,26 +16,34 @@ package com.android.mediaframeworktest.unit; +import static org.junit.Assert.assertTrue; + import android.graphics.Bitmap; import android.media.MediaMetadataRetriever; -import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.util.Log; +import androidx.test.runner.AndroidJUnit4; + import com.android.mediaframeworktest.MediaNames; import com.android.mediaframeworktest.MediaProfileReader; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.io.FileOutputStream; import java.io.IOException; -public class MediaMetadataRetrieverTest extends AndroidTestCase { +@RunWith(AndroidJUnit4.class) +public class MediaMetadataRetrieverTest { private static final String TAG = "MediaMetadataRetrieverTest"; // Test album art extraction. @MediumTest - public static void testGetEmbeddedPicture() throws Exception { + @Test + public void testGetEmbeddedPicture() throws Exception { Log.v(TAG, "testGetEmbeddedPicture starts."); MediaMetadataRetriever retriever = new MediaMetadataRetriever(); boolean supportWMA = MediaProfileReader.getWMAEnable(); @@ -78,7 +86,8 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // Test frame capture @LargeTest - public static void testThumbnailCapture() throws Exception { + @Test + public void testThumbnailCapture() throws Exception { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); boolean supportWMA = MediaProfileReader.getWMAEnable(); boolean supportWMV = MediaProfileReader.getWMVEnable(); @@ -134,7 +143,8 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { } @LargeTest - public static void testMetadataRetrieval() throws Exception { + @Test + public void testMetadataRetrieval() throws Exception { boolean supportWMA = MediaProfileReader.getWMAEnable(); boolean supportWMV = MediaProfileReader.getWMVEnable(); boolean hasFailed = false; @@ -169,7 +179,8 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // If the specified call order and valid media file is used, no exception // should be thrown. @MediumTest - public static void testBasicNormalMethodCallSequence() throws Exception { + @Test + public void testBasicNormalMethodCallSequence() throws Exception { boolean hasFailed = false; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { @@ -197,7 +208,8 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // If setDataSource() has not been called, both getFrameAtTime() and extractMetadata() must // return null. @MediumTest - public static void testBasicAbnormalMethodCallSequence() { + @Test + public void testBasicAbnormalMethodCallSequence() { boolean hasFailed = false; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); if (retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) != null) { @@ -213,7 +225,8 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // Test setDataSource() @MediumTest - public static void testSetDataSource() throws IOException { + @Test + public void testSetDataSource() throws IOException { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); boolean hasFailed = false; diff --git a/omapi/aidl/Android.bp b/omapi/aidl/Android.bp index 58bcd1d49c69..e71597a27a39 100644 --- a/omapi/aidl/Android.bp +++ b/omapi/aidl/Android.bp @@ -24,6 +24,11 @@ aidl_interface { backend: { java: { sdk_version: "module_current", + apex_available: [ + "//apex_available:platform", + "com.android.nfcservices", + ], + }, rust: { enabled: true, diff --git a/packages/SettingsProvider/OWNERS b/packages/SettingsProvider/OWNERS index 5ade9716c8cb..86ae5818e91c 100644 --- a/packages/SettingsProvider/OWNERS +++ b/packages/SettingsProvider/OWNERS @@ -1,5 +1 @@ -hackbod@android.com -hackbod@google.com -narayan@google.com -svetoslavganov@google.com include /PACKAGE_MANAGER_OWNERS diff --git a/ravenwood/OWNERS b/ravenwood/OWNERS new file mode 100644 index 000000000000..c06b3b9c2d11 --- /dev/null +++ b/ravenwood/OWNERS @@ -0,0 +1,3 @@ +jsharkey@google.com +omakoto@google.com +jaggies@google.com diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index d94f4f22f2c9..5b496f4766b3 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -16,6 +16,7 @@ package com.android.server; +import static android.os.Flags.stateOfHealthPublic; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent; import static com.android.server.health.Utils.copyV1Battery; @@ -27,7 +28,6 @@ import android.app.BroadcastOptions; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.database.ContentObserver; import android.hardware.health.HealthInfo; import android.hardware.health.V2_1.BatteryCapacityLevel; @@ -1316,10 +1316,14 @@ public final class BatteryService extends SystemService { @Override public int getProperty(int id, final BatteryProperty prop) throws RemoteException { switch (id) { + case BatteryManager.BATTERY_PROPERTY_STATE_OF_HEALTH: + if (stateOfHealthPublic()) { + break; + } + case BatteryManager.BATTERY_PROPERTY_MANUFACTURING_DATE: case BatteryManager.BATTERY_PROPERTY_FIRST_USAGE_DATE: case BatteryManager.BATTERY_PROPERTY_CHARGING_POLICY: - case BatteryManager.BATTERY_PROPERTY_STATE_OF_HEALTH: mContext.enforceCallingPermission( android.Manifest.permission.BATTERY_STATS, null); break; diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index f4f5c951faaa..d256aead97e8 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -580,7 +580,6 @@ public class PackageWatchdog { PackageHealthObserverImpact.USER_IMPACT_LEVEL_10, PackageHealthObserverImpact.USER_IMPACT_LEVEL_30, PackageHealthObserverImpact.USER_IMPACT_LEVEL_50, - PackageHealthObserverImpact.USER_IMPACT_LEVEL_60, PackageHealthObserverImpact.USER_IMPACT_LEVEL_70, PackageHealthObserverImpact.USER_IMPACT_LEVEL_100}) public @interface PackageHealthObserverImpact { @@ -591,7 +590,6 @@ public class PackageWatchdog { /* Actions having medium user impact, user of a device will likely notice. */ int USER_IMPACT_LEVEL_30 = 30; int USER_IMPACT_LEVEL_50 = 50; - int USER_IMPACT_LEVEL_60 = 60; int USER_IMPACT_LEVEL_70 = 70; /* Action has high user impact, a last resort, user of a device will be very frustrated. */ int USER_IMPACT_LEVEL_100 = 100; diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index f532122c10d9..8da94737f3cb 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -1241,11 +1241,10 @@ class ProcessRecord implements WindowProcessListener { killProcessGroup = true; } if (killProcessGroup) { - if (async) { - ProcessList.killProcessGroup(uid, mPid); - } else { + if (!async) { Process.sendSignalToProcessGroup(uid, mPid, OsConstants.SIGKILL); } + ProcessList.killProcessGroup(uid, mPid); } } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java index 2fa637e030f1..18f84c03d04f 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java @@ -45,7 +45,7 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; -import com.android.server.PersistentDataBlockManagerInternal; +import com.android.server.pdb.PersistentDataBlockManagerInternal; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; diff --git a/services/core/java/com/android/server/oemlock/OemLockService.java b/services/core/java/com/android/server/oemlock/OemLockService.java index 4c6110b99efd..d00268899a07 100644 --- a/services/core/java/com/android/server/oemlock/OemLockService.java +++ b/services/core/java/com/android/server/oemlock/OemLockService.java @@ -35,8 +35,8 @@ import android.service.oemlock.IOemLockService; import android.util.Slog; import com.android.server.LocalServices; -import com.android.server.PersistentDataBlockManagerInternal; import com.android.server.SystemService; +import com.android.server.pdb.PersistentDataBlockManagerInternal; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerInternal.UserRestrictionsListener; import com.android.server.pm.UserRestrictionsUtils; diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java index 7b0eddc505f4..e5616d04554d 100644 --- a/services/core/java/com/android/server/os/NativeTombstoneManager.java +++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java @@ -567,6 +567,10 @@ public final class NativeTombstoneManager { @Override public void onEvent(int event, @Nullable String path) { + if (path == null) { + Slog.w(TAG, "path is null at TombstoneWatcher.onEvent()"); + return; + } mHandler.post(() -> { // Ignore .tmp files. if (path.endsWith(".tmp")) { diff --git a/services/core/java/com/android/server/pdb/OWNERS b/services/core/java/com/android/server/pdb/OWNERS new file mode 100644 index 000000000000..6f322eea0f2e --- /dev/null +++ b/services/core/java/com/android/server/pdb/OWNERS @@ -0,0 +1,2 @@ +victorhsieh@google.com +swillden@google.com diff --git a/services/core/java/com/android/server/PersistentDataBlockManagerInternal.java b/services/core/java/com/android/server/pdb/PersistentDataBlockManagerInternal.java index 21fa9f9a9401..66ad7169d6ec 100644 --- a/services/core/java/com/android/server/PersistentDataBlockManagerInternal.java +++ b/services/core/java/com/android/server/pdb/PersistentDataBlockManagerInternal.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.pdb; /** * Internal interface for storing and retrieving persistent data. diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java index 6fd6afed49b9..870ca788eb3f 100644 --- a/services/core/java/com/android/server/PersistentDataBlockService.java +++ b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.pdb; import static com.android.internal.util.Preconditions.checkArgument; @@ -37,6 +37,9 @@ import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.DumpUtils; import com.android.server.pm.UserManagerInternal; +import com.android.server.LocalServices; +import com.android.server.SystemServerInitThreadPool; +import com.android.server.SystemService; import libcore.io.IoUtils; diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java index 6fc14e814525..046dcc2dce7c 100644 --- a/services/core/java/com/android/server/pm/InstallRequest.java +++ b/services/core/java/com/android/server/pm/InstallRequest.java @@ -22,6 +22,8 @@ import static android.content.pm.PackageManager.INSTALL_SCENARIO_DEFAULT; import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; import static android.os.Process.INVALID_UID; +import static com.android.server.art.model.DexoptResult.DexContainerFileDexoptResult; +import static com.android.server.art.model.DexoptResult.PackageDexoptResult; import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP; import static com.android.server.pm.PackageManagerService.TAG; @@ -30,6 +32,7 @@ import android.annotation.Nullable; import android.apex.ApexInfo; import android.app.AppOpsManager; import android.content.pm.DataLoaderType; +import android.content.pm.Flags; import android.content.pm.IPackageInstallObserver2; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; @@ -52,6 +55,7 @@ import com.android.server.pm.pkg.parsing.ParsingPackageUtils; import java.io.File; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; final class InstallRequest { @@ -130,6 +134,9 @@ final class InstallRequest { private int mDexoptStatus; + @NonNull + private ArrayList<String> mWarnings = new ArrayList<>(); + // New install InstallRequest(InstallingSession params) { mUserId = params.getUser().getIdentifier(); @@ -615,6 +622,11 @@ final class InstallRequest { return mDexoptStatus; } + @NonNull + public ArrayList<String> getWarnings() { + return mWarnings; + } + public void setScanFlags(int scanFlags) { mScanFlags = scanFlags; } @@ -757,6 +769,10 @@ final class InstallRequest { } } + public void addWarning(@NonNull String warning) { + mWarnings.add(warning); + } + public void onPrepareStarted() { if (mPackageMetrics != null) { mPackageMetrics.onStepStarted(PackageMetrics.STEP_PREPARE); @@ -806,22 +822,37 @@ final class InstallRequest { } public void onDexoptFinished(DexoptResult dexoptResult) { - if (mPackageMetrics == null) { - return; - } - mDexoptStatus = dexoptResult.getFinalStatus(); - if (mDexoptStatus != DexoptResult.DEXOPT_PERFORMED) { - return; + // Only report external profile warnings when installing from adb. The goal is to warn app + // developers if they have provided bad external profiles, so it's not beneficial to report + // those warnings in the normal app install workflow. + if (isInstallFromAdb() && Flags.useArtServiceV2()) { + var externalProfileErrors = new LinkedHashSet<String>(); + for (PackageDexoptResult packageResult : dexoptResult.getPackageDexoptResults()) { + for (DexContainerFileDexoptResult fileResult : + packageResult.getDexContainerFileDexoptResults()) { + externalProfileErrors.addAll(fileResult.getExternalProfileErrors()); + } + } + if (!externalProfileErrors.isEmpty()) { + addWarning("Error occurred during dexopt when processing external profiles:\n " + + String.join("\n ", externalProfileErrors)); + } } - long durationMillis = 0; - for (DexoptResult.PackageDexoptResult packageResult : - dexoptResult.getPackageDexoptResults()) { - for (DexoptResult.DexContainerFileDexoptResult fileResult : - packageResult.getDexContainerFileDexoptResults()) { - durationMillis += fileResult.getDex2oatWallTimeMillis(); + + // Report dexopt metrics. + if (mPackageMetrics != null) { + mDexoptStatus = dexoptResult.getFinalStatus(); + if (mDexoptStatus == DexoptResult.DEXOPT_PERFORMED) { + long durationMillis = 0; + for (PackageDexoptResult packageResult : dexoptResult.getPackageDexoptResults()) { + for (DexContainerFileDexoptResult fileResult : + packageResult.getDexContainerFileDexoptResults()) { + durationMillis += fileResult.getDex2oatWallTimeMillis(); + } + } + mPackageMetrics.onStepFinished(PackageMetrics.STEP_DEXOPT, durationMillis); } } - mPackageMetrics.onStepFinished(PackageMetrics.STEP_DEXOPT, durationMillis); } public void onInstallCompleted() { diff --git a/services/core/java/com/android/server/pm/MovePackageHelper.java b/services/core/java/com/android/server/pm/MovePackageHelper.java index 481bd975fef5..fef53d15c09d 100644 --- a/services/core/java/com/android/server/pm/MovePackageHelper.java +++ b/services/core/java/com/android/server/pm/MovePackageHelper.java @@ -89,6 +89,21 @@ public final class MovePackageHelper { if (packageState == null || packageState.getPkg() == null) { throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package"); } + final int[] installedUserIds = PackageStateUtils.queryInstalledUsers(packageState, + mPm.mUserManager.getUserIds(), true); + final UserHandle userForMove; + if (installedUserIds.length > 0) { + userForMove = UserHandle.of(installedUserIds[0]); + } else { + throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, + "Package is not installed for any user"); + } + for (int userId : installedUserIds) { + if (snapshot.shouldFilterApplicationIncludingUninstalled(packageState, callingUid, + userId)) { + throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package"); + } + } final AndroidPackage pkg = packageState.getPkg(); if (packageState.isSystem()) { throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE, @@ -137,8 +152,6 @@ public final class MovePackageHelper { final String label = String.valueOf(pm.getApplicationLabel( AndroidPackageUtils.generateAppInfoWithoutState(pkg))); final int targetSdkVersion = pkg.getTargetSdkVersion(); - final int[] installedUserIds = PackageStateUtils.queryInstalledUsers(packageState, - mPm.mUserManager.getUserIds(), true); final String fromCodePath; if (codeFile.getParentFile().getName().startsWith( PackageManagerService.RANDOM_DIR_PREFIX)) { @@ -305,8 +318,8 @@ public final class MovePackageHelper { final PackageLite lite = ret.isSuccess() ? ret.getResult() : null; final InstallingSession installingSession = new InstallingSession(origin, move, installObserver, installFlags, /* developmentInstallFlags= */ 0, installSource, - volumeUuid, user, packageAbiOverride, PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED, - lite, mPm); + volumeUuid, userForMove, packageAbiOverride, + PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED, lite, mPm); installingSession.movePackage(); } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index f0e38955f050..3e72fe4f95b4 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -2714,15 +2714,40 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * @return a future that will be completed when the whole process is completed. */ private CompletableFuture<Void> install() { + // `futures` either contains only one session (`this`) or contains one parent session + // (`this`) and n-1 child sessions. List<CompletableFuture<InstallResult>> futures = installNonStaged(); CompletableFuture<InstallResult>[] arr = new CompletableFuture[futures.size()]; return CompletableFuture.allOf(futures.toArray(arr)).whenComplete((r, t) -> { if (t == null) { setSessionApplied(); + var multiPackageWarnings = new ArrayList<String>(); + if (isMultiPackage()) { + // This is a parent session. Collect warnings from children. + for (CompletableFuture<InstallResult> f : futures) { + InstallResult result = f.join(); + if (result.session != this && result.extras != null) { + ArrayList<String> childWarnings = result.extras.getStringArrayList( + PackageInstaller.EXTRA_WARNINGS); + if (!ArrayUtils.isEmpty(childWarnings)) { + multiPackageWarnings.addAll(childWarnings); + } + } + } + } for (CompletableFuture<InstallResult> f : futures) { InstallResult result = f.join(); + Bundle extras = result.extras; + if (isMultiPackage() && result.session == this + && !multiPackageWarnings.isEmpty()) { + if (extras == null) { + extras = new Bundle(); + } + extras.putStringArrayList( + PackageInstaller.EXTRA_WARNINGS, multiPackageWarnings); + } result.session.dispatchSessionFinished( - INSTALL_SUCCEEDED, "Session installed", result.extras); + INSTALL_SUCCEEDED, "Session installed", extras); } } else { PackageManagerException e = (PackageManagerException) t.getCause(); @@ -4904,6 +4929,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { if (!TextUtils.isEmpty(existing)) { fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing); } + ArrayList<String> warnings = extras.getStringArrayList(PackageInstaller.EXTRA_WARNINGS); + if (!ArrayUtils.isEmpty(warnings)) { + fillIn.putStringArrayListExtra(PackageInstaller.EXTRA_WARNINGS, warnings); + } } try { final BroadcastOptions options = BroadcastOptions.makeBasic(); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index f2b62eaf25f8..20bd56d56945 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1415,6 +1415,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService break; } } + if (!request.getWarnings().isEmpty()) { + extras.putStringArrayList(PackageInstaller.EXTRA_WARNINGS, request.getWarnings()); + } return extras; } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 2a7ebfb75dde..2327b85ed0bb 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -3982,10 +3982,21 @@ class PackageManagerShellCommand extends ShellCommand { session.commit(receiver.getIntentSender()); if (!session.isStaged()) { final Intent result = receiver.getResult(); - final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, - PackageInstaller.STATUS_FAILURE); + int status = result.getIntExtra( + PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE); + List<String> warnings = + result.getStringArrayListExtra(PackageInstaller.EXTRA_WARNINGS); if (status == PackageInstaller.STATUS_SUCCESS) { - if (logSuccess) { + if (!ArrayUtils.isEmpty(warnings)) { + // Don't start the output string with "Success" because that will make adb + // treat this as a success. + for (String warning : warnings) { + pw.println("Warning: " + warning); + } + // Treat warnings as failure to draw app developers' attention. + status = PackageInstaller.STATUS_FAILURE; + pw.println("Completed with warning(s)"); + } else if (logSuccess) { pw.println("Success"); } } else { diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java index 80d6ebbd90b3..85e11d66737a 100644 --- a/services/core/java/com/android/server/pm/PackageMetrics.java +++ b/services/core/java/com/android/server/pm/PackageMetrics.java @@ -34,8 +34,11 @@ import java.io.File; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Stream; @@ -155,10 +158,27 @@ final class PackageMetrics { private long getApksSize(File apkDir) { // TODO(b/249294752): also count apk sizes for failed installs final AtomicLong apksSize = new AtomicLong(); - try (Stream<Path> walkStream = Files.walk(apkDir.toPath())) { - walkStream.filter(p -> p.toFile().isFile() - && ApkLiteParseUtils.isApkFile(p.toFile())).forEach( - f -> apksSize.addAndGet(f.toFile().length())); + try { + Files.walkFileTree(apkDir.toPath(), new SimpleFileVisitor<>() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) + throws IOException { + if (dir.equals(apkDir.toPath())) { + return FileVisitResult.CONTINUE; + } else { + return FileVisitResult.SKIP_SUBTREE; + } + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + if (file.toFile().isFile() && ApkLiteParseUtils.isApkFile(file.toFile())) { + apksSize.addAndGet(file.toFile().length()); + } + return FileVisitResult.CONTINUE; + } + }); } catch (IOException e) { // ignore } diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java index 0ca560398657..2007079ea5ca 100644 --- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java @@ -121,7 +121,7 @@ final class RollbackPackageHealthObserver implements PackageHealthObserver { impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30; } else if (getAvailableRollback(failedPackage) != null) { // Rollback is available, we may get a callback into #execute - impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_60; + impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30; } else if (anyRollbackAvailable) { // If any rollbacks are available, we will commit them impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_70; diff --git a/services/core/java/com/android/server/stats/OWNERS b/services/core/java/com/android/server/stats/OWNERS index 174ad3ad2e25..c33f3d9fa264 100644 --- a/services/core/java/com/android/server/stats/OWNERS +++ b/services/core/java/com/android/server/stats/OWNERS @@ -1,11 +1,10 @@ jeffreyhuang@google.com joeo@google.com -jtnguyen@google.com +monicamwang@google.com muhammadq@google.com +rayhdez@google.com rslawik@google.com -ruchirr@google.com sharaienko@google.com singhtejinder@google.com tsaichristine@google.com yaochen@google.com -yro@google.com diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java index bfe34049e1e5..9a9b83602832 100644 --- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java +++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java @@ -41,8 +41,8 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; -import com.android.server.PersistentDataBlockManagerInternal; import com.android.server.SystemService; +import com.android.server.pdb.PersistentDataBlockManagerInternal; import com.android.server.pm.UserManagerInternal; import java.io.ByteArrayInputStream; diff --git a/services/core/java/com/android/server/vibrator/OWNERS b/services/core/java/com/android/server/vibrator/OWNERS index 08f0a90485cc..da5a476e9eb8 100644 --- a/services/core/java/com/android/server/vibrator/OWNERS +++ b/services/core/java/com/android/server/vibrator/OWNERS @@ -1,3 +1,5 @@ +# Bug component: 345036 +khalilahmad@google.com lsandrade@google.com michaelwr@google.com -sbowden@google.com
\ No newline at end of file +roosa@google.com diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index f6fa51e3018a..18a6254ca115 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -8225,7 +8225,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private void clearSizeCompatModeAttributes() { mInSizeCompatModeForBounds = false; + final float lastSizeCompatScale = mSizeCompatScale; mSizeCompatScale = 1f; + if (mSizeCompatScale != lastSizeCompatScale) { + forAllWindows(WindowState::updateGlobalScale, false /* traverseTopToBottom */); + } mSizeCompatBounds = null; mCompatDisplayInsets = null; mLetterboxUiController.clearInheritedCompatDisplayInsets(); @@ -8233,11 +8237,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @VisibleForTesting void clearSizeCompatMode() { - final float lastSizeCompatScale = mSizeCompatScale; clearSizeCompatModeAttributes(); - if (mSizeCompatScale != lastSizeCompatScale) { - forAllWindows(WindowState::updateGlobalScale, false /* traverseTopToBottom */); - } // Clear config override in #updateCompatDisplayInsets(). final int activityType = getActivityType(); final Configuration overrideConfig = getRequestedOverrideConfiguration(); diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS index 26abe51c8c34..f6c364008c62 100644 --- a/services/core/java/com/android/server/wm/OWNERS +++ b/services/core/java/com/android/server/wm/OWNERS @@ -18,4 +18,4 @@ rgl@google.com yunfanc@google.com per-file BackgroundActivityStartController.java = set noparent -per-file BackgroundActivityStartController.java = brufino@google.com, ogunwale@google.com, louischang@google.com, lus@google.com +per-file BackgroundActivityStartController.java = brufino@google.com, topjohnwu@google.com, achim@google.com, ogunwale@google.com, louischang@google.com, lus@google.com diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 10687001f9a8..d4a88c7dd6d7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -5206,7 +5206,11 @@ public class WindowManagerService extends IWindowManager.Stub public void displayReady() { synchronized (mGlobalLock) { if (mMaxUiWidth > 0) { - mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth)); + mRoot.forAllDisplays(dc -> { + if (dc.mDisplay.getType() == Display.TYPE_INTERNAL) { + dc.setMaxUiWidth(mMaxUiWidth); + } + }); } applyForcedPropertiesForDefaultDisplay(); mAnimator.ready(); diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 6f2455e073a7..62864485c0e2 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -68,7 +68,7 @@ cc_library_static { "com_android_server_UsbHostManager.cpp", "com_android_server_vibrator_VibratorController.cpp", "com_android_server_vibrator_VibratorManagerService.cpp", - "com_android_server_PersistentDataBlockService.cpp", + "com_android_server_pdb_PersistentDataBlockService.cpp", "com_android_server_am_LowMemDetector.cpp", "com_android_server_pm_PackageManagerShellCommandDataLoader.cpp", "com_android_server_sensor_SensorService.cpp", diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS index d9acf4182736..bc294902f0fc 100644 --- a/services/core/jni/OWNERS +++ b/services/core/jni/OWNERS @@ -20,6 +20,7 @@ per-file com_android_server_lights_* = file:/services/core/java/com/android/serv per-file com_android_server_location_* = file:/location/java/android/location/OWNERS per-file com_android_server_locksettings_* = file:/services/core/java/com/android/server/locksettings/OWNERS per-file com_android_server_net_* = file:/services/core/java/com/android/server/net/OWNERS +per-file com_android_server_pdb_* = file:/services/core/java/com/android/server/pdb/OWNERS per-file com_android_server_pm_* = file:/services/core/java/com/android/server/pm/OWNERS per-file com_android_server_power_* = file:/services/core/java/com/android/server/power/OWNERS per-file com_android_server_powerstats_* = file:/services/core/java/com/android/server/powerstats/OWNERS diff --git a/services/core/jni/com_android_server_PersistentDataBlockService.cpp b/services/core/jni/com_android_server_pdb_PersistentDataBlockService.cpp index 97e69fb4bb40..fc5a11360c8c 100644 --- a/services/core/jni/com_android_server_PersistentDataBlockService.cpp +++ b/services/core/jni/com_android_server_pdb_PersistentDataBlockService.cpp @@ -76,7 +76,7 @@ namespace android { return ret; } - static jlong com_android_server_PersistentDataBlockService_getBlockDeviceSize(JNIEnv *env, jclass, jstring jpath) + static jlong com_android_server_pdb_PersistentDataBlockService_getBlockDeviceSize(JNIEnv *env, jclass, jstring jpath) { ScopedUtfChars path(env, jpath); int fd = open(path.c_str(), O_RDONLY); @@ -91,7 +91,7 @@ namespace android { return size; } - static int com_android_server_PersistentDataBlockService_wipe(JNIEnv *env, jclass, jstring jpath) { + static int com_android_server_pdb_PersistentDataBlockService_wipe(JNIEnv *env, jclass, jstring jpath) { ScopedUtfChars path(env, jpath); int fd = open(path.c_str(), O_WRONLY); @@ -107,13 +107,13 @@ namespace android { static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ - {"nativeGetBlockDeviceSize", "(Ljava/lang/String;)J", (void*)com_android_server_PersistentDataBlockService_getBlockDeviceSize}, - {"nativeWipe", "(Ljava/lang/String;)I", (void*)com_android_server_PersistentDataBlockService_wipe}, + {"nativeGetBlockDeviceSize", "(Ljava/lang/String;)J", (void*)com_android_server_pdb_PersistentDataBlockService_getBlockDeviceSize}, + {"nativeWipe", "(Ljava/lang/String;)I", (void*)com_android_server_pdb_PersistentDataBlockService_wipe}, }; - int register_android_server_PersistentDataBlockService(JNIEnv* env) + int register_android_server_pdb_PersistentDataBlockService(JNIEnv* env) { - return jniRegisterNativeMethods(env, "com/android/server/PersistentDataBlockService", + return jniRegisterNativeMethods(env, "com/android/server/pdb/PersistentDataBlockService", sMethods, NELEM(sMethods)); } diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 290ad8de9547..4078606afb0f 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -46,7 +46,7 @@ int register_android_server_connectivity_Vpn(JNIEnv* env); int register_android_server_devicepolicy_CryptoTestHelper(JNIEnv*); int register_android_server_tv_TvUinputBridge(JNIEnv* env); int register_android_server_tv_TvInputHal(JNIEnv* env); -int register_android_server_PersistentDataBlockService(JNIEnv* env); +int register_android_server_pdb_PersistentDataBlockService(JNIEnv* env); int register_android_server_Watchdog(JNIEnv* env); int register_android_server_HardwarePropertiesManagerService(JNIEnv* env); int register_android_server_SyntheticPasswordManager(JNIEnv* env); @@ -104,7 +104,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_BatteryStatsService(env); register_android_server_tv_TvUinputBridge(env); register_android_server_tv_TvInputHal(env); - register_android_server_PersistentDataBlockService(env); + register_android_server_pdb_PersistentDataBlockService(env); register_android_server_HardwarePropertiesManagerService(env); register_android_server_storage_AppFuse(env); register_android_server_SyntheticPasswordManager(env); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index ab218a671823..c1cc73bb9d10 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -485,13 +485,13 @@ import com.android.server.AlarmManagerInternal; import com.android.server.LocalManagerRegistry; import com.android.server.LocalServices; import com.android.server.LockGuard; -import com.android.server.PersistentDataBlockManagerInternal; import com.android.server.SystemServerInitThreadPool; import com.android.server.SystemService; import com.android.server.SystemServiceManager; import com.android.server.devicepolicy.ActiveAdmin.TrustAgentInfo; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.net.NetworkPolicyManagerInternal; +import com.android.server.pdb.PersistentDataBlockManagerInternal; import com.android.server.pm.DefaultCrossProfileIntentFilter; import com.android.server.pm.DefaultCrossProfileIntentFiltersUtils; import com.android.server.pm.PackageManagerLocal; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 1792964fe3af..3610542c7caf 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -158,6 +158,7 @@ import com.android.server.os.BugreportManagerService; import com.android.server.os.DeviceIdentifiersPolicyService; import com.android.server.os.NativeTombstoneManagerService; import com.android.server.os.SchedulingPolicyService; +import com.android.server.pdb.PersistentDataBlockService; import com.android.server.people.PeopleService; import com.android.server.permission.access.AccessCheckingService; import com.android.server.pm.ApexManager; diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java index 35d4ffdd94d0..a14073006c31 100644 --- a/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java @@ -145,7 +145,7 @@ public class RollbackPackageHealthObserverTest { observer.onHealthCheckFailed(null, PackageWatchdog.FAILURE_REASON_NATIVE_CRASH, 1)); // non-native crash for the package - assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_60, + assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_30, observer.onHealthCheckFailed(testFailedPackage, PackageWatchdog.FAILURE_REASON_APP_CRASH, 1)); // non-native crash for a different package diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java index 9b32a809d2b5..de3cfbf859ff 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java @@ -54,8 +54,8 @@ import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockSettingsInternal; import com.android.server.AlarmManagerInternal; import com.android.server.LocalServices; -import com.android.server.PersistentDataBlockManagerInternal; import com.android.server.net.NetworkPolicyManagerInternal; +import com.android.server.pdb.PersistentDataBlockManagerInternal; import com.android.server.pm.PackageManagerLocal; import com.android.server.pm.UserManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java index 16fdfb16444a..76aa40c04e3d 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java @@ -77,7 +77,7 @@ import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockSettingsInternal; import com.android.server.AlarmManagerInternal; -import com.android.server.PersistentDataBlockManagerInternal; +import com.android.server.pdb.PersistentDataBlockManagerInternal; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.pm.PackageManagerLocal; import com.android.server.pm.UserManagerInternal; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java index 36dc6c5f9f95..cfb3b3497745 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java @@ -22,7 +22,7 @@ import static org.mockito.Mockito.mock; import android.content.Context; -import com.android.server.PersistentDataBlockManagerInternal; +import com.android.server.pdb.PersistentDataBlockManagerInternal; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java index 10ed882f343f..39e2792a3a34 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java @@ -53,8 +53,8 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; -import com.android.server.PersistentDataBlockManagerInternal; import com.android.server.locksettings.LockSettingsStorage.PersistentData; +import com.android.server.pdb.PersistentDataBlockManagerInternal; import org.junit.After; import org.junit.Before; diff --git a/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java b/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java new file mode 100644 index 000000000000..949f8e7a6ab0 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java @@ -0,0 +1,335 @@ +/* + * 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.net; + +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import android.app.Notification; +import android.app.NotificationManager; +import android.content.Context; +import android.content.ContextWrapper; +import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkInfo; +import android.os.Handler; +import android.os.HandlerThread; +import android.text.TextUtils; + +import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import com.android.internal.R; +import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; +import com.android.internal.net.VpnConfig; +import com.android.internal.net.VpnProfile; +import com.android.server.connectivity.Vpn; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class LockdownVpnTrackerTest { + private static final NetworkCapabilities TEST_CELL_NC = new NetworkCapabilities.Builder() + .addTransportType(TRANSPORT_CELLULAR) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) + .build(); + private static final LinkProperties TEST_CELL_LP = new LinkProperties(); + + static { + TEST_CELL_LP.setInterfaceName("rmnet0"); + TEST_CELL_LP.addLinkAddress(new LinkAddress("192.0.2.2/25")); + } + + // Use a context wrapper instead of a mock since LockdownVpnTracker builds notifications which + // is tedious and currently unnecessary to mock. + private final Context mContext = new ContextWrapper(InstrumentationRegistry.getContext()) { + @Override + public Object getSystemService(String name) { + if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; + if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager; + + return super.getSystemService(name); + } + }; + @Mock private ConnectivityManager mCm; + @Mock private Vpn mVpn; + @Mock private NotificationManager mNotificationManager; + @Mock private NetworkInfo mVpnNetworkInfo; + @Mock private VpnConfig mVpnConfig; + @Mock private Network mNetwork; + @Mock private Network mNetwork2; + @Mock private Network mVpnNetwork; + + private HandlerThread mHandlerThread; + private Handler mHandler; + private VpnProfile mProfile; + + private VpnProfile createTestVpnProfile() { + final String profileName = "testVpnProfile"; + final VpnProfile profile = new VpnProfile(profileName); + profile.name = "My VPN"; + profile.server = "192.0.2.1"; + profile.dnsServers = "8.8.8.8"; + profile.ipsecIdentifier = "My ipsecIdentifier"; + profile.ipsecSecret = "My PSK"; + profile.type = VpnProfile.TYPE_IKEV2_IPSEC_PSK; + + return profile; + } + + private NetworkCallback getDefaultNetworkCallback() { + final ArgumentCaptor<NetworkCallback> callbackCaptor = + ArgumentCaptor.forClass(NetworkCallback.class); + verify(mCm).registerSystemDefaultNetworkCallback(callbackCaptor.capture(), eq(mHandler)); + return callbackCaptor.getValue(); + } + + private NetworkCallback getVpnNetworkCallback() { + final ArgumentCaptor<NetworkCallback> callbackCaptor = + ArgumentCaptor.forClass(NetworkCallback.class); + verify(mCm).registerNetworkCallback(any(), callbackCaptor.capture(), eq(mHandler)); + return callbackCaptor.getValue(); + } + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mHandlerThread = new HandlerThread("LockdownVpnTrackerTest"); + mHandlerThread.start(); + mHandler = mHandlerThread.getThreadHandler(); + + doReturn(mVpnNetworkInfo).when(mVpn).getNetworkInfo(); + doReturn(false).when(mVpnNetworkInfo).isConnectedOrConnecting(); + doReturn(mVpnConfig).when(mVpn).getLegacyVpnConfig(); + // mVpnConfig is a mock but the production code will try to add addresses in this array + // assuming it's non-null, so it needs to be initialized. + mVpnConfig.addresses = new ArrayList<>(); + + mProfile = createTestVpnProfile(); + } + + @After + public void tearDown() throws Exception { + if (mHandlerThread != null) { + mHandlerThread.quitSafely(); + mHandlerThread.join(); + } + } + + private LockdownVpnTracker initAndVerifyLockdownVpnTracker() { + final LockdownVpnTracker lockdownVpnTracker = + new LockdownVpnTracker(mContext, mHandler, mVpn, mProfile); + lockdownVpnTracker.init(); + verify(mVpn).setEnableTeardown(false); + verify(mVpn).setLockdown(true); + verify(mCm).setLegacyLockdownVpnEnabled(true); + verify(mVpn).stopVpnRunnerPrivileged(); + verify(mNotificationManager).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS)); + + return lockdownVpnTracker; + } + + private void callCallbacksForNetworkConnect(NetworkCallback callback, Network network, + NetworkCapabilities nc, LinkProperties lp, boolean blocked) { + callback.onAvailable(network); + callback.onCapabilitiesChanged(network, nc); + callback.onLinkPropertiesChanged(network, lp); + callback.onBlockedStatusChanged(network, blocked); + } + + private void callCallbacksForNetworkConnect(NetworkCallback callback, Network network) { + callCallbacksForNetworkConnect( + callback, network, TEST_CELL_NC, TEST_CELL_LP, true /* blocked */); + } + + private boolean isExpectedNotification(Notification notification, int titleRes, int iconRes) { + if (!NOTIFICATION_CHANNEL_VPN.equals(notification.getChannelId())) { + return false; + } + final CharSequence expectedTitle = mContext.getString(titleRes); + final CharSequence actualTitle = notification.extras.getCharSequence( + Notification.EXTRA_TITLE); + if (!TextUtils.equals(expectedTitle, actualTitle)) { + return false; + } + return notification.getSmallIcon().getResId() == iconRes; + } + + @Test + public void testShutdown() { + final LockdownVpnTracker lockdownVpnTracker = initAndVerifyLockdownVpnTracker(); + final NetworkCallback defaultCallback = getDefaultNetworkCallback(); + final NetworkCallback vpnCallback = getVpnNetworkCallback(); + clearInvocations(mVpn, mCm, mNotificationManager); + + lockdownVpnTracker.shutdown(); + verify(mVpn).stopVpnRunnerPrivileged(); + verify(mVpn).setLockdown(false); + verify(mCm).setLegacyLockdownVpnEnabled(false); + verify(mNotificationManager).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS)); + verify(mVpn).setEnableTeardown(true); + verify(mCm).unregisterNetworkCallback(defaultCallback); + verify(mCm).unregisterNetworkCallback(vpnCallback); + } + + @Test + public void testDefaultNetworkConnected() { + initAndVerifyLockdownVpnTracker(); + final NetworkCallback defaultCallback = getDefaultNetworkCallback(); + clearInvocations(mVpn, mCm, mNotificationManager); + + // mNetwork connected and available. + callCallbacksForNetworkConnect(defaultCallback, mNetwork); + + // Vpn is starting + verify(mVpn).startLegacyVpnPrivileged(mProfile, mNetwork, TEST_CELL_LP); + verify(mNotificationManager).notify(any(), eq(SystemMessage.NOTE_VPN_STATUS), + argThat(notification -> isExpectedNotification(notification, + R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected))); + } + + private void doTestDefaultLpChanged(LinkProperties startingLp, LinkProperties newLp) { + initAndVerifyLockdownVpnTracker(); + final NetworkCallback defaultCallback = getDefaultNetworkCallback(); + callCallbacksForNetworkConnect( + defaultCallback, mNetwork, TEST_CELL_NC, startingLp, true /* blocked */); + clearInvocations(mVpn, mCm, mNotificationManager); + + // LockdownVpnTracker#handleStateChangedLocked() is not called on the same network even if + // the LinkProperties change. + defaultCallback.onLinkPropertiesChanged(mNetwork, newLp); + + // Ideally the VPN should start if it hasn't already, but it doesn't because nothing calls + // LockdownVpnTracker#handleStateChangedLocked. This is a bug. + // TODO: consider fixing this. + verify(mVpn, never()).stopVpnRunnerPrivileged(); + verify(mVpn, never()).startLegacyVpnPrivileged(any(), any(), any()); + verify(mNotificationManager, never()).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS)); + } + + @Test + public void testDefaultLPChanged_V4AddLinkAddressV4() { + final LinkProperties lp = new LinkProperties(TEST_CELL_LP); + lp.setInterfaceName("rmnet0"); + lp.addLinkAddress(new LinkAddress("192.0.2.3/25")); + doTestDefaultLpChanged(TEST_CELL_LP, lp); + } + + @Test + public void testDefaultLPChanged_V4AddLinkAddressV6() { + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName("rmnet0"); + lp.addLinkAddress(new LinkAddress("192.0.2.3/25")); + final LinkProperties newLp = new LinkProperties(lp); + newLp.addLinkAddress(new LinkAddress("2001:db8::1/64")); + doTestDefaultLpChanged(lp, newLp); + } + + @Test + public void testDefaultLPChanged_V6AddLinkAddressV4() { + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName("rmnet0"); + lp.addLinkAddress(new LinkAddress("2001:db8::1/64")); + final LinkProperties newLp = new LinkProperties(lp); + newLp.addLinkAddress(new LinkAddress("192.0.2.3/25")); + doTestDefaultLpChanged(lp, newLp); + } + + @Test + public void testDefaultLPChanged_AddLinkAddressV4() { + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName("rmnet0"); + doTestDefaultLpChanged(lp, TEST_CELL_LP); + } + + @Test + public void testDefaultNetworkChanged() { + initAndVerifyLockdownVpnTracker(); + final NetworkCallback defaultCallback = getDefaultNetworkCallback(); + final NetworkCallback vpnCallback = getVpnNetworkCallback(); + callCallbacksForNetworkConnect(defaultCallback, mNetwork); + clearInvocations(mVpn, mCm, mNotificationManager); + + // New network and LinkProperties received + final NetworkCapabilities wifiNc = new NetworkCapabilities.Builder() + .addTransportType(TRANSPORT_WIFI) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) + .build(); + final LinkProperties wifiLp = new LinkProperties(); + wifiLp.setInterfaceName("wlan0"); + callCallbacksForNetworkConnect( + defaultCallback, mNetwork2, wifiNc, wifiLp, true /* blocked */); + + // Vpn is restarted. + verify(mVpn).stopVpnRunnerPrivileged(); + verify(mVpn).startLegacyVpnPrivileged(mProfile, mNetwork2, wifiLp); + verify(mNotificationManager, never()).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS)); + verify(mNotificationManager).notify(any(), eq(SystemMessage.NOTE_VPN_STATUS), + argThat(notification -> isExpectedNotification(notification, + R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected))); + + // Vpn is Connected + doReturn(true).when(mVpnNetworkInfo).isConnectedOrConnecting(); + doReturn(true).when(mVpnNetworkInfo).isConnected(); + vpnCallback.onAvailable(mVpnNetwork); + verify(mNotificationManager).notify(any(), eq(SystemMessage.NOTE_VPN_STATUS), + argThat(notification -> isExpectedNotification(notification, + R.string.vpn_lockdown_connected, R.drawable.vpn_connected))); + + } + + @Test + public void testSystemDefaultLost() { + initAndVerifyLockdownVpnTracker(); + final NetworkCallback defaultCallback = getDefaultNetworkCallback(); + // mNetwork connected + callCallbacksForNetworkConnect(defaultCallback, mNetwork); + clearInvocations(mVpn, mCm, mNotificationManager); + + defaultCallback.onLost(mNetwork); + + // Vpn is stopped + verify(mVpn).stopVpnRunnerPrivileged(); + verify(mNotificationManager).cancel(any(), eq(SystemMessage.NOTE_VPN_STATUS)); + } +} diff --git a/services/tests/servicestests/src/com/android/server/pdb/OWNERS b/services/tests/servicestests/src/com/android/server/pdb/OWNERS new file mode 100644 index 000000000000..6dfb888dedad --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pdb/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/pdb/OWNERS diff --git a/telephony/java/android/telephony/BarringInfo.java b/telephony/java/android/telephony/BarringInfo.java index 29152f19d17d..7b6a201796a6 100644 --- a/telephony/java/android/telephony/BarringInfo.java +++ b/telephony/java/android/telephony/BarringInfo.java @@ -202,6 +202,24 @@ public final class BarringInfo implements Parcelable { && mConditionalBarringTimeSeconds == other.mConditionalBarringTimeSeconds; } + private static String barringTypeToString(@BarringType int barringType) { + return switch (barringType) { + case BARRING_TYPE_NONE -> "NONE"; + case BARRING_TYPE_CONDITIONAL -> "CONDITIONAL"; + case BARRING_TYPE_UNCONDITIONAL -> "UNCONDITIONAL"; + case BARRING_TYPE_UNKNOWN -> "UNKNOWN"; + default -> "UNKNOWN(" + barringType + ")"; + }; + } + + @Override + public String toString() { + return "BarringServiceInfo {mBarringType=" + barringTypeToString(mBarringType) + + ", mIsConditionallyBarred=" + mIsConditionallyBarred + + ", mConditionalBarringFactor=" + mConditionalBarringFactor + + ", mConditionalBarringTimeSeconds=" + mConditionalBarringTimeSeconds + "}"; + } + /** @hide */ public BarringServiceInfo(Parcel p) { mBarringType = p.readInt(); diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt index d1a68d4e9cb2..241e69106718 100644 --- a/test-mock/api/current.txt +++ b/test-mock/api/current.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android.test.mock { @Deprecated public class MockAccountManager { diff --git a/test-mock/api/removed.txt b/test-mock/api/removed.txt index 1496c356da08..fa2fbd276e9a 100644 --- a/test-mock/api/removed.txt +++ b/test-mock/api/removed.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android.test.mock { public class MockContext extends android.content.Context { diff --git a/test-mock/api/system-current.txt b/test-mock/api/system-current.txt index 9e022f0cb0ef..2b5132ecd14f 100644 --- a/test-mock/api/system-current.txt +++ b/test-mock/api/system-current.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android.test.mock { public class MockContext extends android.content.Context { diff --git a/test-mock/api/system-removed.txt b/test-mock/api/system-removed.txt index d802177e249b..14191ebcb080 100644 --- a/test-mock/api/system-removed.txt +++ b/test-mock/api/system-removed.txt @@ -1 +1,3 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt index 35f076fe3f00..1752edcd469e 100644 --- a/test-mock/api/test-current.txt +++ b/test-mock/api/test-current.txt @@ -1,4 +1,6 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 package android.test.mock { public class MockContext extends android.content.Context { diff --git a/test-mock/api/test-removed.txt b/test-mock/api/test-removed.txt index d802177e249b..14191ebcb080 100644 --- a/test-mock/api/test-removed.txt +++ b/test-mock/api/test-removed.txt @@ -1 +1,3 @@ // Signature format: 2.0 +// - add-additional-overrides=no +// - migrating=Migration in progress see b/299366704 diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp index 87da09a7b054..8c644cf83339 100644 --- a/tools/aapt2/java/AnnotationProcessor.cpp +++ b/tools/aapt2/java/AnnotationProcessor.cpp @@ -49,16 +49,19 @@ struct AnnotationRule { kDeprecated = 0x01, kSystemApi = 0x02, kTestApi = 0x04, + kFlaggedApi = 0x08, }; StringPiece doc_str; uint32_t bit_mask; StringPiece annotation; + bool preserve_params; }; -static std::array<AnnotationRule, 2> sAnnotationRules = {{ - {"@SystemApi", AnnotationRule::kSystemApi, "@android.annotation.SystemApi"}, - {"@TestApi", AnnotationRule::kTestApi, "@android.annotation.TestApi"}, +static std::array<AnnotationRule, 3> sAnnotationRules = {{ + {"@SystemApi", AnnotationRule::kSystemApi, "@android.annotation.SystemApi", true}, + {"@TestApi", AnnotationRule::kTestApi, "@android.annotation.TestApi", false}, + {"@FlaggedApi", AnnotationRule::kFlaggedApi, "@android.annotation.FlaggedApi", true}, }}; void AnnotationProcessor::AppendCommentLine(std::string comment) { @@ -73,12 +76,11 @@ void AnnotationProcessor::AppendCommentLine(std::string comment) { std::string::size_type idx = comment.find(rule.doc_str.data()); if (idx != std::string::npos) { // Captures all parameters associated with the specified annotation rule - // by matching the first pair of parantheses after the rule. - std::regex re(std::string(rule.doc_str) += "\\s*\\((.+)\\)"); + // by matching the first pair of parentheses after the rule. + std::regex re(std::string(rule.doc_str).append(R"(\s*\((.+)\))")); std::smatch match_result; const bool is_match = std::regex_search(comment, match_result, re); - // We currently only capture and preserve parameters for SystemApi. - if (is_match && rule.bit_mask == AnnotationRule::kSystemApi) { + if (is_match && rule.preserve_params) { annotation_parameter_map_[rule.bit_mask] = match_result[1].str(); comment.erase(comment.begin() + match_result.position(), comment.begin() + match_result.position() + match_result.length()); diff --git a/tools/aapt2/java/AnnotationProcessor_test.cpp b/tools/aapt2/java/AnnotationProcessor_test.cpp index 6bc8902a6dcf..e98e96ba3bc3 100644 --- a/tools/aapt2/java/AnnotationProcessor_test.cpp +++ b/tools/aapt2/java/AnnotationProcessor_test.cpp @@ -76,6 +76,36 @@ TEST(AnnotationProcessorTest, EmitsSystemApiAnnotationParamsAndRemovesFromCommen EXPECT_THAT(annotations, HasSubstr("This is a system API")); } +TEST(AnnotationProcessorTest, EmitsFlaggedApiAnnotationAndRemovesFromComment) { + AnnotationProcessor processor; + processor.AppendComment("@FlaggedApi This is a flagged API"); + + std::string annotations; + StringOutputStream out(&annotations); + Printer printer(&out); + processor.Print(&printer); + out.Flush(); + + EXPECT_THAT(annotations, HasSubstr("@android.annotation.FlaggedApi")); + EXPECT_THAT(annotations, Not(HasSubstr("@FlaggedApi"))); + EXPECT_THAT(annotations, HasSubstr("This is a flagged API")); +} + +TEST(AnnotationProcessorTest, EmitsFlaggedApiAnnotationParamsAndRemovesFromComment) { + AnnotationProcessor processor; + processor.AppendComment("@FlaggedApi (\"android.flags.my_flag\") This is a flagged API"); + + std::string annotations; + StringOutputStream out(&annotations); + Printer printer(&out); + processor.Print(&printer); + out.Flush(); + + EXPECT_THAT(annotations, HasSubstr("@android.annotation.FlaggedApi(\"android.flags.my_flag\")")); + EXPECT_THAT(annotations, Not(HasSubstr("@FlaggedApi"))); + EXPECT_THAT(annotations, HasSubstr("This is a flagged API")); +} + TEST(AnnotationProcessorTest, EmitsTestApiAnnotationAndRemovesFromComment) { AnnotationProcessor processor; processor.AppendComment("@TestApi This is a test API"); diff --git a/tools/lint/global/integration_tests/Android.bp b/tools/lint/global/integration_tests/Android.bp index ca96559ac016..40281d263a4c 100644 --- a/tools/lint/global/integration_tests/Android.bp +++ b/tools/lint/global/integration_tests/Android.bp @@ -12,25 +12,58 @@ // See the License for the specific language governing permissions and // limitations under the License. -java_library { - name: "AndroidGlobalLintTestNoAidl", - srcs: ["TestNoAidl/**/*.java"], +// Integration tests for @EnforcePermission linters. +// Each test defines its own java_library. The XML lint report from this +// java_library is wrapped under a Python library with a unique pkg_path (this +// is to avoid a name conflict for the report file). All the tests are +// referenced and executed by AndroidGlobalLintCheckerIntegrationTest. + +java_defaults { + name: "AndroidGlobalLintIntegrationTestDefault", libs: [ "framework-annotations-lib", ], lint: { - // It is expected that lint returns an error when processing this + // It is expected that lint returns an error when processing the // library. Silence it here, the lint output is verified in tests.py. suppress_exit_code: true, }, } +java_library { + name: "AndroidGlobalLintTestNoAidl", + srcs: ["TestNoAidl/**/*.java"], + defaults: ["AndroidGlobalLintIntegrationTestDefault"], +} + +python_library_host { + name: "AndroidGlobalLintTestNoAidl_py", + data: [":AndroidGlobalLintTestNoAidl{.lint}"], + pkg_path: "no_aidl", +} + +java_library { + name: "AndroidGlobalLintTestMissingAnnotation", + srcs: [ + "TestMissingAnnotation/**/*.java", + "TestMissingAnnotation/**/*.aidl", + ], + defaults: ["AndroidGlobalLintIntegrationTestDefault"], +} + +python_library_host { + name: "AndroidGlobalLintTestMissingAnnotation_py", + data: [":AndroidGlobalLintTestMissingAnnotation{.lint}"], + pkg_path: "missing_annotation", +} + python_test_host { name: "AndroidGlobalLintCheckerIntegrationTest", srcs: ["tests.py"], main: "tests.py", - data: [ - ":AndroidGlobalLintTestNoAidl{.lint}", + libs: [ + "AndroidGlobalLintTestNoAidl_py", + "AndroidGlobalLintTestMissingAnnotation_py", ], version: { py3: { diff --git a/tools/lint/global/integration_tests/TestMissingAnnotation/TestMissingAnnotation.java b/tools/lint/global/integration_tests/TestMissingAnnotation/TestMissingAnnotation.java new file mode 100644 index 000000000000..9e4854c61f96 --- /dev/null +++ b/tools/lint/global/integration_tests/TestMissingAnnotation/TestMissingAnnotation.java @@ -0,0 +1,28 @@ +/* + * 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.integration_tests; + +/** + * A class that implements an AIDL interface, but is missing the @EnforcePermission annotation. + */ +class TestMissingAnnotation extends IFoo.Stub { + + @Override + public void Method() { + } + +} diff --git a/tools/lint/global/integration_tests/TestMissingAnnotation/com/google/android/lint/integration_tests/IFoo.aidl b/tools/lint/global/integration_tests/TestMissingAnnotation/com/google/android/lint/integration_tests/IFoo.aidl new file mode 100644 index 000000000000..95ec2c230599 --- /dev/null +++ b/tools/lint/global/integration_tests/TestMissingAnnotation/com/google/android/lint/integration_tests/IFoo.aidl @@ -0,0 +1,7 @@ +package com.google.android.lint.integration_tests; + +interface IFoo { + + @EnforcePermission("INTERNET") + void Method(); +} diff --git a/tools/lint/global/integration_tests/tests.py b/tools/lint/global/integration_tests/tests.py index fc3eeb4f8ed9..cdb16b8ba25f 100644 --- a/tools/lint/global/integration_tests/tests.py +++ b/tools/lint/global/integration_tests/tests.py @@ -19,16 +19,28 @@ import xml.etree.ElementTree class TestLinterReports(unittest.TestCase): """Integration tests for the linters used by @EnforcePermission.""" - def test_no_aidl(self): - report = pkgutil.get_data("lint", "lint-report.xml").decode() + def _read_report(self, pkg_path): + report = pkgutil.get_data(pkg_path, "lint/lint-report.xml").decode() issues = xml.etree.ElementTree.fromstring(report) self.assertEqual(issues.tag, "issues") + return issues + + def test_no_aidl(self): + issues = self._read_report("no_aidl") self.assertEqual(len(issues), 1) issue = issues[0] self.assertEqual(issue.attrib["id"], "MisusingEnforcePermissionAnnotation") self.assertEqual(issue.attrib["severity"], "Error") + def test_missing_annotation(self): + issues = self._read_report("missing_annotation") + self.assertEqual(len(issues), 1) + + issue = issues[0] + self.assertEqual(issue.attrib["id"], "MissingEnforcePermissionAnnotation") + self.assertEqual(issue.attrib["severity"], "Error") + if __name__ == '__main__': unittest.main(verbosity=2) |