From c7e66035bb5ca97ad025c5bf6c07b6d8ebddabe2 Mon Sep 17 00:00:00 2001 From: Sudheer Shanka Date: Wed, 2 Nov 2022 10:50:41 -0700 Subject: [PATCH] Deliver DEVICE_IDLE_MODE_CHANGED broadcasts as non-ordered. They are currently being sent as ordered in order to receive the finish callback. Since the modern broadcast queue supports a finish callback with the need for the broadcasts to be ordered, don't send these broadcasts as ordered anymore. Bug: 256597397 Bug: 256597171 Bug: 253226131 Test: treehugger Change-Id: I00a0dec0df99892b2d0f4a023efcc965a2061379 --- .../android/server/DeviceIdleController.java | 17 +++++++++++------ .../android/app/ActivityManagerInternal.java | 15 +++++++++++++++ .../server/am/ActivityManagerService.java | 15 +++++++++++++++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index bd475e9dd7348..e3bd5acd7bc7d 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -31,6 +31,7 @@ import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.content.BroadcastReceiver; import android.content.Context; +import android.content.IIntentReceiver; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; @@ -740,8 +741,10 @@ public class DeviceIdleController extends SystemService } }; - private final BroadcastReceiver mIdleStartedDoneReceiver = new BroadcastReceiver() { - @Override public void onReceive(Context context, Intent intent) { + private final IIntentReceiver mIdleStartedDoneReceiver = new IIntentReceiver.Stub() { + @Override + public void performReceive(Intent intent, int resultCode, String data, Bundle extras, + boolean ordered, boolean sticky, int sendingUser) { // When coming out of a deep idle, we will add in some delay before we allow // the system to settle down and finish the maintenance window. This is // to give a chance for any pending work to be scheduled. @@ -1816,13 +1819,15 @@ public class DeviceIdleController extends SystemService } if (deepChanged) { incActiveIdleOps(); - getContext().sendOrderedBroadcastAsUser(mIdleIntent, UserHandle.ALL, - null, mIdleStartedDoneReceiver, null, 0, null, null); + mLocalActivityManager.broadcastIntentWithCallback(mIdleIntent, + mIdleStartedDoneReceiver, null, UserHandle.USER_ALL, + null, null, null); } if (lightChanged) { incActiveIdleOps(); - getContext().sendOrderedBroadcastAsUser(mLightIdleIntent, UserHandle.ALL, - null, mIdleStartedDoneReceiver, null, 0, null, null); + mLocalActivityManager.broadcastIntentWithCallback(mLightIdleIntent, + mIdleStartedDoneReceiver, null, UserHandle.USER_ALL, + null, null, null); } // Always start with one active op for the message being sent here. // Now we are done! diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 4b1b0a260e27b..ad02df24adc20 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -639,6 +639,8 @@ public abstract class ActivityManagerInternal { * using the rules of package visibility. Returns extras with legitimate package info that the * receiver is able to access, or {@code null} if none of the packages is visible to the * receiver. + * @param serialized Specifies whether or not the broadcast should be delivered to the + * receivers in a serial order. * * @see com.android.server.am.ActivityManagerService#broadcastIntentWithFeature( * IApplicationThread, String, Intent, String, IIntentReceiver, int, String, Bundle, @@ -651,6 +653,19 @@ public abstract class ActivityManagerInternal { @Nullable BiFunction filterExtrasForReceiver, @Nullable Bundle bOptions); + /** + * Variant of + * {@link #broadcastIntent(Intent, IIntentReceiver, String[], boolean, int, int[], BiFunction, Bundle)} + * that allows sender to receive a finish callback once the broadcast delivery is completed, + * but provides no ordering guarantee for how the broadcast is delivered to receivers. + */ + public abstract int broadcastIntentWithCallback(Intent intent, + IIntentReceiver resultTo, + String[] requiredPermissions, + int userId, int[] appIdAllowList, + @Nullable BiFunction filterExtrasForReceiver, + @Nullable Bundle bOptions); + /** * Add uid to the ActivityManagerService PendingStartActivityUids list. * @param uid uid diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 2cf3462554f58..17ca571798fd0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -17327,6 +17327,21 @@ public class ActivityManagerService extends IActivityManager.Stub } + @Override + public int broadcastIntentWithCallback(Intent intent, + IIntentReceiver resultTo, + String[] requiredPermissions, + int userId, int[] appIdAllowList, + @Nullable BiFunction filterExtrasForReceiver, + @Nullable Bundle bOptions) { + // Sending broadcasts with a finish callback without the need for the broadcasts + // delivery to be serialized is only supported by modern queue. So, when modern + // queue is disabled, we continue to send broadcasts in a serialized fashion. + final boolean serialized = !isModernQueueEnabled(); + return broadcastIntent(intent, resultTo, requiredPermissions, serialized, userId, + appIdAllowList, filterExtrasForReceiver, bOptions); + } + @Override public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId,