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 final @NonNull String mQueueName; 53 BroadcastQueue(@onNull ActivityManagerService service, @NonNull Handler handler, @NonNull String name, @NonNull BroadcastSkipPolicy skipPolicy, @NonNull BroadcastHistory history)54 BroadcastQueue(@NonNull ActivityManagerService service, @NonNull Handler handler, 55 @NonNull String name, @NonNull BroadcastSkipPolicy skipPolicy, 56 @NonNull BroadcastHistory history) { 57 mService = Objects.requireNonNull(service); 58 mHandler = Objects.requireNonNull(handler); 59 mQueueName = Objects.requireNonNull(name); 60 mSkipPolicy = Objects.requireNonNull(skipPolicy); 61 mHistory = Objects.requireNonNull(history); 62 } 63 logw(@onNull String msg)64 static void logw(@NonNull String msg) { 65 Slog.w(TAG, msg); 66 } 67 logv(@onNull String msg)68 static void logv(@NonNull String msg) { 69 Slog.v(TAG, msg); 70 } 71 checkState(boolean expression, @NonNull String msg)72 static void checkState(boolean expression, @NonNull String msg) { 73 if (!expression) { 74 throw new IllegalStateException(msg); 75 } 76 } 77 checkStateWtf(boolean expression, @NonNull String msg)78 static void checkStateWtf(boolean expression, @NonNull String msg) { 79 if (!expression) { 80 Slog.wtf(TAG, new IllegalStateException(msg)); 81 } 82 } 83 traceBegin(@onNull String methodName)84 static int traceBegin(@NonNull String methodName) { 85 final int cookie = methodName.hashCode(); 86 Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 87 TAG, methodName, cookie); 88 return cookie; 89 } 90 traceEnd(int cookie)91 static void traceEnd(int cookie) { 92 Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, 93 TAG, cookie); 94 } 95 96 @Override toString()97 public String toString() { 98 return mQueueName; 99 } 100 start(@onNull ContentResolver resolver)101 public abstract void start(@NonNull ContentResolver resolver); 102 isDelayBehindServices()103 public abstract boolean isDelayBehindServices(); 104 105 /** 106 * Return the preferred scheduling group for the given process, typically 107 * influenced by a broadcast being actively dispatched. 108 * 109 * @return scheduling group such as {@link ProcessList#SCHED_GROUP_DEFAULT}, 110 * otherwise {@link ProcessList#SCHED_GROUP_UNDEFINED} if this queue 111 * has no opinion. 112 */ 113 @GuardedBy("mService") getPreferredSchedulingGroupLocked(@onNull ProcessRecord app)114 public abstract int getPreferredSchedulingGroupLocked(@NonNull ProcessRecord app); 115 116 /** 117 * Enqueue the given broadcast to be eventually dispatched. 118 * <p> 119 * Callers must populate {@link BroadcastRecord#receivers} with the relevant 120 * targets before invoking this method. 121 * <p> 122 * When {@link Intent#FLAG_RECEIVER_REPLACE_PENDING} is set, this method 123 * internally handles replacement of any matching broadcasts. 124 */ 125 @GuardedBy("mService") enqueueBroadcastLocked(@onNull BroadcastRecord r)126 public abstract void enqueueBroadcastLocked(@NonNull BroadcastRecord r); 127 128 /** 129 * Signal delivered back from the given process to indicate that it's 130 * finished processing the current broadcast being dispatched to it. 131 * <p> 132 * If this signal isn't delivered back in a timely fashion, we assume the 133 * receiver has somehow wedged and we trigger an ANR. 134 */ 135 @GuardedBy("mService") finishReceiverLocked(@onNull ProcessRecord app, int resultCode, @Nullable String resultData, @Nullable Bundle resultExtras, boolean resultAbort, boolean waitForServices)136 public abstract boolean finishReceiverLocked(@NonNull ProcessRecord app, int resultCode, 137 @Nullable String resultData, @Nullable Bundle resultExtras, boolean resultAbort, 138 boolean waitForServices); 139 140 @GuardedBy("mService") backgroundServicesFinishedLocked(int userId)141 public abstract void backgroundServicesFinishedLocked(int userId); 142 143 /** 144 * Signal from OS internals that the given process has just been actively 145 * attached, and is ready to begin receiving broadcasts. 146 * 147 * @return if the queue performed an action on the given process, such as 148 * dispatching a pending broadcast 149 */ 150 @GuardedBy("mService") onApplicationAttachedLocked(@onNull ProcessRecord app)151 public abstract boolean onApplicationAttachedLocked(@NonNull ProcessRecord app) 152 throws BroadcastDeliveryFailedException; 153 154 /** 155 * Signal from OS internals that the given process has timed out during 156 * an attempted start and attachment. 157 */ 158 @GuardedBy("mService") onApplicationTimeoutLocked(@onNull ProcessRecord app)159 public abstract void onApplicationTimeoutLocked(@NonNull ProcessRecord app); 160 161 /** 162 * Signal from OS internals that the given process, which had already been 163 * previously attached, has now encountered a problem such as crashing or 164 * not responding. 165 */ 166 @GuardedBy("mService") onApplicationProblemLocked(@onNull ProcessRecord app)167 public abstract void onApplicationProblemLocked(@NonNull ProcessRecord app); 168 169 /** 170 * Signal from OS internals that the given process has been killed, and is 171 * no longer actively running. 172 */ 173 @GuardedBy("mService") onApplicationCleanupLocked(@onNull ProcessRecord app)174 public abstract void onApplicationCleanupLocked(@NonNull ProcessRecord app); 175 176 /** 177 * Signal from OS internals that the given process is in a freezable state and will be 178 * frozen soon after. 179 */ 180 @GuardedBy("mService") onProcessFreezableChangedLocked(@onNull ProcessRecord app)181 public abstract void onProcessFreezableChangedLocked(@NonNull ProcessRecord app); 182 183 /** 184 * Signal from OS internals that the given package (or some subset of that 185 * package) has been disabled or uninstalled, and that any pending 186 * broadcasts should be cleaned up. 187 */ 188 @GuardedBy("mService") cleanupDisabledPackageReceiversLocked(@ullable String packageName, @Nullable Set<String> filterByClasses, int userId)189 public abstract boolean cleanupDisabledPackageReceiversLocked(@Nullable String packageName, 190 @Nullable Set<String> filterByClasses, int userId); 191 192 /** 193 * Quickly determine if this queue has broadcasts that are still waiting to 194 * be delivered at some point in the future. 195 * 196 * @see #waitForIdle 197 * @see #waitForBarrier 198 */ 199 @GuardedBy("mService") isIdleLocked()200 public abstract boolean isIdleLocked(); 201 202 /** 203 * Quickly determine if this queue has non-deferred broadcasts enqueued before the given 204 * barrier timestamp that are still waiting to be delivered. 205 * 206 * @see #waitForIdle 207 * @see #waitForBarrier 208 */ 209 @GuardedBy("mService") isBeyondBarrierLocked(@ptimeMillisLong long barrierTime)210 public abstract boolean isBeyondBarrierLocked(@UptimeMillisLong long barrierTime); 211 212 /** 213 * Quickly determine if this queue has non-deferred broadcasts waiting to be dispatched, 214 * that match {@code intent}, as defined by {@link Intent#filterEquals(Intent)}. 215 * 216 * @see #waitForDispatched(Intent, PrintWriter) 217 */ 218 @GuardedBy("mService") isDispatchedLocked(@onNull Intent intent)219 public abstract boolean isDispatchedLocked(@NonNull Intent intent); 220 221 /** 222 * Wait until this queue becomes completely idle. 223 * <p> 224 * Any broadcasts waiting to be delivered at some point in the future will 225 * be dispatched as quickly as possible. 226 * <p> 227 * Callers are cautioned that the queue may take a long time to go idle, 228 * since running apps can continue sending new broadcasts in perpetuity; 229 * consider using {@link #waitForBarrier} instead. 230 */ waitForIdle(@onNull PrintWriter pw)231 public abstract void waitForIdle(@NonNull PrintWriter pw); 232 233 /** 234 * Wait until any currently waiting non-deferred broadcasts have been dispatched. 235 * <p> 236 * Any broadcasts waiting to be delivered at some point in the future will 237 * be dispatched as quickly as possible. 238 * <p> 239 * Callers are advised that this method will <em>not</em> wait for any 240 * future broadcasts that are newly enqueued after being invoked. 241 */ waitForBarrier(@onNull PrintWriter pw)242 public abstract void waitForBarrier(@NonNull PrintWriter pw); 243 244 /** 245 * Wait until all non-deferred broadcasts matching {@code intent}, as defined by 246 * {@link Intent#filterEquals(Intent)}, have been dispatched. 247 * <p> 248 * Any broadcasts waiting to be delivered at some point in the future will 249 * be dispatched as quickly as possible. 250 */ waitForDispatched(@onNull Intent intent, @NonNull PrintWriter pw)251 public abstract void waitForDispatched(@NonNull Intent intent, @NonNull PrintWriter pw); 252 253 /** 254 * Delays delivering broadcasts to the specified package. 255 * 256 * <p> Note that this is only valid for modern queue. 257 */ forceDelayBroadcastDelivery(@onNull String targetPackage, long delayedDurationMs)258 public void forceDelayBroadcastDelivery(@NonNull String targetPackage, 259 long delayedDurationMs) { 260 // No default implementation. 261 } 262 263 /** 264 * Brief summary of internal state, useful for debugging purposes. 265 */ 266 @GuardedBy("mService") describeStateLocked()267 public abstract @NonNull String describeStateLocked(); 268 269 @GuardedBy("mService") dumpDebug(@onNull ProtoOutputStream proto, long fieldId)270 public abstract void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId); 271 272 @GuardedBy("mService") dumpLocked(@onNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args, int opti, boolean dumpConstants, boolean dumpHistory, boolean dumpAll, @Nullable String dumpPackage, boolean needSep)273 public abstract boolean dumpLocked(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, 274 @NonNull String[] args, int opti, boolean dumpConstants, boolean dumpHistory, 275 boolean dumpAll, @Nullable String dumpPackage, boolean needSep); 276 277 /** 278 * Execute {@link #dumpLocked} and store the output into 279 * {@link DropBoxManager} for later inspection. 280 */ dumpToDropBoxLocked(@ullable String msg)281 public void dumpToDropBoxLocked(@Nullable String msg) { 282 LocalServices.getService(DropBoxManagerInternal.class).addEntry(TAG_DUMP, (fd) -> { 283 try (FileOutputStream out = new FileOutputStream(fd); 284 PrintWriter pw = new PrintWriter(out)) { 285 pw.print("Message: "); 286 pw.println(msg); 287 dumpLocked(fd, pw, null, 0, false, false, false, null, false); 288 pw.flush(); 289 } 290 }, DropBoxManager.IS_TEXT); 291 } 292 } 293