• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.am;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.UptimeMillisLong;
22 import android.content.ContentResolver;
23 import android.content.Intent;
24 import android.os.Bundle;
25 import android.os.DropBoxManager;
26 import android.os.Handler;
27 import android.os.Trace;
28 import android.util.Slog;
29 import android.util.proto.ProtoOutputStream;
30 
31 import com.android.internal.annotations.GuardedBy;
32 import com.android.server.DropBoxManagerInternal;
33 import com.android.server.LocalServices;
34 
35 import java.io.FileDescriptor;
36 import java.io.FileOutputStream;
37 import java.io.PrintWriter;
38 import java.util.Objects;
39 import java.util.Set;
40 
41 /**
42  * Queue of broadcast intents and associated bookkeeping.
43  */
44 public abstract class BroadcastQueue {
45     public static final String TAG = "BroadcastQueue";
46     public static final String TAG_DUMP = "broadcast_queue_dump";
47 
48     final @NonNull ActivityManagerService mService;
49     final @NonNull Handler mHandler;
50     final @NonNull BroadcastSkipPolicy mSkipPolicy;
51     final @NonNull BroadcastHistory mHistory;
52 
BroadcastQueue(@onNull ActivityManagerService service, @NonNull Handler handler, @NonNull BroadcastSkipPolicy skipPolicy, @NonNull BroadcastHistory history)53     BroadcastQueue(@NonNull ActivityManagerService service, @NonNull Handler handler,
54             @NonNull BroadcastSkipPolicy skipPolicy,
55             @NonNull BroadcastHistory history) {
56         mService = Objects.requireNonNull(service);
57         mHandler = Objects.requireNonNull(handler);
58         mSkipPolicy = Objects.requireNonNull(skipPolicy);
59         mHistory = Objects.requireNonNull(history);
60     }
61 
logw(@onNull String msg)62     static void logw(@NonNull String msg) {
63         Slog.w(TAG, msg);
64     }
65 
logv(@onNull String msg)66     static void logv(@NonNull String msg) {
67         Slog.v(TAG, msg);
68     }
69 
checkState(boolean expression, @NonNull String msg)70     static void checkState(boolean expression, @NonNull String msg) {
71         if (!expression) {
72             throw new IllegalStateException(msg);
73         }
74     }
75 
traceBegin(@onNull String methodName)76     static int traceBegin(@NonNull String methodName) {
77         final int cookie = methodName.hashCode();
78         Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
79                 TAG, methodName, cookie);
80         return cookie;
81     }
82 
traceEnd(int cookie)83     static void traceEnd(int cookie) {
84         Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
85                 TAG, cookie);
86     }
87 
start(@onNull ContentResolver resolver)88     public abstract void start(@NonNull ContentResolver resolver);
89 
90     /**
91      * Return the preferred scheduling group for the given process, typically
92      * influenced by a broadcast being actively dispatched.
93      *
94      * @return scheduling group such as {@link ProcessList#SCHED_GROUP_DEFAULT},
95      *         otherwise {@link ProcessList#SCHED_GROUP_UNDEFINED} if this queue
96      *         has no opinion.
97      */
98     @GuardedBy("mService")
getPreferredSchedulingGroupLocked(@onNull ProcessRecord app)99     public abstract int getPreferredSchedulingGroupLocked(@NonNull ProcessRecord app);
100 
101     /**
102      * Enqueue the given broadcast to be eventually dispatched.
103      * <p>
104      * Callers must populate {@link BroadcastRecord#receivers} with the relevant
105      * targets before invoking this method.
106      * <p>
107      * When {@link Intent#FLAG_RECEIVER_REPLACE_PENDING} is set, this method
108      * internally handles replacement of any matching broadcasts.
109      */
110     @GuardedBy("mService")
enqueueBroadcastLocked(@onNull BroadcastRecord r)111     public abstract void enqueueBroadcastLocked(@NonNull BroadcastRecord r);
112 
113     /**
114      * Signal delivered back from the given process to indicate that it's
115      * finished processing the current broadcast being dispatched to it.
116      * <p>
117      * If this signal isn't delivered back in a timely fashion, we assume the
118      * receiver has somehow wedged and we trigger an ANR.
119      */
120     @GuardedBy("mService")
finishReceiverLocked(@onNull ProcessRecord app, int resultCode, @Nullable String resultData, @Nullable Bundle resultExtras, boolean resultAbort, boolean waitForServices)121     public abstract boolean finishReceiverLocked(@NonNull ProcessRecord app, int resultCode,
122             @Nullable String resultData, @Nullable Bundle resultExtras, boolean resultAbort,
123             boolean waitForServices);
124 
125     /**
126      * Signal from OS internals that the given process has just been actively
127      * attached, and is ready to begin receiving broadcasts.
128      *
129      * @return if the queue performed an action on the given process, such as
130      *         dispatching a pending broadcast
131      */
132     @GuardedBy("mService")
onApplicationAttachedLocked(@onNull ProcessRecord app)133     public abstract boolean onApplicationAttachedLocked(@NonNull ProcessRecord app)
134             throws BroadcastDeliveryFailedException;
135 
136     /**
137      * Signal from OS internals that the given process has timed out during
138      * an attempted start and attachment.
139      */
140     @GuardedBy("mService")
onApplicationTimeoutLocked(@onNull ProcessRecord app)141     public abstract void onApplicationTimeoutLocked(@NonNull ProcessRecord app);
142 
143     /**
144      * Signal from OS internals that the given process, which had already been
145      * previously attached, has now encountered a problem such as crashing or
146      * not responding.
147      */
148     @GuardedBy("mService")
onApplicationProblemLocked(@onNull ProcessRecord app)149     public abstract void onApplicationProblemLocked(@NonNull ProcessRecord app);
150 
151     /**
152      * Signal from OS internals that the given process has been killed, and is
153      * no longer actively running.
154      */
155     @GuardedBy("mService")
onApplicationCleanupLocked(@onNull ProcessRecord app)156     public abstract void onApplicationCleanupLocked(@NonNull ProcessRecord app);
157 
158     /**
159      * Signal from OS internals that the given process is in a freezable state and will be
160      * frozen soon after.
161      */
162     @GuardedBy("mService")
onProcessFreezableChangedLocked(@onNull ProcessRecord app)163     public abstract void onProcessFreezableChangedLocked(@NonNull ProcessRecord app);
164 
165     /**
166      * Signal from OS internals that the given package (or some subset of that
167      * package) has been disabled or uninstalled, and that any pending
168      * broadcasts should be cleaned up.
169      */
170     @GuardedBy("mService")
cleanupDisabledPackageReceiversLocked(@ullable String packageName, @Nullable Set<String> filterByClasses, int userId)171     public abstract boolean cleanupDisabledPackageReceiversLocked(@Nullable String packageName,
172             @Nullable Set<String> filterByClasses, int userId);
173 
174     /**
175      * Quickly determine if this queue has broadcasts that are still waiting to
176      * be delivered at some point in the future.
177      *
178      * @see #waitForIdle
179      * @see #waitForBarrier
180      */
181     @GuardedBy("mService")
isIdleLocked()182     public abstract boolean isIdleLocked();
183 
184     /**
185      * Quickly determine if this queue has non-deferred broadcasts enqueued before the given
186      * barrier timestamp that are still waiting to be delivered.
187      *
188      * @see #waitForIdle
189      * @see #waitForBarrier
190      */
191     @GuardedBy("mService")
isBeyondBarrierLocked(@ptimeMillisLong long barrierTime)192     public abstract boolean isBeyondBarrierLocked(@UptimeMillisLong long barrierTime);
193 
194     /**
195      * Quickly determine if this queue has non-deferred broadcasts waiting to be dispatched,
196      * that match {@code intent}, as defined by {@link Intent#filterEquals(Intent)}.
197      *
198      * @see #waitForDispatched(Intent, PrintWriter)
199      */
200     @GuardedBy("mService")
isDispatchedLocked(@onNull Intent intent)201     public abstract boolean isDispatchedLocked(@NonNull Intent intent);
202 
203     /**
204      * Wait until this queue becomes completely idle.
205      * <p>
206      * Any broadcasts waiting to be delivered at some point in the future will
207      * be dispatched as quickly as possible.
208      * <p>
209      * Callers are cautioned that the queue may take a long time to go idle,
210      * since running apps can continue sending new broadcasts in perpetuity;
211      * consider using {@link #waitForBarrier} instead.
212      */
waitForIdle(@onNull PrintWriter pw)213     public abstract void waitForIdle(@NonNull PrintWriter pw);
214 
215     /**
216      * Wait until any currently waiting non-deferred broadcasts have been dispatched.
217      * <p>
218      * Any broadcasts waiting to be delivered at some point in the future will
219      * be dispatched as quickly as possible.
220      * <p>
221      * Callers are advised that this method will <em>not</em> wait for any
222      * future broadcasts that are newly enqueued after being invoked.
223      */
waitForBarrier(@onNull PrintWriter pw)224     public abstract void waitForBarrier(@NonNull PrintWriter pw);
225 
226     /**
227      * Wait until all non-deferred broadcasts matching {@code intent}, as defined by
228      * {@link Intent#filterEquals(Intent)}, have been dispatched.
229      * <p>
230      * Any broadcasts waiting to be delivered at some point in the future will
231      * be dispatched as quickly as possible.
232      */
waitForDispatched(@onNull Intent intent, @NonNull PrintWriter pw)233     public abstract void waitForDispatched(@NonNull Intent intent, @NonNull PrintWriter pw);
234 
235     /**
236      * Delays delivering broadcasts to the specified package.
237      */
forceDelayBroadcastDelivery(@onNull String targetPackage, long delayedDurationMs)238     public void forceDelayBroadcastDelivery(@NonNull String targetPackage,
239             long delayedDurationMs) {
240         // No default implementation.
241     }
242 
243     /**
244      * Brief summary of internal state, useful for debugging purposes.
245      */
246     @GuardedBy("mService")
describeStateLocked()247     public abstract @NonNull String describeStateLocked();
248 
249     @GuardedBy("mService")
dumpDebug(@onNull ProtoOutputStream proto, long fieldId)250     public abstract void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId);
251 
252     @GuardedBy("mService")
dumpLocked(@onNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args, int opti, boolean dumpConstants, boolean dumpHistory, boolean dumpAll, @Nullable String dumpPackage, @Nullable String dumpIntentAction, boolean needSep)253     public abstract boolean dumpLocked(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
254             @NonNull String[] args, int opti, boolean dumpConstants, boolean dumpHistory,
255             boolean dumpAll, @Nullable String dumpPackage, @Nullable String dumpIntentAction,
256             boolean needSep);
257 
258     /**
259      * Execute {@link #dumpLocked} and store the output into
260      * {@link DropBoxManager} for later inspection.
261      */
dumpToDropBoxLocked(@ullable String msg)262     public void dumpToDropBoxLocked(@Nullable String msg) {
263         LocalServices.getService(DropBoxManagerInternal.class).addEntry(TAG_DUMP, (fd) -> {
264             try (FileOutputStream out = new FileOutputStream(fd);
265                     PrintWriter pw = new PrintWriter(out)) {
266                 pw.print("Message: ");
267                 pw.println(msg);
268                 dumpLocked(fd, pw, null, 0, false, false, false, null, null, false);
269                 pw.flush();
270             }
271         }, DropBoxManager.IS_TEXT);
272     }
273 }
274