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