diff options
113 files changed, 1600 insertions, 542 deletions
diff --git a/Android.bp b/Android.bp index 1aa297faa7e8..f5c0b6d416b8 100644 --- a/Android.bp +++ b/Android.bp @@ -136,6 +136,9 @@ filegroup { // For the generated R.java and Manifest.java ":framework-res{.aapt.srcjar}", + // Java/AIDL sources to be moved out to CrashRecovery module + ":framework-crashrecovery-sources", + // etc. ":framework-javastream-protos", ":statslog-framework-java-gen", // FrameworkStatsLog.java @@ -410,13 +413,25 @@ java_defaults { ], } +// Collection of non updatable unbundled jars. The list here should match +// |non_updatable_modules| variable in frameworks/base/api/api.go. +java_library { + name: "framework-non-updatable-unbundled-impl-libs", + static_libs: [ + "framework-location.impl", + "framework-nfc.impl", + ], + sdk_version: "core_platform", + installable: false, +} + // Separated so framework-minus-apex-defaults can be used without the libs dependency java_defaults { name: "framework-minus-apex-with-libs-defaults", defaults: ["framework-minus-apex-defaults"], libs: [ "framework-virtualization.stubs.module_lib", - "framework-location.impl", + "framework-non-updatable-unbundled-impl-libs", ], } @@ -447,7 +462,7 @@ java_library { stem: "framework", apex_available: ["//apex_available:platform"], visibility: [ - "//frameworks/base/location", + "//frameworks/base:__subpackages__", ], compile_dex: false, headers_only: true, @@ -510,8 +525,8 @@ java_library { installable: false, // this lib is a build-only library static_libs: [ "app-compat-annotations", - "framework-location.impl", "framework-minus-apex", + "framework-non-updatable-unbundled-impl-libs", "framework-updatable-stubs-module_libs_api", ], sdk_version: "core_platform", diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp index 9366ff2d81a9..e1b3241e051e 100644 --- a/apct-tests/perftests/core/Android.bp +++ b/apct-tests/perftests/core/Android.bp @@ -66,6 +66,7 @@ android_test { errorprone: { javacflags: [ "-Xep:ReturnValueIgnored:WARN", + "-Xep:UnnecessaryStringBuilder:OFF", ], }, } diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java index 4d646de2e529..10764651cdfb 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java @@ -21,7 +21,7 @@ import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; import static android.app.AlarmManager.RTC; import static android.app.AlarmManager.RTC_WAKEUP; -import static com.android.server.alarm.AlarmManagerService.clampPositive; +import static com.android.server.alarm.AlarmManagerService.addClampPositive; import android.app.AlarmManager; import android.app.IAlarmListener; @@ -146,7 +146,7 @@ class Alarm { mPolicyWhenElapsed[REQUESTER_POLICY_INDEX] = requestedWhenElapsed; mWhenElapsed = requestedWhenElapsed; this.windowLength = windowLength; - mMaxWhenElapsed = clampPositive(requestedWhenElapsed + windowLength); + mMaxWhenElapsed = addClampPositive(requestedWhenElapsed, windowLength); repeatInterval = interval; operation = op; listener = rec; @@ -241,8 +241,8 @@ class Alarm { final long oldMaxWhenElapsed = mMaxWhenElapsed; // windowLength should always be >= 0 here. - final long maxRequestedElapsed = clampPositive( - mPolicyWhenElapsed[REQUESTER_POLICY_INDEX] + windowLength); + final long maxRequestedElapsed = addClampPositive( + mPolicyWhenElapsed[REQUESTER_POLICY_INDEX], windowLength); mMaxWhenElapsed = Math.max(maxRequestedElapsed, mWhenElapsed); return (oldWhenElapsed != mWhenElapsed) || (oldMaxWhenElapsed != mMaxWhenElapsed); diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index b96354c396a7..8cc31342ddda 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -1498,15 +1498,15 @@ public class AlarmManagerService extends SystemService { if (futurity < MIN_FUZZABLE_INTERVAL) { futurity = 0; } - long maxElapsed = triggerAtTime + (long) (0.75 * futurity); + long maxElapsed = addClampPositive(triggerAtTime, (long) (0.75 * futurity)); // For non-repeating alarms, window is capped at a maximum of one hour from the requested // delivery time. This allows for inexact-while-idle alarms to be slightly more reliable. // In practice, the delivery window should generally be much smaller than that // when the device is not idling. if (interval == 0) { - maxElapsed = Math.min(maxElapsed, triggerAtTime + INTERVAL_HOUR); + maxElapsed = Math.min(maxElapsed, addClampPositive(triggerAtTime, INTERVAL_HOUR)); } - return clampPositive(maxElapsed); + return maxElapsed; } // The RTC clock has moved arbitrarily, so we need to recalculate all the RTC alarm deliveries. @@ -1593,6 +1593,18 @@ public class AlarmManagerService extends SystemService { return (val >= 0) ? val : Long.MAX_VALUE; } + static long addClampPositive(long val1, long val2) { + long val = val1 + val2; + if (val >= 0) { + return val; + } else if (val1 >= 0 && val2 >= 0) { + /* Both are +ve, so overflow happened. */ + return Long.MAX_VALUE; + } else { + return 0; + } + } + /** * Sends alarms that were blocked due to user applied background restrictions - either because * the user lifted those or the uid came to foreground. diff --git a/api/Android.bp b/api/Android.bp index a89e1f268e58..68babc3660d9 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -89,6 +89,7 @@ combined_apis { "framework-location", "framework-media", "framework-mediaprovider", + "framework-nfc", "framework-ondevicepersonalization", "framework-pdf", "framework-permission", @@ -398,7 +399,10 @@ java_defaults { stub_only_libs: ["framework-protos"], impl_only_libs: ["framework-minus-apex-headers"], // the framework, including hidden API impl_library_visibility: ["//frameworks/base"], - defaults_visibility: ["//frameworks/base/location"], + defaults_visibility: [ + "//frameworks/base/location", + "//frameworks/base/nfc", + ], plugins: ["error_prone_android_framework"], errorprone: { javacflags: [ @@ -414,3 +418,49 @@ build = [ "ApiDocs.bp", "StubLibraries.bp", ] + +genrule_defaults { + name: "flag-api-mapping-generation-defaults", + cmd: "$(location extract-flagged-apis) $(in) $(out)", + tools: ["extract-flagged-apis"], +} + +genrule { + name: "flag-api-mapping-PublicApi", + defaults: ["flag-api-mapping-generation-defaults"], + srcs: [":frameworks-base-api-current.txt"], + out: ["flag_api_map.textproto"], + dist: { + targets: ["droid"], + }, +} + +genrule { + name: "flag-api-mapping-SystemApi", + defaults: ["flag-api-mapping-generation-defaults"], + srcs: [":frameworks-base-api-system-current.txt"], + out: ["system_flag_api_map.textproto"], + dist: { + targets: ["droid"], + }, +} + +genrule { + name: "flag-api-mapping-ModuleLibApi", + defaults: ["flag-api-mapping-generation-defaults"], + srcs: [":frameworks-base-api-module-lib-current.txt"], + out: ["module_lib_flag_api_map.textproto"], + dist: { + targets: ["droid"], + }, +} + +genrule { + name: "flag-api-mapping-SystemServerApi", + defaults: ["flag-api-mapping-generation-defaults"], + srcs: [":frameworks-base-api-system-server-current.txt"], + out: ["system_server_flag_api_map.textproto"], + dist: { + targets: ["droid"], + }, +} diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index f6f69291ce0e..28b2d4b5e3ee 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -635,6 +635,7 @@ java_defaults { api_contributions: [ "framework-virtualization.stubs.source.test.api.contribution", "framework-location.stubs.source.test.api.contribution", + "framework-nfc.stubs.source.test.api.contribution", ], } diff --git a/api/api.go b/api/api.go index 8df6dab715ef..71b1e10d2f47 100644 --- a/api/api.go +++ b/api/api.go @@ -32,6 +32,7 @@ const conscrypt = "conscrypt.module.public.api" const i18n = "i18n.module.public.api" const virtualization = "framework-virtualization" const location = "framework-location" +const nfc = "framework-nfc" var core_libraries_modules = []string{art, conscrypt, i18n} @@ -43,7 +44,7 @@ var core_libraries_modules = []string{art, conscrypt, i18n} // APIs. // In addition, the modules in this list are allowed to contribute to test APIs // stubs. -var non_updatable_modules = []string{virtualization, location} +var non_updatable_modules = []string{virtualization, location, nfc} // The intention behind this soong plugin is to generate a number of "merged" // API-related modules that would otherwise require a large amount of very diff --git a/api/coverage/tools/ExtractFlaggedApis.kt b/api/coverage/tools/ExtractFlaggedApis.kt index 948e64f22f20..9ffb70496c59 100644 --- a/api/coverage/tools/ExtractFlaggedApis.kt +++ b/api/coverage/tools/ExtractFlaggedApis.kt @@ -25,7 +25,7 @@ fun main(args: Array<String>) { var cb = ApiFile.parseApi(listOf(File(args[0]))) val flagToApi = mutableMapOf<String, MutableList<String>>() cb.getPackages() - .allTopLevelClasses() + .allClasses() .filter { it.methods().size > 0 } .forEach { for (method in it.methods()) { diff --git a/core/api/current.txt b/core/api/current.txt index 958b2f9f4e26..9bcbd720358a 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -33236,7 +33236,7 @@ package android.os { method public static android.os.Message obtain(android.os.Handler, int, Object); method public static android.os.Message obtain(android.os.Handler, int, int, int); method public static android.os.Message obtain(android.os.Handler, int, int, int, Object); - method public android.os.Bundle peekData(); + method @Nullable public android.os.Bundle peekData(); method public void recycle(); method public void sendToTarget(); method public void setAsynchronous(boolean); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 3d0101167782..95dc07fe04eb 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -298,7 +298,7 @@ package android { field public static final String RECOVER_KEYSTORE = "android.permission.RECOVER_KEYSTORE"; field public static final String REGISTER_CALL_PROVIDER = "android.permission.REGISTER_CALL_PROVIDER"; field public static final String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER"; - field public static final String REGISTER_NSD_OFFLOAD_ENGINE = "android.permission.REGISTER_NSD_OFFLOAD_ENGINE"; + field @FlaggedApi("com.android.net.flags.register_nsd_offload_engine") public static final String REGISTER_NSD_OFFLOAD_ENGINE = "android.permission.REGISTER_NSD_OFFLOAD_ENGINE"; field public static final String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION"; field public static final String REGISTER_STATS_PULL_ATOM = "android.permission.REGISTER_STATS_PULL_ATOM"; field public static final String REMOTE_DISPLAY_PROVIDER = "android.permission.REMOTE_DISPLAY_PROVIDER"; diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java index 72fb4ae03a63..cc184828cc33 100644 --- a/core/java/android/os/Message.java +++ b/core/java/android/os/Message.java @@ -16,6 +16,7 @@ package android.os; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; @@ -436,6 +437,7 @@ public final class Message implements Parcelable { * @see #getData() * @see #setData(Bundle) */ + @Nullable public Bundle peekData() { return data; } diff --git a/core/java/android/os/TEST_MAPPING b/core/java/android/os/TEST_MAPPING index cc5426631a7b..5c4aa4a233fc 100644 --- a/core/java/android/os/TEST_MAPPING +++ b/core/java/android/os/TEST_MAPPING @@ -52,8 +52,20 @@ ], "name": "FrameworksServicesTests", "options": [ - { "include-filter": "com.android.server.am.BatteryStatsServiceTest" }, - { "include-filter": "com.android.server.power.stats.BatteryStatsTests" } + { "include-filter": "com.android.server.am.BatteryStatsServiceTest" } + ] + }, + { + "file_patterns": [ + "BatteryStats[^/]*\\.java", + "BatteryUsageStats[^/]*\\.java", + "PowerComponents\\.java", + "[^/]*BatteryConsumer[^/]*\\.java" + ], + "name": "FrameworksServicesTests", + "options": [ + { "include-filter": "com.android.server.power.stats" }, + { "exclude-filter": "com.android.server.power.stats.BatteryStatsTests" } ] }, { diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS index e5b76f6c1c15..bf22dccce9d4 100644 --- a/core/java/android/os/storage/OWNERS +++ b/core/java/android/os/storage/OWNERS @@ -4,14 +4,16 @@ # Android Storage Team alukin@google.com -corinac@google.com +ankitavyas@google.com dipankarb@google.com +gargshivam@google.com krishang@google.com +riyaghai@google.com sahanas@google.com sergeynv@google.com +shikhamalhotra@google.com shubhisaxena@google.com tylersaunders@google.com maco@google.com nandana@google.com -narayan@google.com diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 8e72e13051b0..fa42fed75e56 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1729,23 +1729,6 @@ public class StorageManager { return RoSystemProperties.CRYPTO_FILE_ENCRYPTED; } - /** {@hide} - * @deprecated Use {@link #isFileEncrypted} instead, since emulated FBE is no longer supported. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Deprecated - public static boolean isFileEncryptedNativeOnly() { - return isFileEncrypted(); - } - - /** {@hide} - * @deprecated Use {@link #isFileEncrypted} instead, since emulated FBE is no longer supported. - */ - @Deprecated - public static boolean isFileEncryptedNativeOrEmulated() { - return isFileEncrypted(); - } - /** {@hide} */ public static boolean hasAdoptable() { switch (SystemProperties.get(PROP_ADOPTABLE)) { diff --git a/core/java/android/security/OWNERS b/core/java/android/security/OWNERS index 33a67aed6023..533d459e532b 100644 --- a/core/java/android/security/OWNERS +++ b/core/java/android/security/OWNERS @@ -8,4 +8,4 @@ per-file *NetworkSecurityPolicy.java = file:net/OWNERS per-file Confirmation*.java = file:/keystore/OWNERS per-file FileIntegrityManager.java = file:platform/system/security:/fsverity/OWNERS per-file IFileIntegrityService.aidl = file:platform/system/security:/fsverity/OWNERS -per-file *.aconfig = victorhsieh@google.com +per-file *.aconfig = victorhsieh@google.com,eranm@google.com diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index 5aa309753cc4..e94f23a6f4ce 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -8,7 +8,7 @@ flag { } flag { - name: "fix_unlocked_device_required_keys" + name: "fix_unlocked_device_required_keys_v2" namespace: "hardware_backed_security" description: "Fix bugs in behavior of UnlockedDeviceRequired keystore keys" bug: "296464083" diff --git a/core/java/android/service/notification/OWNERS b/core/java/android/service/notification/OWNERS index bb0e6aba436b..cb0b5fa6a029 100644 --- a/core/java/android/service/notification/OWNERS +++ b/core/java/android/service/notification/OWNERS @@ -2,6 +2,7 @@ juliacr@google.com yurilin@google.com +matiashe@google.com jeffdq@google.com dsandler@android.com dsandler@google.com diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 03a6a00e6af4..73d18f91f46c 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -22444,6 +22444,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Configure the {@link android.graphics.RenderEffect} to apply to the backdrop contents of this + * View. This will apply a visual effect to the result of the backdrop contents of this View + * before it is drawn. For example if + * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)} + * is provided, the previous content behind this View will be blurred before this View is drawn. + * @param renderEffect to be applied to the View. Passing null clears the previously configured + * {@link RenderEffect} + * @hide + */ + public void setBackdropRenderEffect(@Nullable RenderEffect renderEffect) { + if (mRenderNode.setBackdropRenderEffect(renderEffect)) { + invalidateViewProperty(true, true); + } + } + + /** * Updates the {@link Paint} object used with the current layer (used only if the current * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time diff --git a/core/java/com/android/internal/pm/OWNERS b/core/java/com/android/internal/pm/OWNERS new file mode 100644 index 000000000000..6ef34e2e5d4b --- /dev/null +++ b/core/java/com/android/internal/pm/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 36137 + +file:/PACKAGE_MANAGER_OWNERS + diff --git a/core/java/com/android/server/pm/OWNERS b/core/java/com/android/server/pm/OWNERS new file mode 100644 index 000000000000..6ef34e2e5d4b --- /dev/null +++ b/core/java/com/android/server/pm/OWNERS @@ -0,0 +1,4 @@ +# Bug component: 36137 + +file:/PACKAGE_MANAGER_OWNERS + diff --git a/core/jni/Android.bp b/core/jni/Android.bp index cc2d2e2aa55c..05117ce5fbff 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -457,9 +457,4 @@ cc_library_shared_for_libandroid_runtime { ], }, }, - - // Workaround Clang LTO crash. - lto: { - never: true, - }, } diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index 0f41229dd0c1..efdfce9ba46d 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -184,11 +184,11 @@ status_t NativeInputEventReceiver::reportTimeline(int32_t inputEventId, nsecs_t void NativeInputEventReceiver::setFdEvents(int events) { if (mFdEvents != events) { mFdEvents = events; - int fd = mInputConsumer.getChannel()->getFd(); + auto&& fd = mInputConsumer.getChannel()->getFd(); if (events) { - mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr); + mMessageQueue->getLooper()->addFd(fd.get(), 0, events, this, nullptr); } else { - mMessageQueue->getLooper()->removeFd(fd); + mMessageQueue->getLooper()->removeFd(fd.get()); } } } diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp index 8d39ddfa0406..694b28beeb9e 100644 --- a/core/jni/android_view_InputEventSender.cpp +++ b/core/jni/android_view_InputEventSender.cpp @@ -101,8 +101,8 @@ NativeInputEventSender::~NativeInputEventSender() { } status_t NativeInputEventSender::initialize() { - int receiveFd = mInputPublisher.getChannel()->getFd(); - mMessageQueue->getLooper()->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, this, NULL); + auto&& receiveFd = mInputPublisher.getChannel()->getFd(); + mMessageQueue->getLooper()->addFd(receiveFd.get(), 0, ALOOPER_EVENT_INPUT, this, NULL); return OK; } @@ -111,7 +111,7 @@ void NativeInputEventSender::dispose() { ALOGD("channel '%s' ~ Disposing input event sender.", getInputChannelName().c_str()); } - mMessageQueue->getLooper()->removeFd(mInputPublisher.getChannel()->getFd()); + mMessageQueue->getLooper()->removeFd(mInputPublisher.getChannel()->getFd().get()); } status_t NativeInputEventSender::sendKeyEvent(uint32_t seq, const KeyEvent* event) { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 0e753e51f597..f7b6a7b6b81c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2278,6 +2278,7 @@ <!-- Allows system apps to call methods to register itself as a mDNS offload engine. <p>Not for use by third-party or privileged applications. @SystemApi + @FlaggedApi("com.android.net.flags.register_nsd_offload_engine") @hide This should only be used by system apps. --> <permission android:name="android.permission.REGISTER_NSD_OFFLOAD_ENGINE" diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java index 07f1d4a09006..8dc9579e6b52 100644 --- a/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java +++ b/errorprone/java/com/google/errorprone/bugpatterns/android/HideInCommentsChecker.java @@ -63,7 +63,7 @@ public class HideInCommentsChecker extends BugChecker implements @Override public Description matchCompilationUnit(CompilationUnitTree tree, VisitorState state) { - final Map<Integer, Tree> javadocableTrees = findJavadocableTrees(tree); + final Map<Integer, Tree> javadocableTrees = findJavadocableTrees(tree, state); final String sourceCode = state.getSourceCode().toString(); for (ErrorProneToken token : ErrorProneTokens.getTokens(sourceCode, state.context)) { for (Tokens.Comment comment : token.comments()) { @@ -112,9 +112,9 @@ public class HideInCommentsChecker extends BugChecker implements } - private Map<Integer, Tree> findJavadocableTrees(CompilationUnitTree tree) { + private Map<Integer, Tree> findJavadocableTrees(CompilationUnitTree tree, VisitorState state) { Map<Integer, Tree> javadoccableTrees = new HashMap<>(); - new SuppressibleTreePathScanner<Void, Void>() { + new SuppressibleTreePathScanner<Void, Void>(state) { @Override public Void visitClass(ClassTree classTree, Void unused) { javadoccableTrees.put(getStartPosition(classTree), classTree); diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java index 2ec4524e1241..d659ddd75f72 100644 --- a/graphics/java/android/graphics/BaseRecordingCanvas.java +++ b/graphics/java/android/graphics/BaseRecordingCanvas.java @@ -402,8 +402,8 @@ public class BaseRecordingCanvas extends Canvas { } @Override - public final void drawDoubleRoundRect(@NonNull RectF outer, float[] outerRadii, - @NonNull RectF inner, float[] innerRadii, @NonNull Paint paint) { + public final void drawDoubleRoundRect(@NonNull RectF outer, @NonNull float[] outerRadii, + @NonNull RectF inner, @NonNull float[] innerRadii, @NonNull Paint paint) { nDrawDoubleRoundRect(mNativeCanvasWrapper, outer.left, outer.top, outer.right, outer.bottom, outerRadii, inner.left, inner.top, inner.right, inner.bottom, innerRadii, diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index 2e91c240d71b..15d26ebe66f6 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -971,6 +971,23 @@ public final class RenderNode { } /** + * Configure the {@link android.graphics.RenderEffect} to apply to the backdrop contents of + * this RenderNode. This will apply a visual effect to the result of the backdrop contents + * of this RenderNode before the RenderNode is drawn into the destination. For example if + * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)} + * is provided, the previous content behind this RenderNode will be blurred before the + * RenderNode is drawn in to the destination. + * @param renderEffect to be applied to the backdrop contents of this RenderNode. Passing + * null clears all previously configured RenderEffects + * @return True if the value changed, false if the new value was the same as the previous value. + * @hide + */ + public boolean setBackdropRenderEffect(@Nullable RenderEffect renderEffect) { + return nSetBackdropRenderEffect(mNativeRenderNode, + renderEffect != null ? renderEffect.getNativeInstance() : 0); + } + + /** * Returns the translucency level of this display list. * * @return A value between 0.0f and 1.0f @@ -1797,6 +1814,9 @@ public final class RenderNode { private static native boolean nSetRenderEffect(long renderNode, long renderEffect); @CriticalNative + private static native boolean nSetBackdropRenderEffect(long renderNode, long renderEffect); + + @CriticalNative private static native boolean nSetHasOverlappingRendering(long renderNode, boolean hasOverlappingRendering); diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java index 5e16bcee1a0e..dd703f5eefb9 100644 --- a/keystore/java/android/security/KeyStore2.java +++ b/keystore/java/android/security/KeyStore2.java @@ -33,7 +33,6 @@ import android.system.keystore2.ResponseCode; import android.util.Log; import java.util.Calendar; -import java.util.Objects; /** * @hide This should not be made public in its present form because it @@ -139,13 +138,25 @@ public class KeyStore2 { return new KeyStore2(); } + /** + * Gets the {@link IKeystoreService} that should be started in early_hal in Android. + * + * @throws IllegalStateException if the KeystoreService is not available or has not + * been initialized when called. This is a state that should not happen and indicates + * and error somewhere in the stack or with the calling processes access permissions. + */ @NonNull private synchronized IKeystoreService getService(boolean retryLookup) { if (mBinder == null || retryLookup) { mBinder = IKeystoreService.Stub.asInterface(ServiceManager - .getService(KEYSTORE2_SERVICE_NAME)); - Binder.allowBlocking(mBinder.asBinder()); + .getService(KEYSTORE2_SERVICE_NAME)); + } + if (mBinder == null) { + throw new IllegalStateException( + "Could not connect to Keystore service. Keystore may have crashed or not been" + + " initialized"); } - return Objects.requireNonNull(mBinder); + Binder.allowBlocking(mBinder.asBinder()); + return mBinder; } void delete(KeyDescriptor descriptor) throws KeyStoreException { diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index db581471e2ca..b5e6f94af022 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -514,6 +514,7 @@ cc_defaults { "canvas/CanvasOpRasterizer.cpp", "effects/StretchEffect.cpp", "effects/GainmapRenderer.cpp", + "pipeline/skia/BackdropFilterDrawable.cpp", "pipeline/skia/HolePunch.cpp", "pipeline/skia/SkiaDisplayList.cpp", "pipeline/skia/SkiaRecordingCanvas.cpp", diff --git a/libs/hwui/Mesh.cpp b/libs/hwui/Mesh.cpp index e59bc9565a59..37a7d74330e9 100644 --- a/libs/hwui/Mesh.cpp +++ b/libs/hwui/Mesh.cpp @@ -90,8 +90,8 @@ std::tuple<bool, SkString> Mesh::validate() { FAIL_MESH_VALIDATE("%s mode requires at least %zu vertices but vertex count is %zu.", modeToStr(meshMode), min_vcount_for_mode(meshMode), mVertexCount); } - SkASSERT(!fICount); - SkASSERT(!fIOffset); + LOG_ALWAYS_FATAL_IF(mIndexCount != 0); + LOG_ALWAYS_FATAL_IF(mIndexOffset != 0); } if (!sm.ok()) { diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 1c39db3a31bb..1dd22cf43c5c 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -260,6 +260,12 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu pushStagingDisplayListChanges(observer, info); } + // always damageSelf when filtering backdrop content, or else the BackdropFilterDrawable will + // get a wrong snapshot of previous content. + if (mProperties.layerProperties().getBackdropImageFilter()) { + damageSelf(info); + } + if (mDisplayList) { info.out.hasFunctors |= mDisplayList.hasFunctor(); mHasHolePunches = mDisplayList.hasHolePunches(); diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp index 0589f136b666..c5371236b9cf 100644 --- a/libs/hwui/RenderProperties.cpp +++ b/libs/hwui/RenderProperties.cpp @@ -55,6 +55,12 @@ bool LayerProperties::setImageFilter(SkImageFilter* imageFilter) { return true; } +bool LayerProperties::setBackdropImageFilter(SkImageFilter* imageFilter) { + if (mBackdropImageFilter.get() == imageFilter) return false; + mBackdropImageFilter = sk_ref_sp(imageFilter); + return true; +} + bool LayerProperties::setFromPaint(const SkPaint* paint) { bool changed = false; changed |= setAlpha(static_cast<uint8_t>(PaintUtils::getAlphaDirect(paint))); @@ -70,6 +76,7 @@ LayerProperties& LayerProperties::operator=(const LayerProperties& other) { setXferMode(other.xferMode()); setColorFilter(other.getColorFilter()); setImageFilter(other.getImageFilter()); + setBackdropImageFilter(other.getBackdropImageFilter()); mStretchEffect = other.mStretchEffect; return *this; } diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index 064ba7aee107..e358b57f6fe1 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -97,8 +97,12 @@ public: bool setImageFilter(SkImageFilter* imageFilter); + bool setBackdropImageFilter(SkImageFilter* imageFilter); + SkImageFilter* getImageFilter() const { return mImageFilter.get(); } + SkImageFilter* getBackdropImageFilter() const { return mBackdropImageFilter.get(); } + const StretchEffect& getStretchEffect() const { return mStretchEffect; } StretchEffect& mutableStretchEffect() { return mStretchEffect; } @@ -129,6 +133,7 @@ private: SkBlendMode mMode; sk_sp<SkColorFilter> mColorFilter; sk_sp<SkImageFilter> mImageFilter; + sk_sp<SkImageFilter> mBackdropImageFilter; StretchEffect mStretchEffect; }; diff --git a/libs/hwui/jni/YuvToJpegEncoder.cpp b/libs/hwui/jni/YuvToJpegEncoder.cpp index 69418b09fee6..729890638931 100644 --- a/libs/hwui/jni/YuvToJpegEncoder.cpp +++ b/libs/hwui/jni/YuvToJpegEncoder.cpp @@ -5,6 +5,7 @@ #include "SkStream.h" #include "YuvToJpegEncoder.h" #include <ui/PixelFormat.h> +#include <utils/Errors.h> #include <hardware/hardware.h> #include "graphics_jni_helpers.h" @@ -298,7 +299,7 @@ void Yuv422IToJpegEncoder::configSamplingFactors(jpeg_compress_struct* cinfo) { } /////////////////////////////////////////////////////////////////////////////// -using namespace android::ultrahdr; +using namespace ultrahdr; ultrahdr_color_gamut P010Yuv420ToJpegREncoder::findColorGamut(JNIEnv* env, int aDataSpace) { switch (aDataSpace & ADataSpace::STANDARD_MASK) { diff --git a/libs/hwui/jni/YuvToJpegEncoder.h b/libs/hwui/jni/YuvToJpegEncoder.h index 8ef780547184..0e711efc2a73 100644 --- a/libs/hwui/jni/YuvToJpegEncoder.h +++ b/libs/hwui/jni/YuvToJpegEncoder.h @@ -103,7 +103,7 @@ public: * @param aDataSpace data space defined in data_space.h. * @return color gamut for JPEG/R. */ - static android::ultrahdr::ultrahdr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace); + static ultrahdr::ultrahdr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace); /** Map data space (defined in DataSpace.java and data_space.h) to the transfer function * used in JPEG/R @@ -112,8 +112,8 @@ public: * @param aDataSpace data space defined in data_space.h. * @return color gamut for JPEG/R. */ - static android::ultrahdr::ultrahdr_transfer_function findHdrTransferFunction( - JNIEnv* env, int aDataSpace); + static ultrahdr::ultrahdr_transfer_function findHdrTransferFunction(JNIEnv* env, + int aDataSpace); }; #endif // _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_ diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp index 8c7b9a4b5e94..2a218a25913d 100644 --- a/libs/hwui/jni/android_graphics_RenderNode.cpp +++ b/libs/hwui/jni/android_graphics_RenderNode.cpp @@ -243,6 +243,13 @@ static jboolean android_view_RenderNode_setRenderEffect(CRITICAL_JNI_PARAMS_COMM return SET_AND_DIRTY(mutateLayerProperties().setImageFilter, imageFilter, RenderNode::GENERIC); } +static jboolean android_view_RenderNode_setBackdropRenderEffect( + CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jlong renderEffectPtr) { + SkImageFilter* imageFilter = reinterpret_cast<SkImageFilter*>(renderEffectPtr); + return SET_AND_DIRTY(mutateLayerProperties().setBackdropImageFilter, imageFilter, + RenderNode::GENERIC); +} + static jboolean android_view_RenderNode_setHasOverlappingRendering(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, bool hasOverlappingRendering) { return SET_AND_DIRTY(setHasOverlappingRendering, hasOverlappingRendering, @@ -792,6 +799,8 @@ static const JNINativeMethod gMethods[] = { {"nSetAlpha", "(JF)Z", (void*)android_view_RenderNode_setAlpha}, {"nSetRenderEffect", "(JJ)Z", (void*)android_view_RenderNode_setRenderEffect}, + {"nSetBackdropRenderEffect", "(JJ)Z", + (void*)android_view_RenderNode_setBackdropRenderEffect}, {"nSetHasOverlappingRendering", "(JZ)Z", (void*)android_view_RenderNode_setHasOverlappingRendering}, {"nSetUsageHint", "(JI)V", (void*)android_view_RenderNode_setUsageHint}, diff --git a/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp b/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp new file mode 100644 index 000000000000..ffad69993fd8 --- /dev/null +++ b/libs/hwui/pipeline/skia/BackdropFilterDrawable.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BackdropFilterDrawable.h" + +#include <SkImage.h> +#include <SkSurface.h> + +#include "RenderNode.h" +#include "RenderNodeDrawable.h" + +namespace android { +namespace uirenderer { +namespace skiapipeline { + +BackdropFilterDrawable::~BackdropFilterDrawable() {} + +bool BackdropFilterDrawable::prepareToDraw(SkCanvas* canvas, const RenderProperties& properties, + int backdropImageWidth, int backdropImageHeight) { + // the drawing bounds for blurred content. + mDstBounds.setWH(properties.getWidth(), properties.getHeight()); + + float alphaMultiplier = 1.0f; + RenderNodeDrawable::setViewProperties(properties, canvas, &alphaMultiplier, true); + + // get proper subset for previous content. + canvas->getTotalMatrix().mapRect(&mImageSubset, mDstBounds); + SkRect imageSubset(mImageSubset); + // ensure the subset is inside bounds of previous content. + if (!mImageSubset.intersect(SkRect::MakeWH(backdropImageWidth, backdropImageHeight))) { + return false; + } + + // correct the drawing bounds if subset was changed. + if (mImageSubset != imageSubset) { + SkMatrix inverse; + if (canvas->getTotalMatrix().invert(&inverse)) { + inverse.mapRect(&mDstBounds, mImageSubset); + } + } + + // follow the alpha from the target RenderNode. + mPaint.setAlpha(properties.layerProperties().alpha() * alphaMultiplier); + return true; +} + +void BackdropFilterDrawable::onDraw(SkCanvas* canvas) { + const RenderProperties& properties = mTargetRenderNode->properties(); + auto* backdropFilter = properties.layerProperties().getBackdropImageFilter(); + auto* surface = canvas->getSurface(); + if (!backdropFilter || !surface) { + return; + } + + auto backdropImage = surface->makeImageSnapshot(); + // sync necessary properties from target RenderNode. + if (!prepareToDraw(canvas, properties, backdropImage->width(), backdropImage->height())) { + return; + } + + auto imageSubset = mImageSubset.roundOut(); + backdropImage = + backdropImage->makeWithFilter(canvas->recordingContext(), backdropFilter, imageSubset, + imageSubset, &mOutSubset, &mOutOffset); + canvas->drawImageRect(backdropImage, SkRect::Make(mOutSubset), mDstBounds, + SkSamplingOptions(SkFilterMode::kLinear), &mPaint, + SkCanvas::kStrict_SrcRectConstraint); +} + +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/BackdropFilterDrawable.h b/libs/hwui/pipeline/skia/BackdropFilterDrawable.h new file mode 100644 index 000000000000..9e35837675ae --- /dev/null +++ b/libs/hwui/pipeline/skia/BackdropFilterDrawable.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <SkCanvas.h> +#include <SkDrawable.h> +#include <SkPaint.h> + +namespace android { +namespace uirenderer { + +class RenderNode; +class RenderProperties; + +namespace skiapipeline { + +/** + * This drawable captures it's backdrop content and render it with a + * image filter. + */ +class BackdropFilterDrawable : public SkDrawable { +public: + BackdropFilterDrawable(RenderNode* renderNode, SkCanvas* canvas) + : mTargetRenderNode(renderNode), mBounds(canvas->getLocalClipBounds()) {} + + ~BackdropFilterDrawable(); + +private: + RenderNode* mTargetRenderNode; + SkPaint mPaint; + + SkRect mDstBounds; + SkRect mImageSubset; + SkIRect mOutSubset; + SkIPoint mOutOffset; + + /** + * Check all necessary properties before actual drawing. + * Return true if ready to draw. + */ + bool prepareToDraw(SkCanvas* canvas, const RenderProperties& properties, int backdropImageWidth, + int backdropImageHeight); + +protected: + void onDraw(SkCanvas* canvas) override; + + virtual SkRect onGetBounds() override { return mBounds; } + const SkRect mBounds; +}; + +} // namespace skiapipeline +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index da4f66d45a70..9d72c2315198 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -362,7 +362,7 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { } void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, SkCanvas* canvas, - float* alphaMultiplier) { + float* alphaMultiplier, bool ignoreLayer) { if (properties.getLeft() != 0 || properties.getTop() != 0) { canvas->translate(properties.getLeft(), properties.getTop()); } @@ -378,7 +378,8 @@ void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, S canvas->concat(*properties.getTransformMatrix()); } } - if (Properties::getStretchEffectBehavior() == StretchEffectBehavior::UniformScale) { + if (Properties::getStretchEffectBehavior() == StretchEffectBehavior::UniformScale && + !ignoreLayer) { const StretchEffect& stretch = properties.layerProperties().getStretchEffect(); if (!stretch.isEmpty()) { canvas->concat( @@ -388,10 +389,10 @@ void RenderNodeDrawable::setViewProperties(const RenderProperties& properties, S const bool isLayer = properties.effectiveLayerType() != LayerType::None; int clipFlags = properties.getClippingFlags(); if (properties.getAlpha() < 1) { - if (isLayer) { + if (isLayer && !ignoreLayer) { clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer } - if (CC_LIKELY(isLayer || !properties.getHasOverlappingRendering())) { + if (CC_LIKELY(isLayer || !properties.getHasOverlappingRendering()) || ignoreLayer) { *alphaMultiplier = properties.getAlpha(); } else { // savelayer needed to create an offscreen buffer diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.h b/libs/hwui/pipeline/skia/RenderNodeDrawable.h index c7582e734009..818ac45bf346 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.h +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.h @@ -120,7 +120,7 @@ private: * Applies the rendering properties of a view onto a SkCanvas. */ static void setViewProperties(const RenderProperties& properties, SkCanvas* canvas, - float* alphaMultiplier); + float* alphaMultiplier, bool ignoreLayer = false); /** * Stores transform on the canvas at time of recording and is used for @@ -149,6 +149,11 @@ private: * display list that is searched for any render nodes with getProjectBackwards==true */ SkiaDisplayList* mProjectedDisplayList = nullptr; + + /** + * Allow BackdropFilterDrawable to apply same render properties onto SkCanvas. + */ + friend class BackdropFilterDrawable; }; } // namespace skiapipeline diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 3ca7eeb37a89..58c14c1fabbd 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -37,6 +37,7 @@ #include "NinePatchUtils.h" #include "RenderNode.h" #include "pipeline/skia/AnimatedDrawables.h" +#include "pipeline/skia/BackdropFilterDrawable.h" #ifdef __ANDROID__ // Layoutlib does not support GL, Vulcan etc. #include "pipeline/skia/GLFunctorDrawable.h" #include "pipeline/skia/VkFunctorDrawable.h" @@ -168,6 +169,14 @@ void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) { // Put Vulkan WebViews with non-rectangular clips in a HW layer renderNode->mutateStagingProperties().setClipMayBeComplex(mRecorder.isClipMayBeComplex()); } + + // draw backdrop filter drawable if needed. + if (renderNode->stagingProperties().layerProperties().getBackdropImageFilter()) { + auto* backdropFilterDrawable = + mDisplayList->allocateDrawable<BackdropFilterDrawable>(renderNode, asSkCanvas()); + drawDrawable(backdropFilterDrawable); + } + drawDrawable(&renderNodeDrawable); // use staging property, since recording on UI thread diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp index 596bd37e4cf5..f67042b21f8f 100644 --- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp +++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp @@ -20,14 +20,17 @@ #include <SkBlendMode.h> #include <SkClipStack.h> #include <SkSurface_Base.h> +#include <include/effects/SkImageFilters.h> #include <string.h> + #include "AnimationContext.h" #include "DamageAccumulator.h" #include "FatalTestCanvas.h" #include "IContextFactory.h" -#include "hwui/Paint.h" #include "RecordingCanvas.h" #include "SkiaCanvas.h" +#include "hwui/Paint.h" +#include "pipeline/skia/BackdropFilterDrawable.h" #include "pipeline/skia/SkiaDisplayList.h" #include "pipeline/skia/SkiaOpenGLPipeline.h" #include "pipeline/skia/SkiaPipeline.h" @@ -1210,3 +1213,77 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaRecordingCanvas, drawVectorDrawable) { canvas.drawDrawable(&drawable); EXPECT_EQ(2, canvas.mDrawCounter); } + +// Verify drawing logics for BackdropFilterDrawable +RENDERTHREAD_TEST(BackdropFilterDrawable, drawing) { + static const int CANVAS_WIDTH = 100; + static const int CANVAS_HEIGHT = 200; + class SimpleTestCanvas : public TestCanvasBase { + public: + SkRect mDstBounds; + SimpleTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {} + void onDrawRect(const SkRect& rect, const SkPaint& paint) override { + // did nothing. + } + + // called when BackdropFilterDrawable is drawn. + void onDrawImageRect2(const SkImage*, const SkRect& src, const SkRect& dst, + const SkSamplingOptions&, const SkPaint*, + SrcRectConstraint) override { + mDrawCounter++; + mDstBounds = dst; + } + }; + class SimpleLayer : public SkSurface_Base { + public: + SimpleLayer() + : SkSurface_Base(SkImageInfo::MakeN32Premul(CANVAS_WIDTH, CANVAS_HEIGHT), nullptr) { + } + virtual sk_sp<SkImage> onNewImageSnapshot(const SkIRect* bounds) override { + SkBitmap bitmap; + bitmap.allocN32Pixels(CANVAS_WIDTH, CANVAS_HEIGHT); + bitmap.setImmutable(); + return SkImage::MakeFromBitmap(bitmap); + } + SkCanvas* onNewCanvas() override { return new SimpleTestCanvas(); } + sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; } + bool onCopyOnWrite(ContentChangeMode) override { return true; } + void onWritePixels(const SkPixmap&, int x, int y) {} + }; + + auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, + [](RenderProperties& props, SkiaRecordingCanvas& canvas) { + canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, + Paint()); + }); + + sk_sp<SkSurface> surface(new SimpleLayer()); + auto* canvas = reinterpret_cast<SimpleTestCanvas*>(surface->getCanvas()); + RenderNodeDrawable drawable(node.get(), canvas, true); + BackdropFilterDrawable backdropDrawable(node.get(), canvas); + canvas->drawDrawable(&drawable); + canvas->drawDrawable(&backdropDrawable); + // no backdrop filter, skip drawing. + EXPECT_EQ(0, canvas->mDrawCounter); + + sk_sp<SkImageFilter> filter(SkImageFilters::Blur(3, 3, nullptr)); + node->animatorProperties().mutateLayerProperties().setBackdropImageFilter(filter.get()); + canvas->drawDrawable(&drawable); + canvas->drawDrawable(&backdropDrawable); + // backdrop filter is set, ok to draw. + EXPECT_EQ(1, canvas->mDrawCounter); + EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), canvas->mDstBounds); + + canvas->translate(30, 30); + canvas->drawDrawable(&drawable); + canvas->drawDrawable(&backdropDrawable); + // the drawable is still visible, ok to draw. + EXPECT_EQ(2, canvas->mDrawCounter); + EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH - 30, CANVAS_HEIGHT - 30), canvas->mDstBounds); + + canvas->translate(CANVAS_WIDTH, CANVAS_HEIGHT); + canvas->drawDrawable(&drawable); + canvas->drawDrawable(&backdropDrawable); + // the drawable is invisible, skip drawing. + EXPECT_EQ(2, canvas->mDrawCounter); +} diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java index 0a0a6263686a..ab7c27f70e05 100644 --- a/media/java/android/media/MediaCas.java +++ b/media/java/android/media/MediaCas.java @@ -272,7 +272,7 @@ public final class MediaCas implements AutoCloseable { Log.d(TAG, "Trying to get AIDL service"); IMediaCasService serviceAidl = IMediaCasService.Stub.asInterface( - ServiceManager.getService( + ServiceManager.waitForDeclaredService( IMediaCasService.DESCRIPTOR + "/default")); if (serviceAidl != null) { return serviceAidl; diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 6031ef70535d..94fce797f5d6 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -122,11 +122,6 @@ cc_library_shared { "-Wunused", "-Wunreachable-code", ], - - // Workaround Clang LTO crash. - lto: { - never: true, - }, } cc_library_shared { diff --git a/media/jni/audioeffect/Android.bp b/media/jni/audioeffect/Android.bp index 8b5b726fd2db..cf5059ceb3c9 100644 --- a/media/jni/audioeffect/Android.bp +++ b/media/jni/audioeffect/Android.bp @@ -44,9 +44,4 @@ cc_library_shared { "-Wunreachable-code", "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION", ], - - // Workaround Clang LTO crash. - lto: { - never: true, - }, } diff --git a/mime/java-res/android.mime.types b/mime/java-res/android.mime.types index cb74cfc89cbe..fbdfe3e35b87 100644 --- a/mime/java-res/android.mime.types +++ b/mime/java-res/android.mime.types @@ -54,6 +54,8 @@ ?application/ttml+xml ttml dfxp ?application/vnd.android.ota ota ?application/vnd.apple.mpegurl m3u8 +?application/vnd.apple.pkpass pkpass +?application/vnd.apple.pkpasses pkpasses ?application/vnd.ms-pki.stl stl ?application/vnd.ms-powerpoint pot ?application/vnd.ms-wpl wpl diff --git a/nfc/Android.bp b/nfc/Android.bp new file mode 100644 index 000000000000..bf9f47ceb0a7 --- /dev/null +++ b/nfc/Android.bp @@ -0,0 +1,51 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +filegroup { + name: "framework-nfc-non-updatable-sources", + path: "java", + srcs: [], +} + +filegroup { + name: "framework-nfc-updatable-sources", + path: "java", + srcs: [ + "java/**/*.java", + "java/**/*.aidl", + ], + exclude_srcs: [ + ":framework-nfc-non-updatable-sources", + ], +} + +java_sdk_library { + name: "framework-nfc", + libs: [ + "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage + ], + srcs: [ + ":framework-nfc-updatable-sources", + ], + defaults: ["framework-non-updatable-unbundled-defaults"], + permitted_packages: [ + "android.nfc", + "com.android.nfc", + ], + hidden_api_packages: [ + "com.android.nfc", + ], + aidl: { + include_dirs: [ + // TODO (b/303286040): Remove these when we change to |framework-module-defaults| + "frameworks/base/nfc/java", + "frameworks/base/core/java", + ], + }, +} diff --git a/nfc/OWNERS b/nfc/OWNERS new file mode 100644 index 000000000000..35e9713f5715 --- /dev/null +++ b/nfc/OWNERS @@ -0,0 +1,2 @@ +# Bug component: 48448 +include platform/packages/apps/Nfc:/OWNERS diff --git a/nfc/TEST_MAPPING b/nfc/TEST_MAPPING new file mode 100644 index 000000000000..5b5ea3790010 --- /dev/null +++ b/nfc/TEST_MAPPING @@ -0,0 +1,10 @@ +{ + "presubmit": [ + { + "name": "NfcManagerTests" + }, + { + "name": "CtsNfcTestCases" + } + ] +} diff --git a/nfc/api/current.txt b/nfc/api/current.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/module-lib-current.txt b/nfc/api/module-lib-current.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/module-lib-current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/module-lib-removed.txt b/nfc/api/module-lib-removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/module-lib-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/removed.txt b/nfc/api/removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/system-current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/system-removed.txt b/nfc/api/system-removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/system-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/test-current.txt b/nfc/api/test-current.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/test-current.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/api/test-removed.txt b/nfc/api/test-removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/nfc/api/test-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/nfc/java/android/nfc/Placeholder.java b/nfc/java/android/nfc/Placeholder.java new file mode 100644 index 000000000000..3509644ac106 --- /dev/null +++ b/nfc/java/android/nfc/Placeholder.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.nfc; + +/** + * Placeholder class so new framework-nfc module isn't empty, will be removed once module is + * populated. + * + * @hide + * + */ +public class Placeholder { +} diff --git a/packages/CrashRecovery/OWNERS b/packages/CrashRecovery/OWNERS new file mode 100644 index 000000000000..daa02111f71f --- /dev/null +++ b/packages/CrashRecovery/OWNERS @@ -0,0 +1,3 @@ +ancr@google.com +harshitmahajan@google.com +robertogil@google.com diff --git a/packages/CrashRecovery/framework/Android.bp b/packages/CrashRecovery/framework/Android.bp new file mode 100644 index 000000000000..b2af315ef2c9 --- /dev/null +++ b/packages/CrashRecovery/framework/Android.bp @@ -0,0 +1,9 @@ +filegroup { + name: "framework-crashrecovery-sources", + srcs: [ + "java/**/*.java", + "java/**/*.aidl", + ], + path: "java", + visibility: ["//frameworks/base:__subpackages__"], +} diff --git a/core/java/android/service/watchdog/ExplicitHealthCheckService.java b/packages/CrashRecovery/framework/java/android/service/watchdog/ExplicitHealthCheckService.java index 7befbfb0f370..7befbfb0f370 100644 --- a/core/java/android/service/watchdog/ExplicitHealthCheckService.java +++ b/packages/CrashRecovery/framework/java/android/service/watchdog/ExplicitHealthCheckService.java diff --git a/core/java/android/service/watchdog/IExplicitHealthCheckService.aidl b/packages/CrashRecovery/framework/java/android/service/watchdog/IExplicitHealthCheckService.aidl index 78c0328d36f0..90965092ac2b 100644 --- a/core/java/android/service/watchdog/IExplicitHealthCheckService.aidl +++ b/packages/CrashRecovery/framework/java/android/service/watchdog/IExplicitHealthCheckService.aidl @@ -21,6 +21,7 @@ import android.os.RemoteCallback; /** * @hide */ +@PermissionManuallyEnforced oneway interface IExplicitHealthCheckService { void setCallback(in @nullable RemoteCallback callback); diff --git a/core/java/android/service/watchdog/OWNERS b/packages/CrashRecovery/framework/java/android/service/watchdog/OWNERS index 1c045e10c0ec..1c045e10c0ec 100644 --- a/core/java/android/service/watchdog/OWNERS +++ b/packages/CrashRecovery/framework/java/android/service/watchdog/OWNERS diff --git a/core/java/android/service/watchdog/PackageConfig.aidl b/packages/CrashRecovery/framework/java/android/service/watchdog/PackageConfig.aidl index 013158676f79..013158676f79 100644 --- a/core/java/android/service/watchdog/PackageConfig.aidl +++ b/packages/CrashRecovery/framework/java/android/service/watchdog/PackageConfig.aidl diff --git a/packages/CrashRecovery/services/Android.bp b/packages/CrashRecovery/services/Android.bp new file mode 100644 index 000000000000..27ddff93247e --- /dev/null +++ b/packages/CrashRecovery/services/Android.bp @@ -0,0 +1,9 @@ +filegroup { + name: "services-crashrecovery-sources", + srcs: [ + "java/**/*.java", + "java/**/*.aidl", + ], + path: "java", + visibility: ["//frameworks/base:__subpackages__"], +} diff --git a/services/core/java/com/android/server/ExplicitHealthCheckController.java b/packages/CrashRecovery/services/java/com/android/server/ExplicitHealthCheckController.java index 3d610d3747c9..3d610d3747c9 100644 --- a/services/core/java/com/android/server/ExplicitHealthCheckController.java +++ b/packages/CrashRecovery/services/java/com/android/server/ExplicitHealthCheckController.java diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java index d256aead97e8..d256aead97e8 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java diff --git a/services/core/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java index eb65b2a9eedd..eb65b2a9eedd 100644 --- a/services/core/java/com/android/server/RescueParty.java +++ b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java index 2007079ea5ca..2007079ea5ca 100644 --- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +++ b/packages/CrashRecovery/services/java/com/android/server/rollback/RollbackPackageHealthObserver.java diff --git a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java b/packages/CrashRecovery/services/java/com/android/server/rollback/WatchdogRollbackLogger.java index f9ef994a523a..f9ef994a523a 100644 --- a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java +++ b/packages/CrashRecovery/services/java/com/android/server/rollback/WatchdogRollbackLogger.java diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java index 1088acef0fb0..4992ef1e1c00 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java @@ -290,7 +290,14 @@ public class InstallInstalling extends AlertActivity { broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); - session.commit(pendingIntent.getIntentSender()); + try { + session.commit(pendingIntent.getIntentSender()); + } catch (Exception e) { + Log.e(LOG_TAG, "Cannot install package: ", e); + launchFailure(PackageInstaller.STATUS_FAILURE, + PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null); + return; + } mCancelButton.setEnabled(false); setFinishOnTouchOutside(false); } else { diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index ed5654d4f259..ec50323dd91d 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -2432,9 +2432,7 @@ class DatabaseHelper extends SQLiteOpenHelper { R.bool.def_auto_time_zone); // Sync timezone to NITZ loadSetting(stmt, Settings.Global.STAY_ON_WHILE_PLUGGED_IN, - ("1".equals(SystemProperties.get("ro.boot.qemu")) - || res.getBoolean(R.bool.def_stay_on_while_plugged_in)) - ? 1 : 0); + res.getBoolean(R.bool.def_stay_on_while_plugged_in) ? 1 : 0); loadIntegerSetting(stmt, Settings.Global.WIFI_SLEEP_POLICY, R.integer.def_wifi_sleep_policy); diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java index 63b4288ce055..e0ce3db39403 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java @@ -27,7 +27,7 @@ import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_S import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; -import android.os.SystemProperties; +import android.os.Build; import android.provider.Settings; import android.util.Log; @@ -87,7 +87,7 @@ public class ClipboardListener implements String clipSource = mClipboardManager.getPrimaryClipSource(); ClipData clipData = mClipboardManager.getPrimaryClip(); - if (shouldSuppressOverlay(clipData, clipSource, isEmulator())) { + if (shouldSuppressOverlay(clipData, clipSource, Build.IS_EMULATOR)) { Log.i(TAG, "Clipboard overlay suppressed."); return; } @@ -141,10 +141,6 @@ public class ClipboardListener implements return true; } - private static boolean isEmulator() { - return SystemProperties.getBoolean("ro.boot.qemu", false); - } - private boolean isUserSetupComplete() { return Settings.Secure.getInt(mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1; diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java index 67e96645f9c5..27e6895af612 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java @@ -165,6 +165,9 @@ public class PeopleTileViewHelper { + "\\p{Emoji}(\\p{EMod}|\\x{FE0F}\\x{20E3}?|[\\x{E0020}-\\x{E007E}]+\\x{E007F})" + "?)*"; + // Not all JDKs support emoji patterns, including the one errorprone runs under, which + // makes it think that this is an invalid pattern. + @SuppressWarnings("InvalidPatternSyntax") private static final Pattern EMOJI_PATTERN = Pattern.compile(UNICODE_EMOJI_REGEX); public static final String EMPTY_STRING = ""; diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java index 941cd7783ed0..900805f818d3 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java @@ -25,6 +25,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.debug.IAdbManager; import android.hardware.usb.UsbManager; +import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.ServiceManager; @@ -69,8 +70,7 @@ public class UsbDebuggingActivity extends AlertActivity super.onCreate(icicle); // Emulator does not support reseating the usb cable to reshow the dialog. - boolean isEmulator = SystemProperties.get("ro.boot.qemu").equals("1"); - if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0 && !isEmulator) { + if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0 && !Build.IS_EMULATOR) { mDisconnectedReceiver = new UsbDisconnectedReceiver(this); IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE); mBroadcastDispatcher.registerReceiver(mDisconnectedReceiver, filter); diff --git a/services/Android.bp b/services/Android.bp index 0f6b9845b4aa..e4fe581dc6bf 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -43,7 +43,10 @@ soong_config_module_type { name: "system_optimized_java_defaults", module_type: "java_defaults", config_namespace: "ANDROID", - bool_variables: ["SYSTEM_OPTIMIZE_JAVA"], + bool_variables: [ + "SYSTEM_OPTIMIZE_JAVA", + "FULL_SYSTEM_OPTIMIZE_JAVA", + ], properties: ["optimize"], } @@ -55,6 +58,7 @@ system_optimized_java_defaults { enabled: true, // TODO(b/210510433): Enable optimizations after improving // retracing infra. + // See also FULL_SYSTEM_OPTIMIZE_JAVA. optimize: false, shrink: true, ignore_warnings: false, @@ -78,6 +82,12 @@ system_optimized_java_defaults { }, }, }, + // Allow form factors to opt-in full system java optimization + FULL_SYSTEM_OPTIMIZE_JAVA: { + optimize: { + optimize: true, + }, + }, }, } diff --git a/services/companion/java/com/android/server/companion/virtual/OWNERS b/services/companion/java/com/android/server/companion/virtual/OWNERS index 5295ec82e3c3..4fe0592f9075 100644 --- a/services/companion/java/com/android/server/companion/virtual/OWNERS +++ b/services/companion/java/com/android/server/companion/virtual/OWNERS @@ -2,7 +2,7 @@ set noparent -ogunwale@google.com -michaelwr@google.com +marvinramin@google.com vladokom@google.com -marvinramin@google.com
\ No newline at end of file +ogunwale@google.com +michaelwr@google.com
\ No newline at end of file diff --git a/services/core/Android.bp b/services/core/Android.bp index 22f85703f428..37976b58a4e0 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -122,6 +122,9 @@ java_library_static { "java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/wm/EventLogTags.logtags", "java/com/android/server/policy/EventLogTags.logtags", + + // Java/AIDL sources to be moved out to CrashRecovery module + ":services-crashrecovery-sources", ], libs: [ @@ -130,7 +133,6 @@ java_library_static { "android.hardware.light-V2.0-java", "android.hardware.gnss-V2-java", "android.hardware.vibrator-V2-java", - "android.nfc.flags-aconfig-java", "app-compat-annotations", "framework-tethering.stubs.module_lib", "service-art.stubs.system_server", @@ -153,7 +155,7 @@ java_library_static { "android.hardware.boot-V1.0-java", // HIDL "android.hardware.boot-V1.1-java", // HIDL "android.hardware.boot-V1.2-java", // HIDL - "android.hardware.boot-V1-java", // AIDL + "android.hardware.boot-V1-java", // AIDL "android.hardware.broadcastradio-V2.0-java", // HIDL "android.hardware.broadcastradio-V1-java", // AIDL "android.hardware.health-V1.0-java", // HIDL diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java index 572e9c2a5d82..926d7a4d3ea6 100644 --- a/services/core/java/com/android/server/BootReceiver.java +++ b/services/core/java/com/android/server/BootReceiver.java @@ -62,6 +62,7 @@ import java.nio.file.Files; import java.nio.file.attribute.PosixFilePermissions; import java.util.HashMap; import java.util.Iterator; +import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -328,9 +329,11 @@ public class BootReceiver extends BroadcastReceiver { * @param tombstone path to the tombstone * @param proto whether the tombstone is stored as proto * @param processName the name of the process corresponding to the tombstone + * @param tmpFileLock the lock for reading/writing tmp files */ public static void addTombstoneToDropBox( - Context ctx, File tombstone, boolean proto, String processName) { + Context ctx, File tombstone, boolean proto, String processName, + ReentrantLock tmpFileLock) { final DropBoxManager db = ctx.getSystemService(DropBoxManager.class); if (db == null) { Slog.e(TAG, "Can't log tombstone: DropBoxManager not available"); @@ -351,39 +354,11 @@ public class BootReceiver extends BroadcastReceiver { // due to rate limiting. Do this by enclosing the proto tombsstone in a // container proto that has the dropped entry count and the proto tombstone as // bytes (to avoid the complexity of reading and writing nested protos). - - // Read the proto tombstone file as bytes. - final byte[] tombstoneBytes = Files.readAllBytes(tombstone.toPath()); - - final File tombstoneProtoWithHeaders = File.createTempFile( - tombstone.getName(), ".tmp", TOMBSTONE_TMP_DIR); - Files.setPosixFilePermissions( - tombstoneProtoWithHeaders.toPath(), - PosixFilePermissions.fromString("rw-rw----")); - - // Write the new proto container proto with headers. - ParcelFileDescriptor pfd; + tmpFileLock.lock(); try { - pfd = ParcelFileDescriptor.open(tombstoneProtoWithHeaders, MODE_READ_WRITE); - - ProtoOutputStream protoStream = new ProtoOutputStream( - pfd.getFileDescriptor()); - protoStream.write(TombstoneWithHeadersProto.TOMBSTONE, tombstoneBytes); - protoStream.write( - TombstoneWithHeadersProto.DROPPED_COUNT, - rateLimitResult.droppedCountSinceRateLimitActivated()); - protoStream.flush(); - - // Add the proto to dropbox. - db.addFile(TAG_TOMBSTONE_PROTO_WITH_HEADERS, tombstoneProtoWithHeaders, 0); - } catch (FileNotFoundException ex) { - Slog.e(TAG, "failed to open for write: " + tombstoneProtoWithHeaders, ex); - throw ex; + addAugmentedProtoToDropbox(tombstone, db, rateLimitResult); } finally { - // Remove the temporary file. - if (tombstoneProtoWithHeaders != null) { - tombstoneProtoWithHeaders.delete(); - } + tmpFileLock.unlock(); } } } else { @@ -399,6 +374,44 @@ public class BootReceiver extends BroadcastReceiver { writeTimestamps(timestamps); } + private static void addAugmentedProtoToDropbox( + File tombstone, DropBoxManager db, + DropboxRateLimiter.RateLimitResult rateLimitResult) throws IOException { + // Read the proto tombstone file as bytes. + final byte[] tombstoneBytes = Files.readAllBytes(tombstone.toPath()); + + final File tombstoneProtoWithHeaders = File.createTempFile( + tombstone.getName(), ".tmp", TOMBSTONE_TMP_DIR); + Files.setPosixFilePermissions( + tombstoneProtoWithHeaders.toPath(), + PosixFilePermissions.fromString("rw-rw----")); + + // Write the new proto container proto with headers. + try (ParcelFileDescriptor pfd = ParcelFileDescriptor.open( + tombstoneProtoWithHeaders, MODE_READ_WRITE)) { + ProtoOutputStream protoStream = + new ProtoOutputStream(pfd.getFileDescriptor()); + protoStream.write(TombstoneWithHeadersProto.TOMBSTONE, tombstoneBytes); + protoStream.write( + TombstoneWithHeadersProto.DROPPED_COUNT, + rateLimitResult.droppedCountSinceRateLimitActivated()); + protoStream.flush(); + + // Add the proto to dropbox. + db.addFile(TAG_TOMBSTONE_PROTO_WITH_HEADERS, tombstoneProtoWithHeaders, 0); + } catch (FileNotFoundException ex) { + Slog.e(TAG, "failed to open for write: " + tombstoneProtoWithHeaders, ex); + throw ex; + } catch (IOException ex) { + Slog.e(TAG, "IO exception during write: " + tombstoneProtoWithHeaders, ex); + } finally { + // Remove the temporary file and unlock the lock. + if (tombstoneProtoWithHeaders != null) { + tombstoneProtoWithHeaders.delete(); + } + } + } + private static void addLastkToDropBox( DropBoxManager db, HashMap<String, Long> timestamps, String headers, String footers, String filename, int maxSize, diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index 987507fe7f03..3aa275c8d9b8 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -1,5 +1,5 @@ -# BootReceiver -per-file BootReceiver.java = gaillard@google.com +# BootReceiver / Watchdog +per-file BootReceiver.java,Watchdog.java = gaillard@google.com # Connectivity / Networking per-file ConnectivityService.java,ConnectivityServiceInitializer.java,NetworkManagementService.java,NsdService.java,VpnManagerService.java = file:/services/core/java/com/android/server/net/OWNERS diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java index 6794f750c82d..3280afdf6703 100644 --- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java +++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java @@ -1797,8 +1797,13 @@ public class AdbDebuggingManager { mFingerprints); try { - dump.write("user_keys", AdbDebuggingManagerProto.USER_KEYS, - FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null)); + File userKeys = new File("/data/misc/adb/adb_keys"); + if (userKeys.exists()) { + dump.write("user_keys", AdbDebuggingManagerProto.USER_KEYS, + FileUtils.readTextFile(userKeys, 0, null)); + } else { + Slog.i(TAG, "No user keys on this device"); + } } catch (IOException e) { Slog.i(TAG, "Cannot read user keys", e); } diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java index 0fcec6faa0cc..c26fd5d9b798 100644 --- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java +++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java @@ -258,13 +258,6 @@ class BroadcastProcessQueue { @Nullable public BroadcastRecord enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record, int recordIndex, @NonNull BroadcastConsumer deferredStatesApplyConsumer) { - // When updateDeferredStates() has already applied a deferred state to - // all pending items, apply to this new broadcast too - if (mLastDeferredStates && record.deferUntilActive - && (record.getDeliveryState(recordIndex) == BroadcastRecord.DELIVERY_PENDING)) { - deferredStatesApplyConsumer.accept(record, recordIndex); - } - // Ignore FLAG_RECEIVER_REPLACE_PENDING if the sender specified the policy using the // BroadcastOptions delivery group APIs. if (record.isReplacePending() @@ -287,6 +280,13 @@ class BroadcastProcessQueue { // with implicit responsiveness expectations. getQueueForBroadcast(record).addLast(newBroadcastArgs); onBroadcastEnqueued(record, recordIndex); + + // When updateDeferredStates() has already applied a deferred state to + // all pending items, apply to this new broadcast too + if (mLastDeferredStates && shouldBeDeferred() + && (record.getDeliveryState(recordIndex) == BroadcastRecord.DELIVERY_PENDING)) { + deferredStatesApplyConsumer.accept(record, recordIndex); + } return null; } @@ -1144,9 +1144,6 @@ class BroadcastProcessQueue { } else if (mProcessPersistent) { mRunnableAt = runnableAt + constants.DELAY_PERSISTENT_PROC_MILLIS; mRunnableAtReason = REASON_PERSISTENT; - } else if (UserHandle.isCore(uid)) { - mRunnableAt = runnableAt; - mRunnableAtReason = REASON_CORE_UID; } else if (mCountOrdered > 0) { mRunnableAt = runnableAt; mRunnableAtReason = REASON_CONTAINS_ORDERED; @@ -1193,6 +1190,9 @@ class BroadcastProcessQueue { // is already cached, they'll be deferred on the line above mRunnableAt = runnableAt; mRunnableAtReason = REASON_CONTAINS_RESULT_TO; + } else if (UserHandle.isCore(uid)) { + mRunnableAt = runnableAt; + mRunnableAtReason = REASON_CORE_UID; } else { mRunnableAt = runnableAt + constants.DELAY_NORMAL_MILLIS; mRunnableAtReason = REASON_NORMAL; @@ -1221,32 +1221,45 @@ class BroadcastProcessQueue { } /** - * Update {@link BroadcastRecord.DELIVERY_DEFERRED} states of all our + * Update {@link BroadcastRecord#DELIVERY_DEFERRED} states of all our * pending broadcasts, when needed. */ void updateDeferredStates(@NonNull BroadcastConsumer applyConsumer, @NonNull BroadcastConsumer clearConsumer) { // When all we have pending is deferred broadcasts, and we're cached, // then we want everything to be marked deferred - final boolean wantDeferredStates = (mCountDeferred > 0) - && (mCountDeferred == mCountEnqueued) && mProcessFreezable; + final boolean wantDeferredStates = shouldBeDeferred(); if (mLastDeferredStates != wantDeferredStates) { mLastDeferredStates = wantDeferredStates; if (wantDeferredStates) { forEachMatchingBroadcast((r, i) -> { - return r.deferUntilActive - && (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_PENDING); + return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_PENDING); }, applyConsumer, false); } else { forEachMatchingBroadcast((r, i) -> { - return r.deferUntilActive - && (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); + return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); }, clearConsumer, false); } } } + void clearDeferredStates(@NonNull BroadcastConsumer clearConsumer) { + if (mLastDeferredStates) { + mLastDeferredStates = false; + forEachMatchingBroadcast((r, i) -> { + return (r.getDeliveryState(i) == BroadcastRecord.DELIVERY_DEFERRED); + }, clearConsumer, false); + } + } + + @VisibleForTesting + boolean shouldBeDeferred() { + if (mRunnableAtInvalidated) updateRunnableAt(); + return mRunnableAtReason == REASON_CACHED + || mRunnableAtReason == REASON_CACHED_INFINITE_DEFER; + } + /** * Check overall health, confirming things are in a reasonable state and * that we're not wedged. diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java index f420619db490..abec890299a3 100644 --- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java @@ -249,6 +249,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue { private static final int MSG_CHECK_HEALTH = 5; private static final int MSG_CHECK_PENDING_COLD_START_VALIDITY = 6; private static final int MSG_PROCESS_FREEZABLE_CHANGED = 7; + private static final int MSG_UID_STATE_CHANGED = 8; private void enqueueUpdateRunningList() { mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST); @@ -295,6 +296,19 @@ class BroadcastQueueModernImpl extends BroadcastQueue { } return true; } + case MSG_UID_STATE_CHANGED: { + final int uid = (int) msg.obj; + final int procState = msg.arg1; + synchronized (mService) { + if (procState == ActivityManager.PROCESS_STATE_TOP) { + mUidForeground.put(uid, true); + } else { + mUidForeground.delete(uid); + } + refreshProcessQueuesLocked(uid); + } + return true; + } } return false; }; @@ -450,6 +464,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue { break; } + // Clear the deferred state of broadcasts in this queue as we are just about to + // deliver broadcasts to this process. + queue.clearDeferredStates(mBroadcastConsumerDeferClear); + // We might not have heard about a newly running process yet, so // consider refreshing if we think we're cold updateWarmProcess(queue); @@ -672,7 +690,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue { @Override public void onProcessFreezableChangedLocked(@NonNull ProcessRecord app) { mLocalHandler.removeMessages(MSG_PROCESS_FREEZABLE_CHANGED, app); - mLocalHandler.sendMessage(mHandler.obtainMessage(MSG_PROCESS_FREEZABLE_CHANGED, app)); + mLocalHandler.obtainMessage(MSG_PROCESS_FREEZABLE_CHANGED, app).sendToTarget(); } @Override @@ -1510,12 +1528,14 @@ class BroadcastQueueModernImpl extends BroadcastQueue { r.resultExtras = null; }; - private final BroadcastConsumer mBroadcastConsumerDeferApply = (r, i) -> { + @VisibleForTesting + final BroadcastConsumer mBroadcastConsumerDeferApply = (r, i) -> { setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_DEFERRED, "mBroadcastConsumerDeferApply"); }; - private final BroadcastConsumer mBroadcastConsumerDeferClear = (r, i) -> { + @VisibleForTesting + final BroadcastConsumer mBroadcastConsumerDeferClear = (r, i) -> { setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_PENDING, "mBroadcastConsumerDeferClear"); }; @@ -1601,14 +1621,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { - synchronized (mService) { - if (procState == ActivityManager.PROCESS_STATE_TOP) { - mUidForeground.put(uid, true); - } else { - mUidForeground.delete(uid); - } - refreshProcessQueuesLocked(uid); - } + mLocalHandler.removeMessages(MSG_UID_STATE_CHANGED, uid); + mLocalHandler.obtainMessage(MSG_UID_STATE_CHANGED, procState, 0, uid) + .sendToTarget(); } }, ActivityManager.UID_OBSERVER_PROCSTATE, ActivityManager.PROCESS_STATE_TOP, "android"); diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java index 4dfd9b076354..f0dd23ce832a 100644 --- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java +++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceImpl.java @@ -221,20 +221,24 @@ public class AppOpsCheckingServiceImpl implements AppOpsCheckingServiceInterface synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid, null); if (opModes == null) { - if (mode != defaultMode) { - opModes = new SparseIntArray(); - mUidModes.put(uid, opModes); - opModes.put(op, mode); - scheduleWriteLocked(); + if (mode == defaultMode) { + return false; } + opModes = new SparseIntArray(); + mUidModes.put(uid, opModes); + opModes.put(op, mode); + scheduleWriteLocked(); } else { - if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) { + if (opModes.indexOfKey(op) >= 0) { + if (opModes.get(op) == mode) { + return false; + } + } else if (mode == defaultMode) { return false; } if (mode == defaultMode) { opModes.delete(op); if (opModes.size() <= 0) { - opModes = null; mUidModes.delete(uid); } } else { diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java index 18f24db8b307..f46586779f4c 100644 --- a/services/core/java/com/android/server/audio/SpatializerHelper.java +++ b/services/core/java/com/android/server/audio/SpatializerHelper.java @@ -965,6 +965,11 @@ public class SpatializerHelper { if (mSpat == null) { mSpatCallback = new SpatializerCallback(); mSpat = AudioSystem.getSpatializer(mSpatCallback); + if (mSpat == null) { + Log.e(TAG, "createSpat(): No Spatializer found"); + postReset(); + return; + } try { //TODO: register heatracking callback only when sensors are registered if (mIsHeadTrackingSupported) { diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java index 3c885a145315..3b18f0c76d25 100644 --- a/services/core/java/com/android/server/camera/CameraServiceProxy.java +++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java @@ -52,7 +52,6 @@ import android.hardware.display.DisplayManager; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; import android.media.AudioManager; -import android.nfc.INfcAdapter; import android.nfc.NfcAdapter; import android.nfc.NfcManager; import android.os.Binder; @@ -1252,45 +1251,19 @@ public class CameraServiceProxy extends SystemService } } - // TODO(b/303286040): Remove the raw INfcAdapter usage once |ENABLE_NFC_MAINLINE_FLAG| is - // rolled out. - private static final String NFC_SERVICE_BINDER_NAME = "nfc"; - // Flags arguments to NFC adapter to enable/disable NFC - public static final int DISABLE_POLLING_FLAGS = 0x1000; - public static final int ENABLE_POLLING_FLAGS = 0x0000; - private void setNfcReaderModeUsingINfcAdapter(boolean enablePolling) { - IBinder nfcServiceBinder = getBinderService(NFC_SERVICE_BINDER_NAME); - if (nfcServiceBinder == null) { + private void notifyNfcService(boolean enablePolling) { + NfcManager nfcManager = mContext.getSystemService(NfcManager.class); + if (nfcManager == null) { Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); return; } - INfcAdapter nfcAdapterRaw = INfcAdapter.Stub.asInterface(nfcServiceBinder); - int flags = enablePolling ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS; - if (DEBUG) Slog.v(TAG, "Setting NFC reader mode to flags " + flags); - try { - nfcAdapterRaw.setReaderMode(nfcInterfaceToken, null, flags, null); - } catch (RemoteException e) { - Slog.w(TAG, "Could not notify NFC service, remote exception: " + e); - } - } - - private void notifyNfcService(boolean enablePolling) { - if (android.nfc.Flags.enableNfcMainline()) { - NfcManager nfcManager = mContext.getSystemService(NfcManager.class); - if (nfcManager == null) { - Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); - return; - } - NfcAdapter nfcAdapter = nfcManager.getDefaultAdapter(); - if (nfcAdapter == null) { - Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); - return; - } - if (DEBUG) Slog.v(TAG, "Setting NFC reader mode. enablePolling: " + enablePolling); - nfcAdapter.setReaderMode(enablePolling); - } else { - setNfcReaderModeUsingINfcAdapter(enablePolling); + NfcAdapter nfcAdapter = nfcManager.getDefaultAdapter(); + if (nfcAdapter == null) { + Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); + return; } + if (DEBUG) Slog.v(TAG, "Setting NFC reader mode. enablePolling: " + enablePolling); + nfcAdapter.setReaderMode(enablePolling); } private static int[] toArray(Collection<Integer> c) { diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index 4b8b43134e6c..74310b52cf06 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -54,6 +54,7 @@ import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; @@ -65,7 +66,6 @@ import android.os.Parcel; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; @@ -114,8 +114,6 @@ import java.util.function.Consumer; public class ClipboardService extends SystemService { private static final String TAG = "ClipboardService"; - private static final boolean IS_EMULATOR = - SystemProperties.getBoolean("ro.boot.qemu", false); @VisibleForTesting public static final long DEFAULT_CLIPBOARD_TIMEOUT_MILLIS = 3600000; @@ -190,7 +188,7 @@ public class ClipboardService extends SystemService { mAutofillInternal = LocalServices.getService(AutofillManagerInternal.class); final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard"); mPermissionOwner = permOwner; - if (IS_EMULATOR) { + if (Build.IS_EMULATOR) { mEmulatorClipboardMonitor = new EmulatorClipboardMonitor((clip) -> { synchronized (mLock) { setPrimaryClipInternalLocked(getClipboardLocked(0, DEVICE_ID_DEFAULT), clip, diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index ec7f561bd9da..b4c39972dcaa 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -246,7 +246,7 @@ public class LockSettingsService extends ILockSettings.Stub { private static final String MIGRATED_SP_FULL = "migrated_all_users_to_sp_and_bound_keys"; private static final boolean FIX_UNLOCKED_DEVICE_REQUIRED_KEYS = - android.security.Flags.fixUnlockedDeviceRequiredKeys(); + android.security.Flags.fixUnlockedDeviceRequiredKeysV2(); // Duration that LockSettingsService will store the gatekeeper password for. This allows // multiple biometric enrollments without prompting the user to enter their password via diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java index 4bac872dbaa9..17f2fcc5b9d8 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java @@ -155,43 +155,45 @@ class LockSettingsShellCommand extends ShellCommand { try (final PrintWriter pw = getOutPrintWriter();) { pw.println("lockSettings service commands:"); pw.println(""); - pw.println("NOTE: when lock screen is set, all commands require the --old <CREDENTIAL>" - + " argument."); + pw.println("NOTE: when a secure lock screen is set, most commands require the"); + pw.println("--old <CREDENTIAL> option."); pw.println(""); pw.println(" help"); pw.println(" Prints this help text."); pw.println(""); - pw.println(" get-disabled [--old <CREDENTIAL>] [--user USER_ID]"); - pw.println(" Checks whether lock screen is disabled."); + pw.println(" get-disabled [--user USER_ID]"); + pw.println(" Prints true if the lock screen is completely disabled, i.e. set to None."); + pw.println(" Otherwise prints false."); pw.println(""); - pw.println(" set-disabled [--old <CREDENTIAL>] [--user USER_ID] <true|false>"); - pw.println(" When true, disables lock screen."); + pw.println(" set-disabled [--user USER_ID] <true|false>"); + pw.println(" Sets whether the lock screen is disabled. If the lock screen is secure, this"); + pw.println(" has no immediate effect. I.e. this can only change between Swipe and None."); pw.println(""); pw.println(" set-pattern [--old <CREDENTIAL>] [--user USER_ID] <PATTERN>"); - pw.println(" Sets the lock screen as pattern, using the given PATTERN to unlock."); + pw.println(" Sets a secure lock screen that uses the given PATTERN. PATTERN is a series"); + pw.println(" of digits 1-9 that identify the cells of the pattern."); pw.println(""); pw.println(" set-pin [--old <CREDENTIAL>] [--user USER_ID] <PIN>"); - pw.println(" Sets the lock screen as PIN, using the given PIN to unlock."); + pw.println(" Sets a secure lock screen that uses the given PIN."); pw.println(""); pw.println(" set-password [--old <CREDENTIAL>] [--user USER_ID] <PASSWORD>"); - pw.println(" Sets the lock screen as password, using the given PASSWORD to unlock."); + pw.println(" Sets a secure lock screen that uses the given PASSWORD."); pw.println(""); pw.println(" clear [--old <CREDENTIAL>] [--user USER_ID]"); - pw.println(" Clears the lock credentials."); + pw.println(" Clears the lock credential."); pw.println(""); pw.println(" verify [--old <CREDENTIAL>] [--user USER_ID]"); - pw.println(" Verifies the lock credentials."); + pw.println(" Verifies the lock credential."); pw.println(""); pw.println(" remove-cache [--user USER_ID]"); pw.println(" Removes cached unified challenge for the managed profile."); pw.println(""); pw.println(" set-resume-on-reboot-provider-package <package_name>"); - pw.println(" Sets the package name for server based resume on reboot service " - + "provider."); + pw.println(" Sets the package name for server based resume on reboot service provider."); pw.println(""); pw.println(" require-strong-auth [--user USER_ID] <reason>"); - pw.println(" Requires the strong authentication. The current supported reasons: " - + "STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN."); + pw.println(" Requires strong authentication. The current supported reasons:"); + pw.println(" STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN."); pw.println(""); } } diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java index e5616d04554d..ab0d0d2626db 100644 --- a/services/core/java/com/android/server/os/NativeTombstoneManager.java +++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java @@ -61,6 +61,7 @@ import java.util.Collections; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import java.util.concurrent.locks.ReentrantLock; /** * A class to manage native tombstones. @@ -74,6 +75,8 @@ public final class NativeTombstoneManager { private final Handler mHandler; private final TombstoneWatcher mWatcher; + private final ReentrantLock mTmpFileLock = new ReentrantLock(); + private final Object mLock = new Object(); @GuardedBy("mLock") @@ -112,7 +115,12 @@ public final class NativeTombstoneManager { // Clean up temporary files if they made it this far (e.g. if system server crashes). if (filename.endsWith(".tmp")) { - path.delete(); + mTmpFileLock.lock(); + try { + path.delete(); + } finally { + mTmpFileLock.unlock(); + } return; } @@ -128,7 +136,7 @@ public final class NativeTombstoneManager { if (parsedTombstone.isPresent()) { processName = parsedTombstone.get().getProcessName(); } - BootReceiver.addTombstoneToDropBox(mContext, path, isProtoFile, processName); + BootReceiver.addTombstoneToDropBox(mContext, path, isProtoFile, processName, mTmpFileLock); } private Optional<TombstoneFile> handleProtoTombstone(File path, boolean addToList) { diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java index fcaaa90dbc8a..c33af9b28b62 100644 --- a/services/core/java/com/android/server/pm/DumpHelper.java +++ b/services/core/java/com/android/server/pm/DumpHelper.java @@ -160,7 +160,7 @@ final class DumpHelper { pkg = snapshot.resolveInternalPackageName(pkg, PackageManager.VERSION_CODE_HIGHEST); - pw.println(mPermissionManager.checkPermission(perm, pkg, user)); + pw.println(mPermissionManager.checkPermission(pkg, perm, user)); return; } else if ("l".equals(cmd) || "libraries".equals(cmd)) { dumpState.setDump(DumpState.DUMP_LIBS); diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java index 6d58d3401675..8adb5661ad1d 100644 --- a/services/core/java/com/android/server/pm/UserDataPreparer.java +++ b/services/core/java/com/android/server/pm/UserDataPreparer.java @@ -23,10 +23,10 @@ import android.content.pm.UserInfo; import android.os.Environment; import android.os.FileUtils; import android.os.RecoverySystem; -import android.os.storage.StorageManager; -import android.os.storage.VolumeInfo; import android.os.SystemProperties; import android.os.UserHandle; +import android.os.storage.StorageManager; +import android.os.storage.VolumeInfo; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -35,6 +35,7 @@ import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.utils.Slogf; import java.io.File; import java.io.IOException; @@ -43,7 +44,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.Set; /** * Helper class for preparing and destroying user storage @@ -65,31 +65,37 @@ class UserDataPreparer { /** * Prepare storage areas for given user on all mounted devices. */ - void prepareUserData(int userId, int userSerial, int flags) { + void prepareUserData(UserInfo userInfo, int flags) { synchronized (mInstallLock) { final StorageManager storage = mContext.getSystemService(StorageManager.class); /* * Internal storage must be prepared before adoptable storage, since the user's volume * keys are stored in their internal storage. */ - prepareUserDataLI(null /* internal storage */, userId, userSerial, flags, true); + prepareUserDataLI(null /* internal storage */, userInfo, flags, true); for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { final String volumeUuid = vol.getFsUuid(); if (volumeUuid != null) { - prepareUserDataLI(volumeUuid, userId, userSerial, flags, true); + prepareUserDataLI(volumeUuid, userInfo, flags, true); } } } } - private void prepareUserDataLI(String volumeUuid, int userId, int userSerial, int flags, + private void prepareUserDataLI(String volumeUuid, UserInfo userInfo, int flags, boolean allowRecover) { - // Prepare storage and verify that serial numbers are consistent; if - // there's a mismatch we need to destroy to avoid leaking data + final int userId = userInfo.id; + final int userSerial = userInfo.serialNumber; final StorageManager storage = mContext.getSystemService(StorageManager.class); + final boolean isNewUser = userInfo.lastLoggedInTime == 0; + Slogf.d(TAG, "Preparing user data; volumeUuid=%s, userId=%d, flags=0x%x, isNewUser=%s", + volumeUuid, userId, flags, isNewUser); try { + // Prepare CE and/or DE storage. storage.prepareUserStorage(volumeUuid, userId, userSerial, flags); + // Ensure that the data directories of a removed user with the same ID are not being + // reused. New users must get fresh data directories, to avoid leaking data. if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) { enforceSerialNumber(getDataUserDeDirectory(volumeUuid, userId), userSerial); if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) { @@ -103,9 +109,10 @@ class UserDataPreparer { } } + // Prepare the app data directories. mInstaller.createUserData(volumeUuid, userId, userSerial, flags); - // CE storage is available after they are prepared. + // If applicable, record that the system user's CE storage has been prepared. if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && (userId == UserHandle.USER_SYSTEM)) { String propertyName = "sys.user." + userId + ".ce_available"; @@ -113,20 +120,31 @@ class UserDataPreparer { SystemProperties.set(propertyName, "true"); } } catch (Exception e) { - logCriticalInfo(Log.WARN, "Destroying user " + userId + " on volume " + volumeUuid - + " because we failed to prepare: " + e); - destroyUserDataLI(volumeUuid, userId, flags); - + // Failed to prepare user data. For new users, specifically users that haven't ever + // been unlocked, destroy the user data, and try again (if not already retried). This + // might be effective at resolving some errors, such as stale directories from a reused + // user ID. Don't auto-destroy data for existing users, since issues with existing + // users might be fixable via an OTA without having to wipe the user's data. + if (isNewUser) { + logCriticalInfo(Log.ERROR, "Destroying user " + userId + " on volume " + volumeUuid + + " because we failed to prepare: " + e); + destroyUserDataLI(volumeUuid, userId, flags); + } else { + logCriticalInfo(Log.ERROR, "Failed to prepare user " + userId + " on volume " + + volumeUuid + ": " + e); + } if (allowRecover) { // Try one last time; if we fail again we're really in trouble - prepareUserDataLI(volumeUuid, userId, userSerial, - flags | StorageManager.FLAG_STORAGE_DE, false); + prepareUserDataLI(volumeUuid, userInfo, flags | StorageManager.FLAG_STORAGE_DE, + false); } else { + // If internal storage of the system user fails to prepare on first boot, then + // things are *really* broken, so we might as well reboot to recovery right away. try { Log.wtf(TAG, "prepareUserData failed for user " + userId, e); - if (userId == UserHandle.USER_SYSTEM) { + if (isNewUser && userId == UserHandle.USER_SYSTEM && volumeUuid == null) { RecoverySystem.rebootPromptAndWipeUserData(mContext, - "prepareUserData failed for system user"); + "failed to prepare internal storage for system user"); } } catch (IOException e2) { throw new RuntimeException("error rebooting into recovery", e2); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index e11e226054e3..68148482c68a 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -4914,8 +4914,7 @@ public class UserManagerService extends IUserManager.Stub { // unlocked. We do this to ensure that CE storage isn't prepared before the CE key is // saved to disk. This also matches what is done for user 0. t.traceBegin("prepareUserData"); - mUserDataPreparer.prepareUserData(userId, userInfo.serialNumber, - StorageManager.FLAG_STORAGE_DE); + mUserDataPreparer.prepareUserData(userInfo, StorageManager.FLAG_STORAGE_DE); t.traceEnd(); t.traceBegin("LSS.createNewUser"); @@ -6199,12 +6198,11 @@ public class UserManagerService extends IUserManager.Stub { } TimingsTraceAndSlog t = new TimingsTraceAndSlog(); t.traceBegin("onBeforeStartUser-" + userId); - final int userSerial = userInfo.serialNumber; // Migrate only if build fingerprints mismatch boolean migrateAppsData = !PackagePartitions.FINGERPRINT.equals( userInfo.lastLoggedInFingerprint); t.traceBegin("prepareUserData"); - mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE); + mUserDataPreparer.prepareUserData(userInfo, StorageManager.FLAG_STORAGE_DE); t.traceEnd(); t.traceBegin("reconcileAppsData"); getPackageManagerInternal().reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE, @@ -6230,14 +6228,13 @@ public class UserManagerService extends IUserManager.Stub { if (userInfo == null) { return; } - final int userSerial = userInfo.serialNumber; // Migrate only if build fingerprints mismatch boolean migrateAppsData = !PackagePartitions.FINGERPRINT.equals( userInfo.lastLoggedInFingerprint); final TimingsTraceAndSlog t = new TimingsTraceAndSlog(); t.traceBegin("prepareUserData-" + userId); - mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_CE); + mUserDataPreparer.prepareUserData(userInfo, StorageManager.FLAG_STORAGE_CE); t.traceEnd(); StorageManagerInternal smInternal = LocalServices.getService(StorageManagerInternal.class); diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java index d0c346a63889..57f4a5ddb2bd 100644 --- a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java +++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java @@ -337,7 +337,8 @@ public class ArtStatsLogUtils { 0, // deprecated, used to be durationIncludingSleepMs 0, // optimizedPackagesCount 0, // packagesDependingOnBootClasspathCount - 0); // totalPackagesCount + 0, // totalPackagesCount + ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__PASS__PASS_UNKNOWN); } } } diff --git a/services/core/java/com/android/server/power/TEST_MAPPING b/services/core/java/com/android/server/power/TEST_MAPPING index cf1bfc3b555f..fbfe291b1659 100644 --- a/services/core/java/com/android/server/power/TEST_MAPPING +++ b/services/core/java/com/android/server/power/TEST_MAPPING @@ -20,6 +20,7 @@ "name": "FrameworksServicesTests", "options": [ {"include-filter": "com.android.server.power"}, + {"exclude-filter": "com.android.server.power.BatteryStatsTests"}, {"exclude-annotation": "android.platform.test.annotations.FlakyTest"}, {"exclude-annotation": "androidx.test.filters.FlakyTest"} ] @@ -38,7 +39,8 @@ { "name": "FrameworksServicesTests", "options": [ - {"include-filter": "com.android.server.power"} + {"include-filter": "com.android.server.power"}, + {"exclude-filter": "com.android.server.power.BatteryStatsTests"} ] } ] diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java index 27329e20bc8d..5dff9ef5076e 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -8203,18 +8203,18 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("mBsi") private void ensureMultiStateCounters(long timestampMs) { - if (mProcStateTimeMs != null) { - return; + if (mProcStateTimeMs == null) { + mProcStateTimeMs = + new TimeInFreqMultiStateCounter(mBsi.mOnBatteryTimeBase, + PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(), + timestampMs); + } + if (mProcStateScreenOffTimeMs == null) { + mProcStateScreenOffTimeMs = + new TimeInFreqMultiStateCounter(mBsi.mOnBatteryScreenOffTimeBase, + PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(), + timestampMs); } - - mProcStateTimeMs = - new TimeInFreqMultiStateCounter(mBsi.mOnBatteryTimeBase, - PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(), - timestampMs); - mProcStateScreenOffTimeMs = - new TimeInFreqMultiStateCounter(mBsi.mOnBatteryScreenOffTimeBase, - PROC_STATE_TIME_COUNTER_STATE_COUNT, mBsi.getCpuFreqCount(), - timestampMs); } @GuardedBy("mBsi") diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 635e11be3a16..24c971c678c0 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -829,7 +829,7 @@ public class TrustManagerService extends SystemService { } final boolean trusted; - if (android.security.Flags.fixUnlockedDeviceRequiredKeys()) { + if (android.security.Flags.fixUnlockedDeviceRequiredKeysV2()) { trusted = getUserTrustStateInner(id) == TrustState.TRUSTED; } else { trusted = aggregateIsTrusted(id); @@ -1647,8 +1647,22 @@ public class TrustManagerService extends SystemService { fout.printf(" User \"%s\" (id=%d, flags=%#x)", user.name, user.id, user.flags); if (!user.supportsSwitchToByUser()) { - fout.println("(managed profile)"); - fout.println(" disabled because switching to this user is not possible."); + final boolean locked; + if (user.isProfile()) { + if (mLockPatternUtils.isSeparateProfileChallengeEnabled(user.id)) { + fout.print(" (profile with separate challenge)"); + locked = isDeviceLockedInner(user.id); + } else { + fout.print(" (profile with unified challenge)"); + locked = isDeviceLockedInner(resolveProfileParent(user.id)); + } + } else { + fout.println(" (user that cannot be switched to)"); + locked = isDeviceLockedInner(user.id); + } + fout.println(": deviceLocked=" + dumpBool(locked)); + fout.println( + " Trust agents disabled because switching to this user is not possible."); return; } if (isCurrent) { diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 6d560e4b762b..f2346e6eab5d 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -6135,6 +6135,7 @@ class Task extends TaskFragment { // Avoid resuming activities on secondary displays since we don't want bubble // activities to be resumed while bubble is still collapsed. // TODO(b/113840485): Having keyguard going away state for secondary displays. + && display != null && display.isDefaultDisplay) { return false; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 06978a5338ea..0a5b9eb270a1 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3276,7 +3276,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // just kill it. And if it is a window of foreground activity, the activity can be // restarted automatically if needed. Slog.w(TAG, "Exception thrown during dispatchAppVisibility " + this, e); - android.os.Process.killProcess(mSession.mPid); + if (android.os.Process.getUidForPid(mSession.mPid) == mSession.mUid) { + android.os.Process.killProcess(mSession.mPid); + } } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 3610542c7caf..f1f5d8359f42 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1451,8 +1451,6 @@ public final class SystemServer implements Dumpable { boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice", false); - boolean isEmulator = SystemProperties.get("ro.boot.qemu").equals("1"); - boolean isWatch = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WATCH); @@ -2261,7 +2259,7 @@ public final class SystemServer implements Dumpable { if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST) || mPackageManager.hasSystemFeature( PackageManager.FEATURE_USB_ACCESSORY) - || isEmulator) { + || Build.IS_EMULATOR) { // Manage USB host and device support t.traceBegin("StartUsbService"); mSystemServiceManager.startService(USB_SERVICE_CLASS); diff --git a/services/proguard.flags b/services/proguard.flags index 84f2a52a2b22..88561b460b05 100644 --- a/services/proguard.flags +++ b/services/proguard.flags @@ -50,6 +50,11 @@ -keep,allowoptimization,allowaccessmodification class com.android.net.module.util.* { *; } -keep,allowoptimization,allowaccessmodification public class com.android.server.net.IpConfigStore { *; } -keep,allowoptimization,allowaccessmodification public class com.android.server.net.BaseNetworkObserver { *; } +-keep,allowoptimization,allowaccessmodification class com.android.server.display.feature.DisplayManagerFlags { *; } +-keep,allowoptimization,allowaccessmodification class android.app.admin.flags.FeatureFlagsImpl { *; } +-keep,allowoptimization,allowaccessmodification class com.android.server.input.NativeInputManagerService$NativeImpl { *; } +-keep,allowoptimization,allowaccessmodification class com.android.server.ThreadPriorityBooster { *; } +-keep,allowaccessmodification class android.app.admin.flags.Flags { *; } # Referenced via CarServiceHelperService in car-frameworks-service (avoid removing) -keep public class com.android.server.utils.Slogf { *; } @@ -102,9 +107,6 @@ -keep,allowoptimization,allowaccessmodification class com.android.server.input.InputManagerService { <methods>; } --keep,allowoptimization,allowaccessmodification class com.android.server.input.NativeInputManagerService$NativeImpl { - <methods>; -} -keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbHostManager { *** usbDeviceRemoved(...); *** usbDeviceAdded(...); diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java index afbe352ad676..e5be4d9aa755 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java @@ -21,6 +21,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -56,6 +58,7 @@ public class UserDataPreparerTest { private static final int TEST_USER_SERIAL = 1000; private static final int TEST_USER_ID = 10; + private static final UserInfo TEST_USER = new UserInfo(); private TestUserDataPreparer mUserDataPreparer; @@ -72,6 +75,8 @@ public class UserDataPreparerTest { @Before public void setup() { + TEST_USER.id = TEST_USER_ID; + TEST_USER.serialNumber = TEST_USER_SERIAL; Context ctx = InstrumentationRegistry.getContext(); FileUtils.deleteContents(ctx.getCacheDir()); mInstallLock = new Object(); @@ -92,8 +97,7 @@ public class UserDataPreparerTest { userDeDir.mkdirs(); File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID); systemDeDir.mkdirs(); - mUserDataPreparer - .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_DE); + mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_DE); verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE)); verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID), @@ -110,8 +114,7 @@ public class UserDataPreparerTest { userCeDir.mkdirs(); File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID); systemCeDir.mkdirs(); - mUserDataPreparer - .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_CE); + mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE)); verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID), @@ -123,6 +126,28 @@ public class UserDataPreparerTest { } @Test + public void testPrepareUserData_forNewUser_destroysOnFailure() throws Exception { + TEST_USER.lastLoggedInTime = 0; + doThrow(new IllegalStateException("expected exception for test")).when(mStorageManagerMock) + .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), eq(TEST_USER_SERIAL), + eq(StorageManager.FLAG_STORAGE_CE)); + mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); + verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID), + eq(StorageManager.FLAG_STORAGE_CE)); + } + + @Test + public void testPrepareUserData_forExistingUser_doesNotDestroyOnFailure() throws Exception { + TEST_USER.lastLoggedInTime = System.currentTimeMillis(); + doThrow(new IllegalStateException("expected exception for test")).when(mStorageManagerMock) + .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), eq(TEST_USER_SERIAL), + eq(StorageManager.FLAG_STORAGE_CE)); + mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); + verify(mStorageManagerMock, never()).destroyUserStorage(isNull(String.class), + eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); + } + + @Test public void testDestroyUserData_De_DoesNotDestroyCe() throws Exception { // Add file in CE storage File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java new file mode 100644 index 000000000000..a0beb174dc94 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.am; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.annotation.NonNull; +import android.app.usage.UsageStatsManagerInternal; +import android.content.ComponentName; +import android.content.Context; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManagerInternal; +import android.content.pm.ResolveInfo; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.TestLooperManager; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.SparseArray; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.server.AlarmManagerInternal; +import com.android.server.DropBoxManagerInternal; +import com.android.server.LocalServices; +import com.android.server.appop.AppOpsService; +import com.android.server.wm.ActivityTaskManagerService; + +import org.junit.Rule; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.File; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; + +public abstract class BaseBroadcastQueueTest { + + static final int USER_GUEST = 11; + + static final String PACKAGE_ANDROID = "android"; + static final String PACKAGE_PHONE = "com.android.phone"; + static final String PACKAGE_RED = "com.example.red"; + static final String PACKAGE_GREEN = "com.example.green"; + static final String PACKAGE_BLUE = "com.example.blue"; + static final String PACKAGE_YELLOW = "com.example.yellow"; + static final String PACKAGE_ORANGE = "com.example.orange"; + + static final String PROCESS_SYSTEM = "system"; + + static final String CLASS_RED = "com.example.red.Red"; + static final String CLASS_GREEN = "com.example.green.Green"; + static final String CLASS_BLUE = "com.example.blue.Blue"; + static final String CLASS_YELLOW = "com.example.yellow.Yellow"; + static final String CLASS_ORANGE = "com.example.orange.Orange"; + + static final BroadcastProcessQueue.BroadcastPredicate BROADCAST_PREDICATE_ANY = + (r, i) -> true; + + @Rule + public final ApplicationExitInfoTest.ServiceThreadRule + mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule(); + + @Mock + AppOpsService mAppOpsService; + @Mock + PackageManagerInternal mPackageManagerInt; + @Mock + UsageStatsManagerInternal mUsageStatsManagerInt; + @Mock + DropBoxManagerInternal mDropBoxManagerInt; + @Mock + AlarmManagerInternal mAlarmManagerInt; + @Mock + ProcessList mProcessList; + + Context mContext; + ActivityManagerService mAms; + BroadcastConstants mConstants; + BroadcastSkipPolicy mSkipPolicy; + HandlerThread mHandlerThread; + TestLooperManager mLooper; + AtomicInteger mNextPid; + + /** + * Map from PID to registered registered runtime receivers. + */ + SparseArray<ReceiverList> mRegisteredReceivers = new SparseArray<>(); + + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + mHandlerThread = new HandlerThread(getTag()); + mHandlerThread.start(); + // Pause all event processing until a test chooses to resume + mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() + .acquireLooperManager(mHandlerThread.getLooper())); + mNextPid = new AtomicInteger(100); + + LocalServices.removeServiceForTest(DropBoxManagerInternal.class); + LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt); + LocalServices.removeServiceForTest(PackageManagerInternal.class); + LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt); + LocalServices.removeServiceForTest(AlarmManagerInternal.class); + LocalServices.addService(AlarmManagerInternal.class, mAlarmManagerInt); + doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent(); + doNothing().when(mPackageManagerInt).setPackageStoppedState(any(), anyBoolean(), anyInt()); + doAnswer((invocation) -> { + return getUidForPackage(invocation.getArgument(0)); + }).when(mPackageManagerInt).getPackageUid(any(), anyLong(), eq(UserHandle.USER_SYSTEM)); + + final ActivityManagerService realAms = new ActivityManagerService( + new TestInjector(mContext), mServiceThreadRule.getThread()); + realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext); + realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper()); + realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal()); + realAms.mOomAdjuster = spy(realAms.mOomAdjuster); + realAms.mPackageManagerInt = mPackageManagerInt; + realAms.mUsageStatsService = mUsageStatsManagerInt; + realAms.mProcessesReady = true; + mAms = spy(realAms); + + mSkipPolicy = spy(new BroadcastSkipPolicy(mAms)); + doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any()); + doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any()); + + mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS); + } + + public void tearDown() throws Exception { + mHandlerThread.quit(); + } + + static int getUidForPackage(@NonNull String packageName) { + switch (packageName) { + case PACKAGE_ANDROID: return android.os.Process.SYSTEM_UID; + case PACKAGE_PHONE: return android.os.Process.PHONE_UID; + case PACKAGE_RED: return android.os.Process.FIRST_APPLICATION_UID + 1; + case PACKAGE_GREEN: return android.os.Process.FIRST_APPLICATION_UID + 2; + case PACKAGE_BLUE: return android.os.Process.FIRST_APPLICATION_UID + 3; + case PACKAGE_YELLOW: return android.os.Process.FIRST_APPLICATION_UID + 4; + case PACKAGE_ORANGE: return android.os.Process.FIRST_APPLICATION_UID + 5; + default: throw new IllegalArgumentException(); + } + } + + static int getUidForPackage(@NonNull String packageName, int userId) { + return UserHandle.getUid(userId, getUidForPackage(packageName)); + } + + private class TestInjector extends ActivityManagerService.Injector { + TestInjector(Context context) { + super(context); + } + + @Override + public AppOpsService getAppOpsService(File recentAccessesFile, File storageFile, + Handler handler) { + return mAppOpsService; + } + + @Override + public Handler getUiHandler(ActivityManagerService service) { + return mHandlerThread.getThreadHandler(); + } + + @Override + public ProcessList getProcessList(ActivityManagerService service) { + return mProcessList; + } + } + + abstract String getTag(); + + static ApplicationInfo makeApplicationInfo(String packageName) { + return makeApplicationInfo(packageName, packageName, UserHandle.USER_SYSTEM); + } + + static ApplicationInfo makeApplicationInfo(String packageName, String processName, int userId) { + final ApplicationInfo ai = new ApplicationInfo(); + ai.packageName = packageName; + ai.processName = processName; + ai.uid = getUidForPackage(packageName, userId); + return ai; + } + + static ResolveInfo withPriority(ResolveInfo info, int priority) { + info.priority = priority; + return info; + } + + static BroadcastFilter withPriority(BroadcastFilter filter, int priority) { + filter.setPriority(priority); + return filter; + } + + static ResolveInfo makeManifestReceiver(String packageName, String name) { + return makeManifestReceiver(packageName, name, UserHandle.USER_SYSTEM); + } + + static ResolveInfo makeManifestReceiver(String packageName, String name, int userId) { + return makeManifestReceiver(packageName, packageName, name, userId); + } + + static ResolveInfo makeManifestReceiver(String packageName, String processName, + String name, int userId) { + final ResolveInfo ri = new ResolveInfo(); + ri.activityInfo = new ActivityInfo(); + ri.activityInfo.packageName = packageName; + ri.activityInfo.processName = processName; + ri.activityInfo.name = name; + ri.activityInfo.applicationInfo = makeApplicationInfo(packageName, processName, userId); + return ri; + } + + BroadcastFilter makeRegisteredReceiver(ProcessRecord app) { + return makeRegisteredReceiver(app, 0); + } + + BroadcastFilter makeRegisteredReceiver(ProcessRecord app, int priority) { + final ReceiverList receiverList = mRegisteredReceivers.get(app.getPid()); + return makeRegisteredReceiver(receiverList, priority); + } + + static BroadcastFilter makeRegisteredReceiver(ReceiverList receiverList, int priority) { + final IntentFilter filter = new IntentFilter(); + filter.setPriority(priority); + final BroadcastFilter res = new BroadcastFilter(filter, receiverList, + receiverList.app.info.packageName, null, null, null, receiverList.uid, + receiverList.userId, false, false, true); + receiverList.add(res); + return res; + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java index ff04728912ef..2378416f8bd0 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java @@ -31,17 +31,6 @@ import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_ORDERE import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_PRIORITIZED; import static com.android.server.am.BroadcastProcessQueue.insertIntoRunnableList; import static com.android.server.am.BroadcastProcessQueue.removeFromRunnableList; -import static com.android.server.am.BroadcastQueueTest.CLASS_BLUE; -import static com.android.server.am.BroadcastQueueTest.CLASS_GREEN; -import static com.android.server.am.BroadcastQueueTest.CLASS_RED; -import static com.android.server.am.BroadcastQueueTest.CLASS_YELLOW; -import static com.android.server.am.BroadcastQueueTest.PACKAGE_BLUE; -import static com.android.server.am.BroadcastQueueTest.PACKAGE_GREEN; -import static com.android.server.am.BroadcastQueueTest.PACKAGE_RED; -import static com.android.server.am.BroadcastQueueTest.PACKAGE_YELLOW; -import static com.android.server.am.BroadcastQueueTest.getUidForPackage; -import static com.android.server.am.BroadcastQueueTest.makeManifestReceiver; -import static com.android.server.am.BroadcastQueueTest.withPriority; import static com.android.server.am.BroadcastRecord.isReceiverEquals; import static com.google.common.truth.Truth.assertThat; @@ -74,17 +63,15 @@ import android.appwidget.AppWidgetManager; import android.content.IIntentReceiver; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; import android.media.AudioManager; import android.os.Bundle; import android.os.BundleMerger; import android.os.DropBoxManager; -import android.os.HandlerThread; import android.os.Process; import android.os.SystemClock; -import android.os.TestLooperManager; import android.os.UserHandle; -import android.provider.Settings; import android.util.IndentingPrintWriter; import android.util.Pair; @@ -108,11 +95,12 @@ import java.util.List; import java.util.Objects; @SmallTest -public final class BroadcastQueueModernImplTest { +public final class BroadcastQueueModernImplTest extends BaseBroadcastQueueTest { + private static final String TAG = "BroadcastQueueModernImplTest"; + private static final int TEST_UID = android.os.Process.FIRST_APPLICATION_UID; private static final int TEST_UID2 = android.os.Process.FIRST_APPLICATION_UID + 1; - @Mock ActivityManagerService mAms; @Mock ProcessRecord mProcess; @Mock BroadcastProcessQueue mQueue1; @@ -120,11 +108,6 @@ public final class BroadcastQueueModernImplTest { @Mock BroadcastProcessQueue mQueue3; @Mock BroadcastProcessQueue mQueue4; - HandlerThread mHandlerThread; - TestLooperManager mLooper; - - BroadcastConstants mConstants; - private BroadcastSkipPolicy mSkipPolicy; BroadcastQueueModernImpl mImpl; BroadcastProcessQueue mHead; @@ -136,22 +119,12 @@ public final class BroadcastQueueModernImplTest { @Before public void setUp() throws Exception { - mHandlerThread = new HandlerThread(getClass().getSimpleName()); - mHandlerThread.start(); - - // Pause all event processing until a test chooses to resume - mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() - .acquireLooperManager(mHandlerThread.getLooper())); + super.setUp(); - mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS); mConstants.DELAY_URGENT_MILLIS = -120_000; mConstants.DELAY_NORMAL_MILLIS = 10_000; mConstants.DELAY_CACHED_MILLIS = 120_000; - mSkipPolicy = spy(new BroadcastSkipPolicy(mAms)); - doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any()); - doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any()); - final BroadcastHistory emptyHistory = new BroadcastHistory(mConstants) { public void addBroadcastToHistoryLocked(BroadcastRecord original) { // Ignored @@ -169,7 +142,12 @@ public final class BroadcastQueueModernImplTest { @After public void tearDown() throws Exception { - mHandlerThread.quit(); + super.tearDown(); + } + + @Override + public String getTag() { + return TAG; } /** @@ -225,11 +203,6 @@ public final class BroadcastQueueModernImplTest { List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)), false); } - private BroadcastRecord makeOrderedBroadcastRecord(Intent intent) { - return makeBroadcastRecord(intent, BroadcastOptions.makeBasic(), - List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)), true); - } - private BroadcastRecord makeBroadcastRecord(Intent intent, List receivers) { return makeBroadcastRecord(intent, BroadcastOptions.makeBasic(), receivers, false); } @@ -246,8 +219,8 @@ public final class BroadcastQueueModernImplTest { private BroadcastRecord makeBroadcastRecord(Intent intent, BroadcastOptions options, List receivers, IIntentReceiver resultTo, boolean ordered) { - return new BroadcastRecord(mImpl, intent, mProcess, PACKAGE_RED, null, 21, 42, false, null, - null, null, null, AppOpsManager.OP_NONE, options, receivers, null, resultTo, + return new BroadcastRecord(mImpl, intent, mProcess, PACKAGE_RED, null, 21, TEST_UID, false, + null, null, null, null, AppOpsManager.OP_NONE, options, receivers, null, resultTo, Activity.RESULT_OK, null, null, ordered, false, false, UserHandle.USER_SYSTEM, BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN); } @@ -259,12 +232,12 @@ public final class BroadcastQueueModernImplTest { private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue, BroadcastRecord record, int recordIndex, long enqueueTime) { - queue.enqueueOrReplaceBroadcast(record, recordIndex, (r, i) -> { - throw new UnsupportedOperationException(); - }); record.enqueueTime = enqueueTime; record.enqueueRealTime = enqueueTime; record.enqueueClockTime = enqueueTime; + queue.enqueueOrReplaceBroadcast(record, recordIndex, (r, i) -> { + throw new UnsupportedOperationException(); + }); } @Test @@ -419,6 +392,7 @@ public final class BroadcastQueueModernImplTest { assertFalse(queue.isRunnable()); assertEquals(BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER, queue.getRunnableAtReason()); + assertTrue(queue.shouldBeDeferred()); assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); } @@ -445,6 +419,7 @@ public final class BroadcastQueueModernImplTest { assertThat(cachedRunnableAt).isGreaterThan(notCachedRunnableAt); assertTrue(queue.isRunnable()); assertEquals(BroadcastProcessQueue.REASON_CACHED, queue.getRunnableAtReason()); + assertTrue(queue.shouldBeDeferred()); assertEquals(ProcessList.SCHED_GROUP_UNDEFINED, queue.getPreferredSchedulingGroupLocked()); } @@ -526,11 +501,13 @@ public final class BroadcastQueueModernImplTest { queue.invalidateRunnableAt(); assertThat(queue.getRunnableAt()).isGreaterThan(airplaneRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); mConstants.MAX_PENDING_BROADCASTS = 1; queue.invalidateRunnableAt(); assertThat(queue.getRunnableAt()).isAtMost(airplaneRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_MAX_PENDING, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); } @Test @@ -549,10 +526,12 @@ public final class BroadcastQueueModernImplTest { queue.setProcessAndUidState(mProcess, true, false); assertThat(queue.getRunnableAt()).isLessThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_FOREGROUND, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); queue.setProcessAndUidState(mProcess, false, false); assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); } @Test @@ -570,6 +549,7 @@ public final class BroadcastQueueModernImplTest { assertThat(queue.getRunnableAt()).isLessThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_TOP_PROCESS, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); doReturn(ActivityManager.PROCESS_STATE_SERVICE).when(mProcess).getSetProcState(); queue.setProcessAndUidState(mProcess, false, false); @@ -580,6 +560,7 @@ public final class BroadcastQueueModernImplTest { List.of(makeMockRegisteredReceiver())), 0); assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); } @Test @@ -594,16 +575,19 @@ public final class BroadcastQueueModernImplTest { assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); doReturn(true).when(mProcess).isPersistent(); queue.setProcessAndUidState(mProcess, false, false); assertThat(queue.getRunnableAt()).isLessThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_PERSISTENT, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); doReturn(false).when(mProcess).isPersistent(); queue.setProcessAndUidState(mProcess, false, false); assertThat(queue.getRunnableAt()).isGreaterThan(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_NORMAL, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); } @Test @@ -618,6 +602,31 @@ public final class BroadcastQueueModernImplTest { assertThat(queue.getRunnableAt()).isEqualTo(timeTickRecord.enqueueTime); assertEquals(BroadcastProcessQueue.REASON_CORE_UID, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); + } + + @Test + public void testRunnableAt_freezableCoreUid() { + final BroadcastProcessQueue queue = new BroadcastProcessQueue(mConstants, + "com.android.bluetooth", Process.BLUETOOTH_UID); + + // Mark the process as freezable + queue.setProcessAndUidState(mProcess, false, true); + final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); + final BroadcastOptions options = BroadcastOptions.makeWithDeferUntilActive(true); + final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, options, + List.of(makeMockRegisteredReceiver()), false); + enqueueOrReplaceBroadcast(queue, timeTickRecord, 0); + + assertEquals(Long.MAX_VALUE, queue.getRunnableAt()); + assertEquals(BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER, + queue.getRunnableAtReason()); + assertTrue(queue.shouldBeDeferred()); + + queue.setProcessAndUidState(mProcess, false, false); + assertThat(queue.getRunnableAt()).isEqualTo(timeTickRecord.enqueueTime); + assertEquals(BroadcastProcessQueue.REASON_CORE_UID, queue.getRunnableAtReason()); + assertFalse(queue.shouldBeDeferred()); } /** @@ -1553,6 +1562,216 @@ public final class BroadcastQueueModernImplTest { verifyPendingRecords(redQueue, List.of(userPresent, timeTick)); } + @Test + public void testDeliveryDeferredForCached() throws Exception { + final ProcessRecord greenProcess = makeProcessRecord(makeApplicationInfo(PACKAGE_GREEN)); + final ProcessRecord redProcess = makeProcessRecord(makeApplicationInfo(PACKAGE_RED)); + + final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); + final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, + List.of(makeRegisteredReceiver(greenProcess, 0))); + + final Intent batteryChanged = new Intent(Intent.ACTION_BATTERY_CHANGED); + final BroadcastOptions optionsBatteryChanged = + BroadcastOptions.makeWithDeferUntilActive(true); + final BroadcastRecord batteryChangedRecord = makeBroadcastRecord(batteryChanged, + optionsBatteryChanged, + List.of(makeRegisteredReceiver(greenProcess, 10), + makeRegisteredReceiver(redProcess, 0)), + false /* ordered */); + + mImpl.enqueueBroadcastLocked(timeTickRecord); + mImpl.enqueueBroadcastLocked(batteryChangedRecord); + + final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN, + getUidForPackage(PACKAGE_GREEN)); + final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED, + getUidForPackage(PACKAGE_RED)); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, greenQueue.getRunnableAtReason()); + assertFalse(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_BLOCKED, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // Simulate process state change + greenQueue.setProcessAndUidState(greenProcess, false /* uidForeground */, + true /* processFreezable */); + greenQueue.updateDeferredStates(mImpl.mBroadcastConsumerDeferApply, + mImpl.mBroadcastConsumerDeferClear); + + assertEquals(BroadcastProcessQueue.REASON_CACHED, greenQueue.getRunnableAtReason()); + assertTrue(greenQueue.shouldBeDeferred()); + // Once the broadcasts to green process are deferred, broadcasts to red process + // shouldn't be blocked anymore. + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // All broadcasts to green process should be deferred. + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_DEFERRED, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + + final Intent packageChanged = new Intent(Intent.ACTION_PACKAGE_CHANGED); + final BroadcastRecord packageChangedRecord = makeBroadcastRecord(packageChanged, + List.of(makeRegisteredReceiver(greenProcess, 0))); + mImpl.enqueueBroadcastLocked(packageChangedRecord); + + assertEquals(BroadcastProcessQueue.REASON_CACHED, greenQueue.getRunnableAtReason()); + assertTrue(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // All broadcasts to the green process, including the newly enqueued one, should be + // deferred. + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_DEFERRED, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + + // Simulate process state change + greenQueue.setProcessAndUidState(greenProcess, false /* uidForeground */, + false /* processFreezable */); + greenQueue.updateDeferredStates(mImpl.mBroadcastConsumerDeferApply, + mImpl.mBroadcastConsumerDeferClear); + + assertEquals(BroadcastProcessQueue.REASON_NORMAL, greenQueue.getRunnableAtReason()); + assertFalse(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + } + + @Test + public void testDeliveryDeferredForCached_withInfiniteDeferred() throws Exception { + final ProcessRecord greenProcess = makeProcessRecord(makeApplicationInfo(PACKAGE_GREEN)); + final ProcessRecord redProcess = makeProcessRecord(makeApplicationInfo(PACKAGE_RED)); + + final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); + final BroadcastOptions optionsTimeTick = BroadcastOptions.makeWithDeferUntilActive(true); + final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick, optionsTimeTick, + List.of(makeRegisteredReceiver(greenProcess, 0)), false /* ordered */); + + final Intent batteryChanged = new Intent(Intent.ACTION_BATTERY_CHANGED); + final BroadcastOptions optionsBatteryChanged = + BroadcastOptions.makeWithDeferUntilActive(true); + final BroadcastRecord batteryChangedRecord = makeBroadcastRecord(batteryChanged, + optionsBatteryChanged, + List.of(makeRegisteredReceiver(greenProcess, 10), + makeRegisteredReceiver(redProcess, 0)), + false /* ordered */); + + mImpl.enqueueBroadcastLocked(timeTickRecord); + mImpl.enqueueBroadcastLocked(batteryChangedRecord); + + final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN, + getUidForPackage(PACKAGE_GREEN)); + final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED, + getUidForPackage(PACKAGE_RED)); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, greenQueue.getRunnableAtReason()); + assertFalse(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_BLOCKED, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // Simulate process state change + greenQueue.setProcessAndUidState(greenProcess, false /* uidForeground */, + true /* processFreezable */); + greenQueue.updateDeferredStates(mImpl.mBroadcastConsumerDeferApply, + mImpl.mBroadcastConsumerDeferClear); + + assertEquals(BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER, + greenQueue.getRunnableAtReason()); + assertTrue(greenQueue.shouldBeDeferred()); + // Once the broadcasts to green process are deferred, broadcasts to red process + // shouldn't be blocked anymore. + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // All broadcasts to green process should be deferred. + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_DEFERRED, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + + final Intent packageChanged = new Intent(Intent.ACTION_PACKAGE_CHANGED); + final BroadcastOptions optionsPackageChanged = + BroadcastOptions.makeWithDeferUntilActive(true); + final BroadcastRecord packageChangedRecord = makeBroadcastRecord(packageChanged, + optionsPackageChanged, + List.of(makeRegisteredReceiver(greenProcess, 0)), false /* ordered */); + mImpl.enqueueBroadcastLocked(packageChangedRecord); + + assertEquals(BroadcastProcessQueue.REASON_CACHED_INFINITE_DEFER, + greenQueue.getRunnableAtReason()); + assertTrue(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + // All broadcasts to the green process, including the newly enqueued one, should be + // deferred. + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_DEFERRED, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + + // Simulate process state change + greenQueue.setProcessAndUidState(greenProcess, false /* uidForeground */, + false /* processFreezable */); + greenQueue.updateDeferredStates(mImpl.mBroadcastConsumerDeferApply, + mImpl.mBroadcastConsumerDeferClear); + + assertEquals(BroadcastProcessQueue.REASON_NORMAL, greenQueue.getRunnableAtReason()); + assertFalse(greenQueue.shouldBeDeferred()); + assertEquals(BroadcastProcessQueue.REASON_NORMAL, redQueue.getRunnableAtReason()); + assertFalse(redQueue.shouldBeDeferred()); + + greenQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + redQueue.forEachMatchingBroadcast(BROADCAST_PREDICATE_ANY, (r, i) -> { + assertEquals("Unexpected state for " + r, + BroadcastRecord.DELIVERY_PENDING, r.getDeliveryState(i)); + }, false /* andRemove */); + } + + // TODO: Reuse BroadcastQueueTest.makeActiveProcessRecord() + private ProcessRecord makeProcessRecord(ApplicationInfo info) { + final ProcessRecord r = spy(new ProcessRecord(mAms, info, info.processName, info.uid)); + r.setPid(mNextPid.incrementAndGet()); + return r; + } + + BroadcastFilter makeRegisteredReceiver(ProcessRecord app, int priority) { + final IIntentReceiver receiver = mock(IIntentReceiver.class); + final ReceiverList receiverList = new ReceiverList(mAms, app, app.getPid(), app.info.uid, + UserHandle.getUserId(app.info.uid), receiver); + return makeRegisteredReceiver(receiverList, priority); + } + private Intent createPackageChangedIntent(int uid, List<String> componentNameList) { final Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED); packageChangedIntent.putExtra(Intent.EXTRA_UID, uid); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java index 73eb237fa9e7..e91472670c2d 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java @@ -62,58 +62,36 @@ import android.app.BroadcastOptions; import android.app.IApplicationThread; import android.app.UidObserver; import android.app.usage.UsageEvents.Event; -import android.app.usage.UsageStatsManagerInternal; import android.content.ComponentName; -import android.content.Context; import android.content.IIntentReceiver; import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; -import android.content.pm.ResolveInfo; import android.os.Binder; import android.os.Bundle; import android.os.DeadObjectException; -import android.os.Handler; -import android.os.HandlerThread; import android.os.IBinder; import android.os.PowerExemptionManager; import android.os.SystemClock; -import android.os.TestLooperManager; import android.os.UserHandle; -import android.provider.Settings; import android.util.Log; import android.util.Pair; -import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import androidx.test.filters.MediumTest; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.server.AlarmManagerInternal; -import com.android.server.DropBoxManagerInternal; -import com.android.server.LocalServices; -import com.android.server.am.ActivityManagerService.Injector; -import com.android.server.appop.AppOpsService; -import com.android.server.wm.ActivityTaskManagerService; - import org.junit.After; import org.junit.Assume; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.mockito.ArgumentMatcher; import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.verification.VerificationMode; -import java.io.File; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.Writer; @@ -125,7 +103,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; import java.util.function.UnaryOperator; @@ -135,13 +113,9 @@ import java.util.function.UnaryOperator; @MediumTest @RunWith(Parameterized.class) @SuppressWarnings("GuardedBy") -public class BroadcastQueueTest { +public class BroadcastQueueTest extends BaseBroadcastQueueTest { private static final String TAG = "BroadcastQueueTest"; - @Rule - public final ApplicationExitInfoTest.ServiceThreadRule - mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule(); - private final Impl mImpl; private enum Impl { @@ -149,30 +123,8 @@ public class BroadcastQueueTest { MODERN, } - private Context mContext; - private HandlerThread mHandlerThread; - private TestLooperManager mLooper; - private AtomicInteger mNextPid; - - @Mock - private AppOpsService mAppOpsService; - @Mock - private ProcessList mProcessList; - @Mock - private DropBoxManagerInternal mDropBoxManagerInt; - @Mock - private PackageManagerInternal mPackageManagerInt; - @Mock - private UsageStatsManagerInternal mUsageStatsManagerInt; - @Mock - private AlarmManagerInternal mAlarmManagerInt; - - private ActivityManagerService mAms; private BroadcastQueue mQueue; - BroadcastConstants mConstants; - private BroadcastSkipPolicy mSkipPolicy; private UidObserver mUidObserver; - private UidObserver mUidCachedStateObserver; /** * Desired behavior of the next @@ -182,11 +134,6 @@ public class BroadcastQueueTest { ProcessStartBehavior.SUCCESS); /** - * Map from PID to registered registered runtime receivers. - */ - private SparseArray<ReceiverList> mRegisteredReceivers = new SparseArray<>(); - - /** * Collection of all active processes during current test run. */ private List<ProcessRecord> mActiveProcesses = new ArrayList<>(); @@ -207,41 +154,8 @@ public class BroadcastQueueTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + super.setUp(); - mHandlerThread = new HandlerThread(TAG); - mHandlerThread.start(); - - // Pause all event processing until a test chooses to resume - mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() - .acquireLooperManager(mHandlerThread.getLooper())); - - mNextPid = new AtomicInteger(100); - - LocalServices.removeServiceForTest(DropBoxManagerInternal.class); - LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt); - LocalServices.removeServiceForTest(PackageManagerInternal.class); - LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt); - LocalServices.removeServiceForTest(AlarmManagerInternal.class); - LocalServices.addService(AlarmManagerInternal.class, mAlarmManagerInt); - doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent(); - doNothing().when(mPackageManagerInt).setPackageStoppedState(any(), anyBoolean(), anyInt()); - doAnswer((invocation) -> { - return getUidForPackage(invocation.getArgument(0)); - }).when(mPackageManagerInt).getPackageUid(any(), anyLong(), eq(UserHandle.USER_SYSTEM)); - - final ActivityManagerService realAms = new ActivityManagerService( - new TestInjector(mContext), mServiceThreadRule.getThread()); - realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext); - realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper()); - realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal()); - realAms.mOomAdjuster = spy(realAms.mOomAdjuster); - realAms.mPackageManagerInt = mPackageManagerInt; - realAms.mUsageStatsService = mUsageStatsManagerInt; - realAms.mProcessesReady = true; - mAms = spy(realAms); doAnswer((invocation) -> { Log.v(TAG, "Intercepting startProcessLocked() for " + Arrays.toString(invocation.getArguments())); @@ -320,21 +234,11 @@ public class BroadcastQueueTest { return null; }).when(mAms).registerUidObserver(any(), anyInt(), eq(ActivityManager.PROCESS_STATE_TOP), any()); - doAnswer((invocation) -> { - mUidCachedStateObserver = invocation.getArgument(0); - return null; - }).when(mAms).registerUidObserver(any(), anyInt(), - eq(ActivityManager.PROCESS_STATE_LAST_ACTIVITY), any()); - mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS); - mConstants.TIMEOUT = 100; + mConstants.TIMEOUT = 200; mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT = 0; mConstants.PENDING_COLD_START_CHECK_INTERVAL_MILLIS = 500; - mSkipPolicy = spy(new BroadcastSkipPolicy(mAms)); - doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any()); - doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any()); - final BroadcastHistory emptyHistory = new BroadcastHistory(mConstants) { public void addBroadcastToHistoryLocked(BroadcastRecord original) { // Ignored @@ -357,7 +261,7 @@ public class BroadcastQueueTest { @After public void tearDown() throws Exception { - mHandlerThread.quit(); + super.tearDown(); // Verify that all processes have finished handling broadcasts for (ProcessRecord app : mActiveProcesses) { @@ -368,26 +272,9 @@ public class BroadcastQueueTest { } } - private class TestInjector extends Injector { - TestInjector(Context context) { - super(context); - } - - @Override - public AppOpsService getAppOpsService(File recentAccessesFile, File storageFile, - Handler handler) { - return mAppOpsService; - } - - @Override - public Handler getUiHandler(ActivityManagerService service) { - return mHandlerThread.getThreadHandler(); - } - - @Override - public ProcessList getProcessList(ActivityManagerService service) { - return mProcessList; - } + @Override + public String getTag() { + return TAG; } private enum ProcessStartBehavior { @@ -533,62 +420,6 @@ public class BroadcastQueueTest { return Pair.create(app.getPid(), intent.getAction()); } - static ApplicationInfo makeApplicationInfo(String packageName) { - return makeApplicationInfo(packageName, packageName, UserHandle.USER_SYSTEM); - } - - static ApplicationInfo makeApplicationInfo(String packageName, String processName, int userId) { - final ApplicationInfo ai = new ApplicationInfo(); - ai.packageName = packageName; - ai.processName = processName; - ai.uid = getUidForPackage(packageName, userId); - return ai; - } - - static ResolveInfo withPriority(ResolveInfo info, int priority) { - info.priority = priority; - return info; - } - - static BroadcastFilter withPriority(BroadcastFilter filter, int priority) { - filter.setPriority(priority); - return filter; - } - - static ResolveInfo makeManifestReceiver(String packageName, String name) { - return makeManifestReceiver(packageName, name, UserHandle.USER_SYSTEM); - } - - static ResolveInfo makeManifestReceiver(String packageName, String name, int userId) { - return makeManifestReceiver(packageName, packageName, name, userId); - } - - static ResolveInfo makeManifestReceiver(String packageName, String processName, String name, - int userId) { - final ResolveInfo ri = new ResolveInfo(); - ri.activityInfo = new ActivityInfo(); - ri.activityInfo.packageName = packageName; - ri.activityInfo.processName = processName; - ri.activityInfo.name = name; - ri.activityInfo.applicationInfo = makeApplicationInfo(packageName, processName, userId); - return ri; - } - - private BroadcastFilter makeRegisteredReceiver(ProcessRecord app) { - return makeRegisteredReceiver(app, 0); - } - - private BroadcastFilter makeRegisteredReceiver(ProcessRecord app, int priority) { - final ReceiverList receiverList = mRegisteredReceivers.get(app.getPid()); - final IntentFilter filter = new IntentFilter(); - filter.setPriority(priority); - final BroadcastFilter res = new BroadcastFilter(filter, receiverList, - receiverList.app.info.packageName, null, null, null, receiverList.uid, - receiverList.userId, false, false, true); - receiverList.add(res); - return res; - } - private BroadcastRecord makeBroadcastRecord(Intent intent, ProcessRecord callerApp, List<Object> receivers) { return makeBroadcastRecord(intent, callerApp, BroadcastOptions.makeBasic(), @@ -707,6 +538,9 @@ public class BroadcastQueueTest { private void waitForIdle() throws Exception { mLooper.release(); mQueue.waitForIdle(LOG_WRITER_INFO); + final CountDownLatch latch = new CountDownLatch(1); + mHandlerThread.getThreadHandler().post(latch::countDown); + latch.await(); mLooper = Objects.requireNonNull(InstrumentationRegistry.getInstrumentation() .acquireLooperManager(mHandlerThread.getLooper())); } @@ -772,41 +606,6 @@ public class BroadcastQueueTest { eq(userId), anyInt(), anyInt(), any()); } - static final int USER_GUEST = 11; - - static final String PACKAGE_ANDROID = "android"; - static final String PACKAGE_PHONE = "com.android.phone"; - static final String PACKAGE_RED = "com.example.red"; - static final String PACKAGE_GREEN = "com.example.green"; - static final String PACKAGE_BLUE = "com.example.blue"; - static final String PACKAGE_YELLOW = "com.example.yellow"; - static final String PACKAGE_ORANGE = "com.example.orange"; - - static final String PROCESS_SYSTEM = "system"; - - static final String CLASS_RED = "com.example.red.Red"; - static final String CLASS_GREEN = "com.example.green.Green"; - static final String CLASS_BLUE = "com.example.blue.Blue"; - static final String CLASS_YELLOW = "com.example.yellow.Yellow"; - static final String CLASS_ORANGE = "com.example.orange.Orange"; - - static int getUidForPackage(@NonNull String packageName) { - switch (packageName) { - case PACKAGE_ANDROID: return android.os.Process.SYSTEM_UID; - case PACKAGE_PHONE: return android.os.Process.PHONE_UID; - case PACKAGE_RED: return android.os.Process.FIRST_APPLICATION_UID + 1; - case PACKAGE_GREEN: return android.os.Process.FIRST_APPLICATION_UID + 2; - case PACKAGE_BLUE: return android.os.Process.FIRST_APPLICATION_UID + 3; - case PACKAGE_YELLOW: return android.os.Process.FIRST_APPLICATION_UID + 4; - case PACKAGE_ORANGE: return android.os.Process.FIRST_APPLICATION_UID + 5; - default: throw new IllegalArgumentException(); - } - } - - static int getUidForPackage(@NonNull String packageName, int userId) { - return UserHandle.getUid(userId, getUidForPackage(packageName)); - } - /** * Baseline verification of common debugging infrastructure, mostly to make * sure it doesn't crash. @@ -2342,6 +2141,7 @@ public class BroadcastQueueTest { mUidObserver.onUidStateChanged(receiverGreenApp.info.uid, ActivityManager.PROCESS_STATE_TOP, 0, ActivityManager.PROCESS_CAPABILITY_NONE); + waitForIdle(); final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); @@ -2375,6 +2175,7 @@ public class BroadcastQueueTest { mUidObserver.onUidStateChanged(receiverGreenApp.info.uid, ActivityManager.PROCESS_STATE_TOP, 0, ActivityManager.PROCESS_CAPABILITY_NONE); + waitForIdle(); final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK); diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index c152a41c8694..25bd14f63573 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -2951,11 +2951,11 @@ public final class Call { for(String key : bundle.keySet()) { if (key != null) { - final Object value = bundle.get(key); - final Object newValue = newBundle.get(key); if (!newBundle.containsKey(key)) { return false; } + final Object value = bundle.get(key); + final Object newValue = newBundle.get(key); if (value instanceof Bundle && newValue instanceof Bundle) { if (!areBundlesEqual((Bundle) value, (Bundle) newValue)) { return false; diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index 80c7a21dc11b..db3a992b9c7b 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -789,6 +789,15 @@ </intent-filter> </activity> + <activity android:name="BackdropBlurActivity" + android:label="RenderEffect/BackdropBlur" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="com.android.test.hwui.TEST"/> + </intent-filter> + </activity> + <activity android:name="BlurActivity" android:label="RenderEffect/Blur" android:exported="true"> diff --git a/tests/HwAccelerationTest/res/drawable/robot_repeated.xml b/tests/HwAccelerationTest/res/drawable/robot_repeated.xml new file mode 100644 index 000000000000..bbb15b71c3a5 --- /dev/null +++ b/tests/HwAccelerationTest/res/drawable/robot_repeated.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<bitmap xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/robot" + android:tileMode="repeat" android:gravity="fill" />
\ No newline at end of file diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BackdropBlurActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/BackdropBlurActivity.java new file mode 100644 index 000000000000..8086b29df7cd --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/BackdropBlurActivity.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.hwui; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.Outline; +import android.graphics.RenderEffect; +import android.graphics.Shader; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewOutlineProvider; +import android.view.animation.DecelerateInterpolator; +import android.widget.FrameLayout; +import android.widget.ScrollView; + +@SuppressWarnings({"UnusedDeclaration"}) +public class BackdropBlurActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final ScrollView scrollView = new ScrollView(this); + final FrameLayout innerFrame = new FrameLayout(this); + final View backgroundView = new View(this); + backgroundView.setBackgroundResource(R.drawable.robot_repeated); + innerFrame.addView(backgroundView, ViewGroup.LayoutParams.MATCH_PARENT, 10000); + scrollView.addView(innerFrame, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + + final FrameLayout contentView = new FrameLayout(this); + contentView.addView(scrollView, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + contentView.addView(new BackdropBlurView(this), 300, 300); + setContentView(contentView); + } + + private static class BackdropBlurView extends View { + private final float mBlurRadius = 60f; + private final float mSaturation = 1.8f; + + private float mDownOffsetX; + private float mDownOffsetY; + + BackdropBlurView(Context c) { + super(c); + + // init RenderEffect. + final RenderEffect blurEffect = RenderEffect.createBlurEffect( + mBlurRadius, mBlurRadius, + null, Shader.TileMode.MIRROR // TileMode.MIRROR is better for blur. + ); + + final ColorMatrix colorMatrix = new ColorMatrix(); + colorMatrix.setSaturation(mSaturation); + final RenderEffect effect = RenderEffect.createColorFilterEffect( + new ColorMatrixColorFilter(colorMatrix), blurEffect + ); + setBackdropRenderEffect(effect); + + // clip to a round outline. + setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View v, Outline outline) { + outline.setOval(0, 0, v.getWidth(), v.getHeight()); + } + }); + setClipToOutline(true); + + animate().setInterpolator(new DecelerateInterpolator(2.0f)); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + canvas.drawColor(0x99F0F0F0); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + mDownOffsetX = event.getRawX() - getTranslationX(); + mDownOffsetY = event.getRawY() - getTranslationY(); + animate().scaleX(1.5f).scaleY(1.5f).start(); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + animate().scaleX(1f).scaleY(1f).start(); + break; + case MotionEvent.ACTION_MOVE: + setTranslationX(event.getRawX() - mDownOffsetX); + setTranslationY(event.getRawY() - mDownOffsetY); + break; + } + return true; + } + } +} diff --git a/tests/NetworkSecurityConfigTest/OWNERS b/tests/NetworkSecurityConfigTest/OWNERS index aa87958f1d53..90e1bed9fb26 100644 --- a/tests/NetworkSecurityConfigTest/OWNERS +++ b/tests/NetworkSecurityConfigTest/OWNERS @@ -1 +1,2 @@ include /services/core/java/com/android/server/net/OWNERS +include /core/java/android/security/net/OWNERS diff --git a/tests/SmokeTestApps/Android.bp b/tests/SmokeTestApps/Android.bp index 3505fe1c4afb..38ee8ac99747 100644 --- a/tests/SmokeTestApps/Android.bp +++ b/tests/SmokeTestApps/Android.bp @@ -11,4 +11,7 @@ android_test { name: "SmokeTestTriggerApps", srcs: ["src/**/*.java"], sdk_version: "current", + errorprone: { + enabled: false, + }, } diff --git a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt index 1dfd5c06167b..d0e56268a27d 100644 --- a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt +++ b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt @@ -93,7 +93,7 @@ class GrantAndRevokeTrustTest { } @Test - @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) + @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) fun grantCannotActivelyUnlockDevice() { // On automotive, trust agents can actively unlock the device. assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) @@ -120,7 +120,7 @@ class GrantAndRevokeTrustTest { } @Test - @RequiresFlagsDisabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) + @RequiresFlagsDisabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2) fun grantCouldCauseWrongDeviceLockedStateDueToBug() { // On automotive, trust agents can actively unlock the device. assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) diff --git a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt index 5a8f82827253..01218099f34c 100644 --- a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt +++ b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt @@ -36,7 +36,8 @@ import org.junit.runners.model.Statement class LockStateTrackingRule : TestRule { private val context: Context = getApplicationContext() private val windowManager = checkNotNull(WindowManagerGlobal.getWindowManagerService()) - private val keyguardManager = context.getSystemService(KeyguardManager::class.java) as KeyguardManager + private val keyguardManager = + context.getSystemService(KeyguardManager::class.java) as KeyguardManager @Volatile lateinit var trustState: TrustState private set @@ -63,7 +64,7 @@ class LockStateTrackingRule : TestRule { wait("not trusted") { trustState.trusted == false } } - // TODO(b/299298338) remove this when removing FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS + // TODO(b/299298338) remove this when removing FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS_V2 fun assertUnlockedButNotReally() { wait("device unlocked") { !keyguardManager.isDeviceLocked } wait("not trusted") { trustState.trusted == false } @@ -87,7 +88,7 @@ class LockStateTrackingRule : TestRule { trustGrantedMessages: MutableList<String> ) { Log.d(TAG, "Device became trusted=$enabled") - trustState = trustState.copy(trusted=enabled) + trustState = trustState.copy(trusted = enabled) } } |