From 5a4b0acc74c8ede0a11dae79b89f94f609b77efa Mon Sep 17 00:00:00 2001 From: Lee Shombert Date: Wed, 7 Dec 2022 10:02:45 -0800 Subject: [PATCH] Support multiple broadcast receivers Bug: 253906553 Allow system server to schedule multiple broadcast receivers in a process with a single AIDL call. The AIDL call takes an array of receivers. Each element is either a manifest receiver or a registered receiver. This is a do-no-harm commit. It adds the AIDL call but does not use it. The client side processes the list by forwarding the elements to the scheduleReceiver() and scheduleRegisteredReceiver() handlers, as appropriate. Test: atest * FrameworksCoreTests Change-Id: Ib61f8170badcb2fb24a466dc10c607baeeeb4dc3 --- core/java/android/app/ActivityThread.java | 21 +++++++ core/java/android/app/IApplicationThread.aidl | 4 ++ core/java/android/app/ReceiverInfo.aidl | 60 +++++++++++++++++++ .../am/SameProcessApplicationThread.java | 18 ++++++ 4 files changed, 103 insertions(+) create mode 100644 core/java/android/app/ReceiverInfo.aidl diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 31cbe28334f91..a4c9f8c88eda8 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1020,6 +1020,12 @@ public final class ActivityThread extends ClientTransactionHandler int flags; } + // A list of receivers and an index into the receiver to be processed next. + static final class ReceiverList { + List receivers; + int index; + } + private class ApplicationThread extends IApplicationThread.Stub { private static final String DB_CONNECTION_INFO_HEADER = " %8s %8s %14s %5s %5s %5s %s"; private static final String DB_CONNECTION_INFO_FORMAT = " %8s %8s %14s %5d %5d %5d %s"; @@ -1036,6 +1042,21 @@ public final class ActivityThread extends ClientTransactionHandler sendMessage(H.RECEIVER, r); } + public final void scheduleReceiverList(List info) throws RemoteException { + for (int i = 0; i < info.size(); i++) { + ReceiverInfo r = info.get(i); + if (r.registered) { + scheduleRegisteredReceiver(r.receiver, r.intent, + r.resultCode, r.data, r.extras, r.ordered, r.sticky, + r.sendingUser, r.processState); + } else { + scheduleReceiver(r.intent, r.activityInfo, r.compatInfo, + r.resultCode, r.data, r.extras, r.sync, + r.sendingUser, r.processState); + } + } + } + public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode, int userId, @BackupDestination int backupDestination) { CreateBackupAgentData d = new CreateBackupAgentData(); diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index 595c7f7ab0085..3984fee192037 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -20,6 +20,7 @@ import android.app.ContentProviderHolder; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; +import android.app.ReceiverInfo; import android.app.ResultInfo; import android.app.servertransaction.ClientTransaction; import android.content.AutofillOptions; @@ -66,6 +67,9 @@ oneway interface IApplicationThread { in CompatibilityInfo compatInfo, int resultCode, in String data, in Bundle extras, boolean sync, int sendingUser, int processState); + + void scheduleReceiverList(in List info); + @UnsupportedAppUsage void scheduleCreateService(IBinder token, in ServiceInfo info, in CompatibilityInfo compatInfo, int processState); diff --git a/core/java/android/app/ReceiverInfo.aidl b/core/java/android/app/ReceiverInfo.aidl new file mode 100644 index 0000000000000..d90eee704a7e5 --- /dev/null +++ b/core/java/android/app/ReceiverInfo.aidl @@ -0,0 +1,60 @@ +/** + * 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 android.app; + +import android.content.IIntentReceiver; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.CompatibilityInfo; +import android.os.Bundle; + +/** + * Collect the information needed for manifest and registered receivers into a single structure + * that can be the element of a list. All fields are already parcelable. + * @hide + */ +parcelable ReceiverInfo { + /** + * Fields common to registered and manifest receivers. + */ + Intent intent; + String data; + Bundle extras; + int sendingUser; + int processState; + int resultCode; + + /** + * True if this instance represents a registered receiver and false if this instance + * represents a manifest receiver. + */ + boolean registered; + + /** + * Fields used only for registered receivers. + */ + IIntentReceiver receiver; + boolean ordered; + boolean sticky; + + /** + * Fields used only for manifest receivers. + */ + ActivityInfo activityInfo; + CompatibilityInfo compatInfo; + boolean sync; +} diff --git a/services/core/java/com/android/server/am/SameProcessApplicationThread.java b/services/core/java/com/android/server/am/SameProcessApplicationThread.java index a3c011188539d..62fd6e9d551b8 100644 --- a/services/core/java/com/android/server/am/SameProcessApplicationThread.java +++ b/services/core/java/com/android/server/am/SameProcessApplicationThread.java @@ -18,6 +18,7 @@ package com.android.server.am; import android.annotation.NonNull; import android.app.IApplicationThread; +import android.app.ReceiverInfo; import android.content.IIntentReceiver; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -26,6 +27,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; +import java.util.List; import java.util.Objects; /** @@ -70,4 +72,20 @@ public class SameProcessApplicationThread extends IApplicationThread.Default { } }); } + + @Override + public void scheduleReceiverList(List info) { + for (int i = 0; i < info.size(); i++) { + ReceiverInfo r = info.get(i); + if (r.registered) { + scheduleRegisteredReceiver(r.receiver, r.intent, + r.resultCode, r.data, r.extras, r.ordered, r.sticky, + r.sendingUser, r.processState); + } else { + scheduleReceiver(r.intent, r.activityInfo, r.compatInfo, + r.resultCode, r.data, r.extras, r.sync, + r.sendingUser, r.processState); + } + } + } }